Skip to content

Commit 9f717a9

Browse files
committed
Merge branch 'master' into milestone_0.1.5
2 parents 0578645 + 0a43050 commit 9f717a9

6 files changed

Lines changed: 199 additions & 2 deletions

File tree

sqlparse/engine/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def _group(stream):
6161
def _run1(stream):
6262
ret = []
6363
for stmt in stream:
64+
for i in stmt.flatten():
65+
print repr(i)
6466
for filter_ in self.stmtprocess:
6567
filter_.process(self, stmt)
6668
ret.append(stmt)

sqlparse/filters.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from sqlparse import sql, tokens as T
99
from sqlparse.engine import FilterStack
10+
from sqlparse.lexer import tokenize
11+
from sqlparse.pipeline import Pipeline
1012
from sqlparse.tokens import (Comment, Comparison, Keyword, Name, Punctuation,
1113
String, Whitespace)
1214
from sqlparse.utils import memoize_generator
@@ -687,3 +689,15 @@ def process(self, stack, stream):
687689
return stream[4 - index][1]
688690

689691
return -1
692+
693+
694+
def Compact(sql, includePath="sql"):
695+
"""Function that return a compacted version of the input SQL query"""
696+
pipe = Pipeline()
697+
698+
pipe.append(tokenize)
699+
pipe.append(IncludeStatement(includePath))
700+
pipe.append(StripComments())
701+
pipe.append(StripWhitespace)
702+
703+
return pipe(sql)

sqlparse/functions.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'''
2+
Created on 17/05/2012
3+
4+
@author: piranna
5+
6+
Several utility functions to extract info from the SQL sentences
7+
'''
8+
9+
from sqlparse.filters import ColumnsSelect, Limit
10+
from sqlparse.pipeline import Pipeline
11+
from sqlparse.tokens import Keyword, Whitespace
12+
13+
14+
def getlimit(stream):
15+
"""Function that return the LIMIT of a input SQL """
16+
pipe = Pipeline()
17+
18+
pipe.append(Limit())
19+
20+
result = pipe(stream)
21+
try:
22+
return int(result)
23+
except ValueError:
24+
return result
25+
26+
27+
def getcolumns(stream):
28+
"""Function that return the colums of a SELECT query"""
29+
pipe = Pipeline()
30+
31+
pipe.append(ColumnsSelect())
32+
33+
return pipe(stream)
34+
35+
36+
class IsType():
37+
"""Functor that return is the statement is of a specific type"""
38+
def __init__(self, type):
39+
self.type = type
40+
41+
def __call__(self, stream):
42+
for token_type, value in stream:
43+
if token_type not in Whitespace:
44+
return token_type in Keyword and value == self.type

sqlparse/sql.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ def flatten(self):
181181
else:
182182
yield token
183183

184+
# def __iter__(self):
185+
# return self
186+
#
187+
# def next(self):
188+
# for token in self.tokens:
189+
# yield token
190+
184191
def is_group(self):
185192
return True
186193

@@ -255,7 +262,7 @@ def token_not_matching(self, idx, funcs):
255262

256263
def token_matching(self, idx, funcs):
257264
for token in self.tokens[idx:]:
258-
for i, func in enumerate(funcs):
265+
for func in funcs:
259266
if func(token):
260267
return token
261268

sqlparse/utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ def memoize_generator(func):
1616
cache = {}
1717

1818
def wrapped_func(*args, **kwargs):
19-
params = (args, kwargs)
19+
# params = (args, kwargs)
20+
params = (args, tuple(sorted(kwargs.items())))
2021

2122
# Look if cached
2223
try:
24+
print params
2325
cached = cache[params]
2426

2527
# Not cached, exec and store it

tests/test_functions.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
'''
2+
Created on 13/02/2012
3+
4+
@author: piranna
5+
'''
6+
from unittest import main, TestCase
7+
8+
from sqlparse.filters import Tokens2Unicode
9+
from sqlparse.lexer import tokenize
10+
11+
import sys
12+
sys.path.insert(0, '..')
13+
14+
from sqlparse.filters import Compact
15+
from sqlparse.functions import getcolumns, getlimit, IsType
16+
17+
18+
class Test_SQL(TestCase):
19+
sql = """-- type: script
20+
-- return: integer
21+
22+
INCLUDE "_Make_DirEntry.sql";
23+
24+
INSERT INTO directories(inode)
25+
VALUES(:inode)
26+
LIMIT 1"""
27+
28+
sql2 = """SELECT child_entry,asdf AS inode, creation
29+
FROM links
30+
WHERE parent_dir == :parent_dir AND name == :name
31+
LIMIT 1"""
32+
33+
sql3 = """SELECT
34+
0 AS st_dev,
35+
0 AS st_uid,
36+
0 AS st_gid,
37+
38+
dir_entries.type AS st_mode,
39+
dir_entries.inode AS st_ino,
40+
COUNT(links.child_entry) AS st_nlink,
41+
42+
:creation AS st_ctime,
43+
dir_entries.access AS st_atime,
44+
dir_entries.modification AS st_mtime,
45+
-- :creation AS st_ctime,
46+
-- CAST(STRFTIME('%s',dir_entries.access) AS INTEGER) AS st_atime,
47+
-- CAST(STRFTIME('%s',dir_entries.modification) AS INTEGER) AS st_mtime,
48+
49+
COALESCE(files.size,0) AS st_size, -- Python-FUSE
50+
COALESCE(files.size,0) AS size -- PyFilesystem
51+
52+
FROM dir_entries
53+
LEFT JOIN files
54+
ON dir_entries.inode == files.inode
55+
LEFT JOIN links
56+
ON dir_entries.inode == links.child_entry
57+
58+
WHERE dir_entries.inode == :inode
59+
60+
GROUP BY dir_entries.inode
61+
LIMIT 1"""
62+
63+
64+
class Test_Compact(Test_SQL):
65+
def test_compact1(self):
66+
self.assertEqual(Tokens2Unicode(Compact(self.sql, 'tests/files')),
67+
'INSERT INTO dir_entries(type)VALUES(:type);INSERT INTO '
68+
'directories(inode)VALUES(:inode)LIMIT 1')
69+
70+
def test_compact2(self):
71+
self.assertEqual(Tokens2Unicode(Compact(self.sql2)),
72+
'SELECT child_entry,asdf AS inode,creation FROM links WHERE '
73+
'parent_dir==:parent_dir AND name==:name LIMIT 1')
74+
75+
def test_compact3(self):
76+
self.assertEqual(Tokens2Unicode(Compact(self.sql3)),
77+
'SELECT 0 AS st_dev,0 AS st_uid,0 AS st_gid,dir_entries.type AS '
78+
'st_mode,dir_entries.inode AS st_ino,COUNT(links.child_entry)AS '
79+
'st_nlink,:creation AS st_ctime,dir_entries.access AS st_atime,'
80+
'dir_entries.modification AS st_mtime,COALESCE(files.size,0)AS '
81+
'st_size,COALESCE(files.size,0)AS size FROM dir_entries LEFT JOIN'
82+
' files ON dir_entries.inode==files.inode LEFT JOIN links ON '
83+
'dir_entries.inode==links.child_entry WHERE dir_entries.inode=='
84+
':inode GROUP BY dir_entries.inode LIMIT 1')
85+
86+
87+
class Test_GetColumns(Test_SQL):
88+
def test_getcolumns1(self):
89+
columns = getcolumns(tokenize(self.sql))
90+
self.assertEqual(columns, [])
91+
92+
def test_getcolumns2(self):
93+
columns = getcolumns(tokenize(self.sql2))
94+
self.assertEqual(columns, ['child_entry', 'inode', 'creation'])
95+
96+
def test_getcolumns3(self):
97+
columns = getcolumns(tokenize(self.sql3))
98+
self.assertEqual(columns, ['st_dev', 'st_uid', 'st_gid', 'st_mode',
99+
'st_ino', 'st_nlink', 'st_ctime',
100+
'st_atime', 'st_mtime', 'st_size', 'size'])
101+
102+
103+
class Test_GetLimit(Test_SQL):
104+
def test_getlimit1(self):
105+
limit = getlimit(tokenize(self.sql))
106+
self.assertEqual(limit, 1)
107+
108+
def test_getlimit2(self):
109+
limit = getlimit(tokenize(self.sql2))
110+
self.assertEqual(limit, 1)
111+
112+
def test_getlimit3(self):
113+
limit = getlimit(tokenize(self.sql3))
114+
self.assertEqual(limit, 1)
115+
116+
117+
class Test_IsType(Test_SQL):
118+
def test_istype2(self):
119+
stream = tokenize(self.sql2)
120+
self.assertTrue(IsType('SELECT')(stream))
121+
122+
stream = tokenize(self.sql2)
123+
self.assertFalse(IsType('INSERT')(stream))
124+
125+
126+
if __name__ == "__main__":
127+
#import sys;sys.argv = ['', 'Test.testName']
128+
main()

0 commit comments

Comments
 (0)