Skip to content

Commit

Permalink
Merge branch 'master' into v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
andialbrecht committed Jul 26, 2015
2 parents d463a75 + 8987a3a commit 5df3944
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 9 deletions.
19 changes: 19 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -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).
Expand Down
2 changes: 1 addition & 1 deletion bin/sqlformat
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion sqlparse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""Parse SQL statements."""


__version__ = '0.1.14'
__version__ = '0.1.17-dev'

# Setup namespace
from sqlparse import compat
Expand Down
2 changes: 1 addition & 1 deletion sqlparse/engine/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _change_splitlevel(self, ttype, value):

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

Expand Down
6 changes: 3 additions & 3 deletions sqlparse/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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),
Expand Down
15 changes: 12 additions & 3 deletions sqlparse/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,20 @@ def get_sublists(self):
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):
Expand Down Expand Up @@ -390,7 +395,8 @@ def get_alias(self):
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
Expand Down Expand Up @@ -460,8 +466,11 @@ def get_type(self):
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.
Expand Down
5 changes: 5 additions & 0 deletions tests/test_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ def test_alias_case(self): # see issue46
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))
Expand Down
10 changes: 10 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
17 changes: 17 additions & 0 deletions tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'

0 comments on commit 5df3944

Please sign in to comment.