From 73465819c9d5105f57a9cf5579c5dc78964b37e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22Piranna=22?= Date: Thu, 17 May 2012 23:11:05 +0200 Subject: Added functions from AntiORM --- sqlparse/functions.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 sqlparse/functions.py diff --git a/sqlparse/functions.py b/sqlparse/functions.py new file mode 100644 index 0000000..693fe6a --- /dev/null +++ b/sqlparse/functions.py @@ -0,0 +1,44 @@ +''' +Created on 17/05/2012 + +@author: piranna + +Several utility functions to extract info from the SQL sentences +''' + +from sqlparse.filters import ColumnsSelect, Limit +from sqlparse.pipeline import Pipeline +from sqlparse.tokens import Keyword, Whitespace + + +def GetLimit(stream): + """Function that return the LIMIT of a input SQL """ + pipe = Pipeline() + + pipe.append(Limit()) + + result = pipe(stream) + try: + return int(result) + except ValueError: + return result + + +def GetColumns(stream): + """Function that return the colums of a SELECT query""" + pipe = Pipeline() + + pipe.append(ColumnsSelect()) + + return pipe(stream) + + +class IsType(): + """Functor that return is the statement is of a specific type""" + def __init__(self, type): + self.type = type + + def __call__(self, stream): + for token_type, value in stream: + if token_type in Whitespace: continue + return token_type in Keyword and value == self.type -- cgit v1.2.1 From 4a41241e8fc084d25cde943263ea507509f9ead4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22Piranna=22?= Date: Thu, 17 May 2012 23:18:05 +0200 Subject: Added tests for functions --- sqlparse/functions.py | 4 +- tests/test_functions.py | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tests/test_functions.py diff --git a/sqlparse/functions.py b/sqlparse/functions.py index 693fe6a..25dc005 100644 --- a/sqlparse/functions.py +++ b/sqlparse/functions.py @@ -40,5 +40,5 @@ class IsType(): def __call__(self, stream): for token_type, value in stream: - if token_type in Whitespace: continue - return token_type in Keyword and value == self.type + if token_type not in Whitespace: + return token_type in Keyword and value == self.type diff --git a/tests/test_functions.py b/tests/test_functions.py new file mode 100644 index 0000000..73865a2 --- /dev/null +++ b/tests/test_functions.py @@ -0,0 +1,103 @@ +''' +Created on 13/02/2012 + +@author: piranna +''' +from unittest import main, TestCase + +from sqlparse.lexer import tokenize + +import sys +sys.path.insert(0, '..') + +from sqlparse.functions import GetColumns, GetLimit, IsType + + +class Test_SQL(TestCase): + sql = """-- type: script + -- return: integer + + INCLUDE "_Make_DirEntry.sql"; + + INSERT INTO directories(inode) + VALUES(:inode) + LIMIT 1""" + + sql2 = """SELECT child_entry,asdf AS inode, creation + FROM links + WHERE parent_dir == :parent_dir AND name == :name + LIMIT 1""" + + sql3 = """SELECT + 0 AS st_dev, + 0 AS st_uid, + 0 AS st_gid, + + dir_entries.type AS st_mode, + dir_entries.inode AS st_ino, + COUNT(links.child_entry) AS st_nlink, + + :creation AS st_ctime, + dir_entries.access AS st_atime, + dir_entries.modification AS st_mtime, +-- :creation AS st_ctime, +-- CAST(STRFTIME('%s',dir_entries.access) AS INTEGER) AS st_atime, +-- CAST(STRFTIME('%s',dir_entries.modification) AS INTEGER) AS st_mtime, + + COALESCE(files.size,0) AS st_size, -- Python-FUSE + COALESCE(files.size,0) AS size -- PyFilesystem + +FROM dir_entries + LEFT JOIN files + ON dir_entries.inode == files.inode + LEFT JOIN links + ON dir_entries.inode == links.child_entry + +WHERE dir_entries.inode == :inode + +GROUP BY dir_entries.inode +LIMIT 1""" + + +class Test_GetColumns(Test_SQL): + def test_getcolumns1(self): + columns = GetColumns(tokenize(self.sql)) + self.assertEqual(columns, []) + + def test_getcolumns2(self): + columns = GetColumns(tokenize(self.sql2)) + self.assertEqual(columns, ['child_entry', 'inode', 'creation']) + + def test_getcolumns3(self): + columns = GetColumns(tokenize(self.sql3)) + self.assertEqual(columns, ['st_dev', 'st_uid', 'st_gid', 'st_mode', + 'st_ino', 'st_nlink', 'st_ctime', + 'st_atime', 'st_mtime', 'st_size', 'size']) + + +class Test_GetLimit(Test_SQL): + def test_getlimit1(self): + limit = GetLimit(tokenize(self.sql)) + self.assertEqual(limit, 1) + + def test_getlimit2(self): + limit = GetLimit(tokenize(self.sql2)) + self.assertEqual(limit, 1) + + def test_getlimit3(self): + limit = GetLimit(tokenize(self.sql3)) + self.assertEqual(limit, 1) + + +class Test_IsType(Test_SQL): + def test_istype2(self): + stream = tokenize(self.sql2) + self.assertTrue(IsType('SELECT')(stream)) + + stream = tokenize(self.sql2) + self.assertFalse(IsType('INSERT')(stream)) + + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + main() -- cgit v1.2.1 From de8f502cbd54fdac1b91042d414dd99502b5c02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22Piranna=22?= Date: Thu, 17 May 2012 23:24:54 +0200 Subject: Added compact filter and tests --- sqlparse/filters.py | 24 +++++++++++++++++++----- tests/test_functions.py | 27 ++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/sqlparse/filters.py b/sqlparse/filters.py index 291a613..cc6145a 100644 --- a/sqlparse/filters.py +++ b/sqlparse/filters.py @@ -4,11 +4,13 @@ import re from os.path import abspath, join -from sqlparse import sql -from sqlparse import tokens as T -from sqlparse.engine import FilterStack -from sqlparse.tokens import (Comment, Comparison, Keyword, Name, Punctuation, - String, Whitespace) +from sqlparse import sql +from sqlparse import tokens as T +from sqlparse.engine import FilterStack +from sqlparse.lexer import tokenize +from sqlparse.pipeline import Pipeline +from sqlparse.tokens import (Comment, Comparison, Keyword, Name, Punctuation, + String, Whitespace) # -------------------------- @@ -624,3 +626,15 @@ class Limit: return stream[4 - index][1] return -1 + + +def Compact(sql, includePath="sql"): + """Function that return a compacted version of the input SQL query""" + pipe = Pipeline() + + pipe.append(tokenize) + pipe.append(IncludeStatement(includePath)) + pipe.append(StripComments()) + pipe.append(StripWhitespace) + + return pipe(sql) diff --git a/tests/test_functions.py b/tests/test_functions.py index 73865a2..f522b35 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -5,11 +5,13 @@ Created on 13/02/2012 ''' from unittest import main, TestCase -from sqlparse.lexer import tokenize +from sqlparse.filters import Tokens2Unicode +from sqlparse.lexer import tokenize import sys sys.path.insert(0, '..') +from sqlparse.filters import Compact from sqlparse.functions import GetColumns, GetLimit, IsType @@ -59,6 +61,29 @@ GROUP BY dir_entries.inode LIMIT 1""" +class Test_Compact(Test_SQL): + def test_compact1(self): + self.assertEqual(Tokens2Unicode(Compact(self.sql, 'tests/files')), + 'INSERT INTO dir_entries(type)VALUES(:type);INSERT INTO ' + 'directories(inode)VALUES(:inode)LIMIT 1') + + def test_compact2(self): + self.assertEqual(Tokens2Unicode(Compact(self.sql2)), + 'SELECT child_entry,asdf AS inode,creation FROM links WHERE ' + 'parent_dir==:parent_dir AND name==:name LIMIT 1') + + def test_compact3(self): + self.assertEqual(Tokens2Unicode(Compact(self.sql3)), + 'SELECT 0 AS st_dev,0 AS st_uid,0 AS st_gid,dir_entries.type AS ' + 'st_mode,dir_entries.inode AS st_ino,COUNT(links.child_entry)AS ' + 'st_nlink,:creation AS st_ctime,dir_entries.access AS st_atime,' + 'dir_entries.modification AS st_mtime,COALESCE(files.size,0)AS ' + 'st_size,COALESCE(files.size,0)AS size FROM dir_entries LEFT JOIN' + ' files ON dir_entries.inode==files.inode LEFT JOIN links ON ' + 'dir_entries.inode==links.child_entry WHERE dir_entries.inode==' + ':inode GROUP BY dir_entries.inode LIMIT 1') + + class Test_GetColumns(Test_SQL): def test_getcolumns1(self): columns = GetColumns(tokenize(self.sql)) -- cgit v1.2.1 From 8bd03f158343bd2b83802c1059e15953c72f9f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22Piranna=22?= Date: Sat, 19 May 2012 19:28:18 +0200 Subject: Fixed comments by Andi --- sqlparse/functions.py | 4 ++-- tests/test_functions.py | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sqlparse/functions.py b/sqlparse/functions.py index 25dc005..aaf6fb8 100644 --- a/sqlparse/functions.py +++ b/sqlparse/functions.py @@ -11,7 +11,7 @@ from sqlparse.pipeline import Pipeline from sqlparse.tokens import Keyword, Whitespace -def GetLimit(stream): +def getlimit(stream): """Function that return the LIMIT of a input SQL """ pipe = Pipeline() @@ -24,7 +24,7 @@ def GetLimit(stream): return result -def GetColumns(stream): +def getcolumns(stream): """Function that return the colums of a SELECT query""" pipe = Pipeline() diff --git a/tests/test_functions.py b/tests/test_functions.py index f522b35..1a7ec18 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -12,7 +12,7 @@ import sys sys.path.insert(0, '..') from sqlparse.filters import Compact -from sqlparse.functions import GetColumns, GetLimit, IsType +from sqlparse.functions import getcolumns, getlimit, IsType class Test_SQL(TestCase): @@ -86,15 +86,15 @@ class Test_Compact(Test_SQL): class Test_GetColumns(Test_SQL): def test_getcolumns1(self): - columns = GetColumns(tokenize(self.sql)) + columns = getcolumns(tokenize(self.sql)) self.assertEqual(columns, []) def test_getcolumns2(self): - columns = GetColumns(tokenize(self.sql2)) + columns = getcolumns(tokenize(self.sql2)) self.assertEqual(columns, ['child_entry', 'inode', 'creation']) def test_getcolumns3(self): - columns = GetColumns(tokenize(self.sql3)) + columns = getcolumns(tokenize(self.sql3)) self.assertEqual(columns, ['st_dev', 'st_uid', 'st_gid', 'st_mode', 'st_ino', 'st_nlink', 'st_ctime', 'st_atime', 'st_mtime', 'st_size', 'size']) @@ -102,15 +102,15 @@ class Test_GetColumns(Test_SQL): class Test_GetLimit(Test_SQL): def test_getlimit1(self): - limit = GetLimit(tokenize(self.sql)) + limit = getlimit(tokenize(self.sql)) self.assertEqual(limit, 1) def test_getlimit2(self): - limit = GetLimit(tokenize(self.sql2)) + limit = getlimit(tokenize(self.sql2)) self.assertEqual(limit, 1) def test_getlimit3(self): - limit = GetLimit(tokenize(self.sql3)) + limit = getlimit(tokenize(self.sql3)) self.assertEqual(limit, 1) -- cgit v1.2.1 From 0a43050ab370a90f1036f37bf27b082e40419546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22Piranna=22?= Date: Sat, 19 May 2012 22:32:26 +0200 Subject: Fixed regression thanks to idea from functools.lru_cache() --- sqlparse/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sqlparse/utils.py b/sqlparse/utils.py index 443c64d..6321353 100644 --- a/sqlparse/utils.py +++ b/sqlparse/utils.py @@ -16,7 +16,8 @@ def memoize_generator(func): cache = {} def wrapped_func(*args, **kwargs): - params = (args, kwargs) +# params = (args, kwargs) + params = (args, tuple(sorted(kwargs.items()))) # Look if cached try: -- cgit v1.2.1