Skip to content

Commit dd17d07

Browse files
authored
Merge pull request #3 from ftrotter/ft_create
added create table function
2 parents 3366a72 + 8fffa42 commit dd17d07

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

doc_example.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
">>> new_query.j += Query.build_join('ex_db.dbo.new_tbl nt', 'tbl.id', 'nt.id',"
2828
" 'tbl.city', 'nt.city')",
2929
">>> new_query.join_type = '' # set back to regular join",
30+
">>> new_query.ci += 'thisDB.thatTable' # set back to regular join",
3031
">>> new_query",
3132
">>> new_query.statement",
3233
]

querpy.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
>>> new_query # should print full query
1414
"""
1515

16-
__author__ = 'Paul Garaud'
17-
__version__ = '0.1'
18-
__date__ = '2015-03-19'
16+
__author__ = 'Paul Garaud, Fred Trotter'
17+
__version__ = '0.2'
18+
__date__ = '2022-06-18'
1919

2020

2121
import re
@@ -27,9 +27,11 @@ class Query(object):
2727

2828
# These help with merging all of the statements into a single line
2929
whitespace_regex = re.compile('(^\s+|(?<=\s)\s+|\s+$)')
30-
where_clean_up = re.compile('(?<=WHERE )\s.*?AND|(?<=WHERE )\s.*?OR')
30+
#the design of the where list is such that every element of the list has an 'AND' or 'OR' as a prefix..
31+
#but the first one after the where does not need that.. so we just look for a WHERE OR or a WHERE AND and remove the 'OR' or 'AND'
32+
where_clean_up = re.compile('(?<=WHERE )\s.*?AND|(?<=WHERE )\s.*?OR')
3133

32-
# These help with the SQL pretty print implementation
34+
# All of these fmt_(something) help with the SQL pretty print implementation
3335
fmt = re.compile('\s(?=FROM)|\s(?=WHERE)|\s(?=GROUP BY)')
3436
fmt_after = re.compile(
3537
'(?<=SELECT)\s|(?<=FROM)\s|(?<=WHERE)\s|(?<=GROUP BY)\s'
@@ -49,6 +51,7 @@ class Query(object):
4951

5052

5153
def __init__(self):
54+
self.ci = CreateInsertComponent()
5255
self.s = SelectComponent()
5356
self.f = QueryComponent('FROM')
5457
self.j = JoinComponent()
@@ -58,7 +61,8 @@ def __init__(self):
5861
@property
5962
def statement(self):
6063
# Merges the various SQL componenets into a single SQL statement
61-
elements = [self.s(), self.f(), self.j(), self.w(), self.g()]
64+
print(self.ci())
65+
elements = [self.ci(), self.s(), self.f(), self.j(), self.w(), self.g()]
6266
full_statement = re.subn(self.where_clean_up, '', ' '.join(elements))[0] # removes messy contents of WHERE statements? Note sure why this is needed or why it is run on the whole SQL statement
6367
full_statement = re.subn(self.whitespace_regex, '', full_statement)[0] # flattens pretty print SQL to a single line by removing whitespace
6468
if full_statement:
@@ -100,7 +104,7 @@ def __str__(self):
100104
# This section could be better implemented using a call to sqlpars
101105
# https://github.com/andialbrecht/sqlparse
102106
# But doing it this way keeps the dependancies low, which is important
103-
query = self.statement # This is the single line query gotten from the statement function
107+
query = self.statement # This is the single line query gotten from the statement function
104108
query = re.subn(self.fmt, '\n ', query)[0]
105109
query = re.subn(self.fmt_after, '\n ', query)[0]
106110
query = re.subn(self.fmt_join, '\n ', query)[0]
@@ -146,8 +150,6 @@ def replace_and(match):
146150

147151

148152

149-
150-
151153
class QueryComponent(object):
152154
#This is the base class that everything else will be added to..
153155
# this is where the magic of += is handled, which makes it easy
@@ -179,6 +181,8 @@ def clear(self):
179181
self.components = list()
180182

181183
def __call__(self):
184+
# This is the function that converts the list of items in the querycomponent into a long string
185+
# it is always prefixed by the header..
182186
if self.components:
183187
return self.header + self.sep.join(self.components)
184188
return ''
@@ -197,6 +201,30 @@ def __str__(self):
197201

198202
__repr__ = __str__
199203

204+
class CreateInsertComponent(QueryComponent):
205+
# Implements the very first part of a CREATE TABLE db.table AS or INSERT INTO db.table
206+
# depending on whether the is_first_data_add setting has been set
207+
208+
209+
is_first_data_add = True
210+
211+
def __iadd__(self, item):
212+
#we only have the one item..
213+
self.components = list() # overwrites whatever was there
214+
if self.is_first_data_add:
215+
#Then this is a CREATE TABLE AS clause
216+
self.header = 'CREATE TABLE ' + item + " AS \n"
217+
else:
218+
self.header = 'INSERT INTO ' + item + " \n"
219+
return self
220+
221+
def __init__(self):
222+
self.header = '' # by default, this is not used.
223+
self.components = list()
224+
225+
def __call__(self):
226+
return self.header
227+
200228

201229
class SelectComponent(QueryComponent):
202230
# This models the SELECT component, and sends great energy ensuring that the "DISTINCT" and "TOP" syntax are supported

0 commit comments

Comments
 (0)