summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Albrecht <albrecht.andi@googlemail.com>2012-05-23 01:12:00 -0700
committerAndi Albrecht <albrecht.andi@googlemail.com>2012-05-23 01:12:00 -0700
commitf8c53645cff58a36357058af4ac52422a364d192 (patch)
tree7999011669f7dc6e3d04e1c536a9865fa4596828
parent66742da10ebdc2bc485022ecbd59278d3fc96488 (diff)
parent0a43050ab370a90f1036f37bf27b082e40419546 (diff)
downloadsqlparse-f8c53645cff58a36357058af4ac52422a364d192.tar.gz
Merge pull request #69 from piranna/antiorm
Antiorm
-rw-r--r--sqlparse/engine/__init__.py2
-rw-r--r--sqlparse/filters.py14
-rw-r--r--sqlparse/functions.py44
-rw-r--r--sqlparse/sql.py9
-rw-r--r--sqlparse/utils.py4
-rw-r--r--tests/test_functions.py128
6 files changed, 199 insertions, 2 deletions
diff --git a/sqlparse/engine/__init__.py b/sqlparse/engine/__init__.py
index 3e2822b..c30b6ca 100644
--- a/sqlparse/engine/__init__.py
+++ b/sqlparse/engine/__init__.py
@@ -61,6 +61,8 @@ class FilterStack(object):
def _run1(stream):
ret = []
for stmt in stream:
+ for i in stmt.flatten():
+ print repr(i)
for filter_ in self.stmtprocess:
filter_.process(self, stmt)
ret.append(stmt)
diff --git a/sqlparse/filters.py b/sqlparse/filters.py
index 08c1f69..ce5dd85 100644
--- a/sqlparse/filters.py
+++ b/sqlparse/filters.py
@@ -6,6 +6,8 @@ from os.path import abspath, join
from sqlparse import sql, 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)
from sqlparse.utils import memoize_generator
@@ -647,3 +649,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/sqlparse/functions.py b/sqlparse/functions.py
new file mode 100644
index 0000000..aaf6fb8
--- /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 not in Whitespace:
+ return token_type in Keyword and value == self.type
diff --git a/sqlparse/sql.py b/sqlparse/sql.py
index 05e078d..d18a0a7 100644
--- a/sqlparse/sql.py
+++ b/sqlparse/sql.py
@@ -181,6 +181,13 @@ class TokenList(Token):
else:
yield token
+# def __iter__(self):
+# return self
+#
+# def next(self):
+# for token in self.tokens:
+# yield token
+
def is_group(self):
return True
@@ -255,7 +262,7 @@ class TokenList(Token):
def token_matching(self, idx, funcs):
for token in self.tokens[idx:]:
- for i, func in enumerate(funcs):
+ for func in funcs:
if func(token):
return token
diff --git a/sqlparse/utils.py b/sqlparse/utils.py
index fd6651a..6321353 100644
--- a/sqlparse/utils.py
+++ b/sqlparse/utils.py
@@ -16,10 +16,12 @@ 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:
+ print params
cached = cache[params]
# Not cached, exec and store it
diff --git a/tests/test_functions.py b/tests/test_functions.py
new file mode 100644
index 0000000..1a7ec18
--- /dev/null
+++ b/tests/test_functions.py
@@ -0,0 +1,128 @@
+'''
+Created on 13/02/2012
+
+@author: piranna
+'''
+from unittest import main, TestCase
+
+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
+
+
+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_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))
+ 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()