summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Albrecht <albrecht.andi@gmail.com>2015-07-26 14:35:32 +0200
committerAndi Albrecht <albrecht.andi@gmail.com>2015-07-26 14:35:32 +0200
commit5df394485efbbbc5413b21b9efd6f039ff18fae1 (patch)
tree17a4cd907c79d5e7e75de7cf8c68dbb7dd9f1895
parentd463a753216b5c9e2c7f2b3c8a48fa76cbdb73c2 (diff)
parent8987a3a6b540ea35bbb1f9c5f49f3306501289cd (diff)
downloadsqlparse-v0.2.0.tar.gz
Merge branch 'master' into v0.2.0v0.2.0
-rw-r--r--CHANGES19
-rwxr-xr-xbin/sqlformat2
-rw-r--r--sqlparse/__init__.py2
-rw-r--r--sqlparse/engine/filter.py2
-rw-r--r--sqlparse/lexer.py6
-rw-r--r--sqlparse/sql.py15
-rw-r--r--tests/test_grouping.py5
-rw-r--r--tests/test_parse.py10
-rw-r--r--tests/test_regressions.py17
9 files changed, 69 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index 51a2551..0c29db4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,25 @@
Development Version
-------------------
+Nothing yet.
+
+
+Release 0.1.16 (Jul 26, 2015)
+-----------------------------
+
+Bug Fixes
+* Fix a regression in get_alias() introduced in 0.1.15 (issue185).
+* Fix a bug in the splitter regarding DECLARE (issue193).
+* sqlformat command line tool doesn't duplicat newlines anymore (issue191).
+* Don't mix up MySQL comments starting with hash and MSSQL
+ temp tables (issue192).
+* Statement.get_type() now ignores comments at the beginning of
+ a statement (issue186).
+
+
+Release 0.1.15 (Apr 15, 2015)
+-----------------------------
+
Bug Fixes
* Fix a regression for identifiers with square bracktes
notation (issue153, by darikg).
diff --git a/bin/sqlformat b/bin/sqlformat
index fcee452..cecbed9 100755
--- a/bin/sqlformat
+++ b/bin/sqlformat
@@ -77,7 +77,7 @@ def main():
data = sys.stdin.read()
else:
try:
- data = '\n'.join(open(args[0]).readlines())
+ data = ''.join(open(args[0]).readlines())
except OSError:
err = sys.exc_info()[1] # Python 2.5 compatibility
_error('Failed to read %s: %s' % (args[0], err), exit_=1)
diff --git a/sqlparse/__init__.py b/sqlparse/__init__.py
index 79dd83f..d943956 100644
--- a/sqlparse/__init__.py
+++ b/sqlparse/__init__.py
@@ -6,7 +6,7 @@
"""Parse SQL statements."""
-__version__ = '0.1.14'
+__version__ = '0.1.17-dev'
# Setup namespace
from sqlparse import compat
diff --git a/sqlparse/engine/filter.py b/sqlparse/engine/filter.py
index 9af2f99..e7ea0ec 100644
--- a/sqlparse/engine/filter.py
+++ b/sqlparse/engine/filter.py
@@ -40,7 +40,7 @@ class StatementFilter:
unified = value.upper()
- if unified == 'DECLARE' and self._is_create:
+ if unified == 'DECLARE' and self._is_create and self._begin_depth == 0:
self._in_declare = True
return 1
diff --git a/sqlparse/lexer.py b/sqlparse/lexer.py
index 602d275..7ce6d36 100644
--- a/sqlparse/lexer.py
+++ b/sqlparse/lexer.py
@@ -141,10 +141,10 @@ class Lexer(compat.with_metaclass(LexerMeta)):
tokens = {
'root': [
- (r'(--|#).*?(\r\n|\r|\n)', tokens.Comment.Single),
+ (r'(--|# ).*?(\r\n|\r|\n)', tokens.Comment.Single),
# $ matches *before* newline, therefore we have two patterns
# to match Comment.Single
- (r'(--|#).*?$', tokens.Comment.Single),
+ (r'(--|# ).*?$', tokens.Comment.Single),
(r'(\r\n|\r|\n)', tokens.Newline),
(r'\s+', tokens.Whitespace),
(r'/\*', tokens.Comment.Multiline, 'multiline-comments'),
@@ -162,7 +162,7 @@ class Lexer(compat.with_metaclass(LexerMeta)):
# FIXME(andi): VALUES shouldn't be listed here
# see https://github.com/andialbrecht/sqlparse/pull/64
(r'VALUES', tokens.Keyword),
- (r'@[^\W\d_]\w+', tokens.Name),
+ (r'(@|##|#)[^\W\d_]\w+', tokens.Name),
# IN is special, it may be followed by a parenthesis, but
# is never a functino, see issue183
(r'in\b(?=[ (])?', tokens.Keyword),
diff --git a/sqlparse/sql.py b/sqlparse/sql.py
index 89d1059..8601537 100644
--- a/sqlparse/sql.py
+++ b/sqlparse/sql.py
@@ -233,15 +233,20 @@ class TokenList(Token):
def _groupable_tokens(self):
return self.tokens
- def token_first(self, ignore_whitespace=True):
+ def token_first(self, ignore_whitespace=True, ignore_comments=False):
"""Returns the first child token.
If *ignore_whitespace* is ``True`` (the default), whitespace
tokens are ignored.
+
+ if *ignore_comments* is ``True`` (default: ``False``), comments are
+ ignored too.
"""
for token in self.tokens:
if ignore_whitespace and token.is_whitespace():
continue
+ if ignore_comments and isinstance(token, Comment):
+ continue
return token
def token_next_by_instance(self, idx, clss):
@@ -390,7 +395,8 @@ class TokenList(Token):
return self._get_first_name(kw, keywords=True)
# "name alias" or "complicated column expression alias"
- if len(self.tokens) > 2:
+ if len(self.tokens) > 2 \
+ and self.token_next_by_type(0, T.Whitespace) is not None:
return self._get_first_name(reverse=True)
return None
@@ -460,8 +466,11 @@ class Statement(TokenList):
The returned value is a string holding an upper-cased reprint of
the first DML or DDL keyword. If the first token in this group
isn't a DML or DDL keyword "UNKNOWN" is returned.
+
+ Whitespaces and comments at the beginning of the statement
+ are ignored.
"""
- first_token = self.token_first()
+ first_token = self.token_first(ignore_comments=True)
if first_token is None:
# An "empty" statement that either has not tokens at all
# or only whitespace tokens.
diff --git a/tests/test_grouping.py b/tests/test_grouping.py
index 0c2f108..5b87a38 100644
--- a/tests/test_grouping.py
+++ b/tests/test_grouping.py
@@ -187,6 +187,11 @@ class TestGrouping(TestCaseBase):
self.assertEqual(len(p.tokens), 1)
self.assertEqual(p.tokens[0].get_alias(), 'foo')
+ def test_alias_returns_none(self): # see issue185
+ p = sqlparse.parse('foo.bar')[0]
+ self.assertEqual(len(p.tokens), 1)
+ self.assertEqual(p.tokens[0].get_alias(), None)
+
def test_idlist_function(self): # see issue10 too
p = sqlparse.parse('foo(1) x, bar')[0]
self.assert_(isinstance(p.tokens[0], sql.IdentifierList))
diff --git a/tests/test_parse.py b/tests/test_parse.py
index c953dc2..bbe60df 100644
--- a/tests/test_parse.py
+++ b/tests/test_parse.py
@@ -294,3 +294,13 @@ def test_single_line_comments(sql):
assert p.tokens[-1].ttype == T.Comment.Single
+@pytest.mark.parametrize('sql', [
+ 'foo',
+ '@foo',
+ '#foo', # see issue192
+ '##foo'
+])
+def test_names_and_special_names(sql):
+ p = sqlparse.parse(sql)[0]
+ assert len(p.tokens) == 1
+ assert isinstance(p.tokens[0], sqlparse.sql.Identifier)
diff --git a/tests/test_regressions.py b/tests/test_regressions.py
index 31fda0f..6bd198b 100644
--- a/tests/test_regressions.py
+++ b/tests/test_regressions.py
@@ -248,3 +248,20 @@ def test_null_with_as():
'FROM t1'
])
assert formatted == tformatted
+
+
+def test_issue193_splitting_function():
+ sql = """CREATE FUNCTION a(x VARCHAR(20)) RETURNS VARCHAR(20)
+BEGIN
+ DECLARE y VARCHAR(20);
+ RETURN x;
+END;
+SELECT * FROM a.b;"""
+ splitted = sqlparse.split(sql)
+ assert len(splitted) == 2
+
+
+def test_issue186_get_type():
+ sql = "-- comment\ninsert into foo"
+ p = sqlparse.parse(sql)[0]
+ assert p.get_type() == 'INSERT'