Hello community,
here is the log from the commit of package python-sqlparse for openSUSE:Factory
checked in at 2020-03-11 18:45:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sqlparse (Old)
and /work/SRC/openSUSE:Factory/.python-sqlparse.new.3160 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sqlparse"
Wed Mar 11 18:45:27 2020 rev:9 rq:783018 version:0.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-sqlparse/python-sqlparse.changes
2019-04-19 18:35:40.114977851 +0200
+++
/work/SRC/openSUSE:Factory/.python-sqlparse.new.3160/python-sqlparse.changes
2020-03-11 18:49:23.523515141 +0100
@@ -1,0 +2,23 @@
+Mon Mar 9 16:22:39 UTC 2020 - Dirk Mueller <[email protected]>
+
+- update to v0.3.1:
+ * Add HQL keywords (pr475, by matwalk).
+ * Add support for time zone casts (issue489).
+ * Enhance formatting of AS keyword (issue507, by john-bodley).
+ * Stabilize grouping engine when parsing invalid SQL statements.
+ * Fix splitting of SQL with multiple statements inside
+ parentheses (issue485, pr486 by win39).
+ * Correctly identify NULLS FIRST / NULLS LAST as keywords (issue487).
+ * Fix splitting of SQL statements that contain dollar signs in
+ identifiers (issue491).
+ * Remove support for parsing double slash comments introduced in
+ 0.3.0 (issue456) as it had some side-effects with other dialects and
+ doesn't seem to be widely used (issue476).
+ * Restrict detection of alias names to objects that acutally could
+ have an alias (issue455, adopted some parts of pr509 by john-bodley).
+ * Fix parsing of date/time literals (issue438, by vashek).
+ * Fix initialization of TokenList (issue499, pr505 by john-bodley).
+ * Fix parsing of LIKE (issue493, pr525 by dbczumar).
+ * Improve parsing of identifiers (pr527 by liulk).
+
+-------------------------------------------------------------------
Old:
----
sqlparse-0.3.0.tar.gz
New:
----
sqlparse-0.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-sqlparse.spec ++++++
--- /var/tmp/diff_new_pack.kv4jou/_old 2020-03-11 18:49:24.151515422 +0100
+++ /var/tmp/diff_new_pack.kv4jou/_new 2020-03-11 18:49:24.155515424 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-sqlparse
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,12 +18,12 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-sqlparse
-Version: 0.3.0
+Version: 0.3.1
Release: 0
Summary: Non-validating SQL parser
License: BSD-3-Clause
Group: Development/Languages/Python
-Url: https://github.com/andialbrecht/sqlparse
+URL: https://github.com/andialbrecht/sqlparse
Source:
https://files.pythonhosted.org/packages/source/s/sqlparse/sqlparse-%{version}.tar.gz
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
++++++ sqlparse-0.3.0.tar.gz -> sqlparse-0.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/AUTHORS new/sqlparse-0.3.1/AUTHORS
--- old/sqlparse-0.3.0/AUTHORS 2019-03-10 08:54:52.000000000 +0100
+++ new/sqlparse-0.3.1/AUTHORS 2020-02-02 21:23:42.000000000 +0100
@@ -16,11 +16,13 @@
* casey <[email protected]>
* Cauê Beloni <[email protected]>
* circld <[email protected]>
+* Corey Zumar <[email protected]>
* Cristian Orellana <[email protected]>
* Dag Wieers <[email protected]>
* Darik Gamble <[email protected]>
* Demetrio92 <[email protected]>
* Dennis Taylor <[email protected]>
+* Dvořák Václav <[email protected]>
* Florian Bauer <[email protected]>
* Fredy Wijaya <[email protected]>
* Gavin Wahl <[email protected]>
@@ -33,6 +35,8 @@
* Josh Soref <[email protected]>
* Kevin Jing Qiu <[email protected]>
* koljonen <[email protected]>
+* Likai Liu <[email protected]>
+* mathilde.oustlant <[email protected]>
* Michael Schuller <[email protected]>
* Mike Amy <[email protected]>
* mulos <[email protected]>
@@ -59,4 +63,5 @@
* Ville Skyttä <[email protected]>
* vthriller <[email protected]>
* wayne.wuw <[email protected]>
+* William Ivanski <[email protected]>
* Yago Riveiro <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/CHANGELOG new/sqlparse-0.3.1/CHANGELOG
--- old/sqlparse-0.3.0/CHANGELOG 2019-03-11 19:17:36.000000000 +0100
+++ new/sqlparse-0.3.1/CHANGELOG 2020-02-29 13:55:37.000000000 +0100
@@ -1,3 +1,31 @@
+Release 0.3.1 (Feb 29, 2020)
+----------------------------
+
+Enhancements
+
+* Add HQL keywords (pr475, by matwalk).
+* Add support for time zone casts (issue489).
+* Enhance formatting of AS keyword (issue507, by john-bodley).
+* Stabilize grouping engine when parsing invalid SQL statements.
+
+Bug Fixes
+
+* Fix splitting of SQL with multiple statements inside
+ parentheses (issue485, pr486 by win39).
+* Correctly identify NULLS FIRST / NULLS LAST as keywords (issue487).
+* Fix splitting of SQL statements that contain dollar signs in
+ identifiers (issue491).
+* Remove support for parsing double slash comments introduced in
+ 0.3.0 (issue456) as it had some side-effects with other dialects and
+ doesn't seem to be widely used (issue476).
+* Restrict detection of alias names to objects that acutally could
+ have an alias (issue455, adopted some parts of pr509 by john-bodley).
+* Fix parsing of date/time literals (issue438, by vashek).
+* Fix initialization of TokenList (issue499, pr505 by john-bodley).
+* Fix parsing of LIKE (issue493, pr525 by dbczumar).
+* Improve parsing of identifiers (pr527 by liulk).
+
+
Release 0.3.0 (Mar 11, 2019)
----------------------------
@@ -94,7 +122,7 @@
Release 0.2.1 (Aug 13, 2016)
----------------------------
+----------------------------
Notable Changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/Makefile new/sqlparse-0.3.1/Makefile
--- old/sqlparse-0.3.0/Makefile 2019-03-10 06:56:32.000000000 +0100
+++ new/sqlparse-0.3.1/Makefile 2020-02-29 14:00:54.000000000 +0100
@@ -22,5 +22,5 @@
release:
@rm -rf dist/
- python setup.py sdist upload --sign --identity E0B84F81
- python setup.py bdist_wheel upload --sign --identity E0B84F81
+ python setup.py sdist bdist_wheel
+ twine upload --sign --identity E0B84F81 dist/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/PKG-INFO new/sqlparse-0.3.1/PKG-INFO
--- old/sqlparse-0.3.0/PKG-INFO 2019-03-11 19:27:59.000000000 +0100
+++ new/sqlparse-0.3.1/PKG-INFO 2020-02-29 14:05:40.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: sqlparse
-Version: 0.3.0
+Version: 0.3.1
Summary: Non-validating SQL parser
Home-page: https://github.com/andialbrecht/sqlparse
Author: Andi Albrecht
@@ -26,7 +26,7 @@
Formatting statements::
>>> sql = 'select * from foo where id in (select id from bar);'
- >>> print sqlparse.format(sql, reindent=True, keyword_case='upper')
+ >>> print(sqlparse.format(sql, reindent=True, keyword_case='upper'))
SELECT *
FROM foo
WHERE id IN
@@ -69,6 +69,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Database
Classifier: Topic :: Software Development
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/README.rst
new/sqlparse-0.3.1/README.rst
--- old/sqlparse-0.3.0/README.rst 2019-03-10 06:56:32.000000000 +0100
+++ new/sqlparse-0.3.1/README.rst 2019-10-09 10:03:19.000000000 +0200
@@ -1,62 +1,72 @@
python-sqlparse - Parse SQL statements
======================================
-sqlparse is a non-validating SQL parser module for Python.
-
|buildstatus|_
|coverage|_
+.. docincludebegin
-Install
--------
-
-From pip, run::
+sqlparse is a non-validating SQL parser for Python.
+It provides support for parsing, splitting and formatting SQL statements.
- $ pip install --upgrade sqlparse
+The module is compatible with Python 2.7 and Python 3 (>= 3.4)
+and released under the terms of the `New BSD license
+<https://opensource.org/licenses/BSD-3-Clause>`_.
-Consider using the ``--user`` option_.
+.. note::
-.. _option: https://pip.pypa.io/en/latest/user_guide/#user-installs
+ Support for Python<3.4 (including 2.x) will be dropped soon.
-From the repository, run::
+Visit the project page at https://github.com/andialbrecht/sqlparse for
+further information about this project.
- python setup.py install
-to install python-sqlparse on your system.
+Quick Start
+-----------
-python-sqlparse is compatible with Python 2.7 and Python 3 (>= 3.3).
+.. code-block:: sh
+ $ pip install sqlparse
-Run Tests
----------
+.. code-block:: python
-To run the test suite run::
+ >>> import sqlparse
- tox
+ >>> # Split a string containing two SQL statements:
+ >>> raw = 'select * from foo; select * from bar;'
+ >>> statements = sqlparse.split(raw)
+ >>> statements
+ ['select * from foo;', 'select * from bar;']
-Note, you'll need tox installed, of course.
+ >>> # Format the first statement and print it out:
+ >>> first = statements[0]
+ >>> print(sqlparse.format(first, reindent=True, keyword_case='upper'))
+ SELECT *
+ FROM foo;
+ >>> # Parsing a SQL statement:
+ >>> parsed = sqlparse.parse('select * from foo')[0]
+ >>> parsed.tokens
+ [<DML 'select' at 0x7f22c5e15368>, <Whitespace ' ' at 0x7f22c5e153b0>,
<Wildcard '*' … ]
+ >>>
Links
-----
-Project Page
- https://github.com/andialbrecht/sqlparse
+Project page
+ https://github.com/andialbrecht/sqlparse
-Documentation
- https://sqlparse.readthedocs.io/en/latest/
+Bug tracker
+ https://github.com/andialbrecht/sqlparse/issues
-Discussions
- https://groups.google.com/forum/#!forum/sqlparse
-
-Issues/Bugs
- https://github.com/andialbrecht/sqlparse/issues
+Documentation
+ https://sqlparse.readthedocs.io/
Online Demo
https://sqlformat.org/
-python-sqlparse is licensed under the BSD license.
+sqlparse is licensed under the BSD license.
Parts of the code are based on pygments written by Georg Brandl and others.
pygments-Homepage: http://pygments.org/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/docs/source/api.rst
new/sqlparse-0.3.1/docs/source/api.rst
--- old/sqlparse-0.3.0/docs/source/api.rst 2019-03-10 06:56:32.000000000
+0100
+++ new/sqlparse-0.3.1/docs/source/api.rst 2020-02-29 13:49:48.000000000
+0100
@@ -46,6 +46,12 @@
``reindent``
If ``True`` the indentations of the statements are changed.
+``reindent_aligned``
+ If ``True`` the indentations of the statements are changed, and statements
are aligned by keywords.
+
+``use_space_around_operators``
+ If ``True`` spaces are used around all operators.
+
``indent_tabs``
If ``True`` tabs instead of spaces are used for indentation.
@@ -53,9 +59,14 @@
The width of the indentation, defaults to 2.
``wrap_after``
- The column limit for wrapping comma-separated lists. If unspecified, it
+ The column limit (in characters) for wrapping comma-separated lists. If
unspecified, it
puts every item in the list on its own line.
``output_format``
If given the output is additionally formatted to be used as a variable
in a programming language. Allowed values are "python" and "php".
+
+``comma_first``
+ If ``True`` comma-first notation for column names is used.
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/docs/source/index.rst
new/sqlparse-0.3.1/docs/source/index.rst
--- old/sqlparse-0.3.0/docs/source/index.rst 2019-03-10 06:56:32.000000000
+0100
+++ new/sqlparse-0.3.1/docs/source/index.rst 2019-10-09 10:03:19.000000000
+0200
@@ -6,33 +6,9 @@
python-sqlparse
===============
-:mod:`sqlparse` is a non-validating SQL parser for Python.
-It provides support for parsing, splitting and formatting SQL statements.
-
-The module is compatible with Python 2.7 and Python 3 (>= 3.3)
-and released under the terms of the `New BSD license
-<https://opensource.org/licenses/BSD-3-Clause>`_.
-
-Visit the project page at https://github.com/andialbrecht/sqlparse for
-further information about this project.
-
-
-tl;dr
------
-
-.. code-block:: bash
-
- $ pip install sqlparse
- $ python
- >>> import sqlparse
- >>> print(sqlparse.format('select * from foo', reindent=True))
- select *
- from foo
- >>> parsed = sqlparse.parse('select * from foo')[0]
- >>> parsed.tokens
- [<DML 'select' at 0x7f22c5e15368>, <Whitespace ' ' at 0x7f22c5e153b0>,
<Wildcard '*' … ]
- >>>
-
+.. include:: ../../README.rst
+ :start-after: docincludebegin
+ :end-before: Links
Contents
--------
@@ -45,6 +21,7 @@
analyzing
ui
changes
+ license
indices
@@ -59,3 +36,7 @@
Documentation
https://sqlparse.readthedocs.io/
+
+Online Demo
+ https://sqlformat.org/
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/docs/source/intro.rst
new/sqlparse-0.3.1/docs/source/intro.rst
--- old/sqlparse-0.3.0/docs/source/intro.rst 2019-03-10 06:56:32.000000000
+0100
+++ new/sqlparse-0.3.1/docs/source/intro.rst 2019-10-09 10:03:19.000000000
+0200
@@ -6,7 +6,7 @@
-----------------------
The latest released version can be obtained from the `Python Package
-Index (PyPI) <https://pypi.org/project/sqlparse/>`_. To extract the
+Index (PyPI) <https://pypi.org/project/sqlparse/>`_. To extract and
install the module system-wide run
.. code-block:: bash
@@ -48,7 +48,7 @@
.. code-block:: python
>>> sql = 'select * from foo where id in (select id from bar);'
- >>> print sqlparse.format(sql, reindent=True, keyword_case='upper')
+ >>> print(sqlparse.format(sql, reindent=True, keyword_case='upper'))
SELECT *
FROM foo
WHERE id IN
@@ -120,7 +120,7 @@
to check out the latest sources from the repository.
-:mod:`sqlparse` is currently tested under Python 2.7, >=3.3 and pypy. Tests are
+:mod:`sqlparse` is currently tested under Python 2.7, >=3.4 and pypy. Tests are
automatically run on each commit and for each pull request on Travis:
https://travis-ci.org/andialbrecht/sqlparse
@@ -135,9 +135,4 @@
locally.
Please file bug reports and feature requests on the project site at
-https://github.com/andialbrecht/sqlparse/issues/new or if you have
-code to contribute upload it to https://codereview.appspot.com/ and
-add [email protected] as reviewer.
-
-For more information about the review tool and how to use it visit
-it's project page: https://github.com/rietveld-codereview/rietveld
+https://github.com/andialbrecht/sqlparse/issues/new.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/docs/source/license.rst
new/sqlparse-0.3.1/docs/source/license.rst
--- old/sqlparse-0.3.0/docs/source/license.rst 1970-01-01 01:00:00.000000000
+0100
+++ new/sqlparse-0.3.1/docs/source/license.rst 2019-10-09 10:03:19.000000000
+0200
@@ -0,0 +1,4 @@
+License
+=======
+
+.. include:: ../../LICENSE
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/setup.py new/sqlparse-0.3.1/setup.py
--- old/sqlparse-0.3.0/setup.py 2019-03-10 06:56:32.000000000 +0100
+++ new/sqlparse-0.3.1/setup.py 2020-01-08 16:29:04.000000000 +0100
@@ -44,7 +44,7 @@
Formatting statements::
>>> sql = 'select * from foo where id in (select id from bar);'
- >>> print sqlparse.format(sql, reindent=True, keyword_case='upper')
+ >>> print(sqlparse.format(sql, reindent=True, keyword_case='upper'))
SELECT *
FROM foo
WHERE id IN
@@ -98,6 +98,7 @@
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
'Topic :: Database',
'Topic :: Software Development',
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/__init__.py
new/sqlparse-0.3.1/sqlparse/__init__.py
--- old/sqlparse-0.3.0/sqlparse/__init__.py 2019-03-11 19:18:08.000000000
+0100
+++ new/sqlparse-0.3.1/sqlparse/__init__.py 2020-02-29 13:56:02.000000000
+0100
@@ -18,7 +18,7 @@
from sqlparse.compat import text_type
-__version__ = '0.3.0'
+__version__ = '0.3.1'
__all__ = ['engine', 'filters', 'formatter', 'sql', 'tokens', 'cli']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/engine/grouping.py
new/sqlparse-0.3.1/sqlparse/engine/grouping.py
--- old/sqlparse-0.3.0/sqlparse/engine/grouping.py 2019-03-11
12:35:49.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse/engine/grouping.py 2020-02-02
21:21:46.000000000 +0100
@@ -88,6 +88,49 @@
_group(tlist, sql.Identifier, match, valid_prev, valid_next, post)
+def group_tzcasts(tlist):
+ def match(token):
+ return token.ttype == T.Keyword.TZCast
+
+ def valid(token):
+ return token is not None
+
+ def post(tlist, pidx, tidx, nidx):
+ return pidx, nidx
+
+ _group(tlist, sql.Identifier, match, valid, valid, post)
+
+
+def group_typed_literal(tlist):
+ # definitely not complete, see e.g.:
+ #
https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/interval-literal-syntax
+ #
https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/interval-literals
+ # https://www.postgresql.org/docs/9.1/datatype-datetime.html
+ # https://www.postgresql.org/docs/9.1/functions-datetime.html
+ def match(token):
+ return imt(token, m=sql.TypedLiteral.M_OPEN)
+
+ def match_to_extend(token):
+ return isinstance(token, sql.TypedLiteral)
+
+ def valid_prev(token):
+ return token is not None
+
+ def valid_next(token):
+ return token is not None and token.match(*sql.TypedLiteral.M_CLOSE)
+
+ def valid_final(token):
+ return token is not None and token.match(*sql.TypedLiteral.M_EXTEND)
+
+ def post(tlist, pidx, tidx, nidx):
+ return tidx, nidx
+
+ _group(tlist, sql.TypedLiteral, match, valid_prev, valid_next,
+ post, extend=False)
+ _group(tlist, sql.TypedLiteral, match_to_extend, valid_prev, valid_final,
+ post, extend=True)
+
+
def group_period(tlist):
def match(token):
return token.match(T.Punctuation, '.')
@@ -121,7 +164,7 @@
return token.normalized == 'NULL' or not token.is_keyword
def valid_next(token):
- ttypes = T.DML, T.DDL
+ ttypes = T.DML, T.DDL, T.CTE
return not imt(token, t=ttypes) and token is not None
def post(tlist, pidx, tidx, nidx):
@@ -204,13 +247,16 @@
def group_operator(tlist):
ttypes = T_NUMERICAL + T_STRING + T_NAME
sqlcls = (sql.SquareBrackets, sql.Parenthesis, sql.Function,
- sql.Identifier, sql.Operation)
+ sql.Identifier, sql.Operation, sql.TypedLiteral)
def match(token):
return imt(token, t=(T.Operator, T.Wildcard))
def valid(token):
- return imt(token, i=sqlcls, t=ttypes)
+ return imt(token, i=sqlcls, t=ttypes) \
+ or (token and token.match(
+ T.Keyword,
+ ('CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP')))
def post(tlist, pidx, tidx, nidx):
tlist[tidx].ttype = T.Operator
@@ -358,6 +404,8 @@
group_identifier,
group_order,
group_typecasts,
+ group_tzcasts,
+ group_typed_literal,
group_operator,
group_comparison,
group_as,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/engine/statement_splitter.py
new/sqlparse-0.3.1/sqlparse/engine/statement_splitter.py
--- old/sqlparse-0.3.0/sqlparse/engine/statement_splitter.py 2019-03-10
07:24:45.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse/engine/statement_splitter.py 2019-10-20
17:50:43.000000000 +0200
@@ -27,11 +27,13 @@
def _change_splitlevel(self, ttype, value):
"""Get the new split level (increase, decrease or remain equal)"""
- # ANSI
- # if normal token return
- # wouldn't parenthesis increase/decrease a level?
- # no, inside a parenthesis can't start new statement
- if ttype not in T.Keyword:
+
+ # parenthesis increase/decrease a level
+ if ttype is T.Punctuation and value == '(':
+ return 1
+ elif ttype is T.Punctuation and value == ')':
+ return -1
+ elif ttype not in T.Keyword: # if normal token return
return 0
# Everything after here is ttype = T.Keyword
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/filters/aligned_indent.py
new/sqlparse-0.3.1/sqlparse/filters/aligned_indent.py
--- old/sqlparse-0.3.0/sqlparse/filters/aligned_indent.py 2019-03-10
08:59:54.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse/filters/aligned_indent.py 2019-10-20
17:49:07.000000000 +0200
@@ -105,8 +105,8 @@
# joins, group/order by are special case. only consider the first
# word as aligner
if (
- token.match(T.Keyword, self.join_words, regex=True) or
- token.match(T.Keyword, self.by_words, regex=True)
+ token.match(T.Keyword, self.join_words, regex=True)
+ or token.match(T.Keyword, self.by_words, regex=True)
):
token_indent = token.value.split()[0]
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/keywords.py
new/sqlparse-0.3.1/sqlparse/keywords.py
--- old/sqlparse-0.3.0/sqlparse/keywords.py 2019-03-11 12:30:08.000000000
+0100
+++ new/sqlparse-0.3.1/sqlparse/keywords.py 2020-01-16 09:20:33.000000000
+0100
@@ -16,15 +16,16 @@
return (KEYWORDS_COMMON.get(val)
or KEYWORDS_ORACLE.get(val)
or KEYWORDS_PLPGSQL.get(val)
+ or KEYWORDS_HQL.get(val)
or KEYWORDS.get(val, tokens.Name)), value
SQL_REGEX = {
'root': [
- (r'(--|//|# )\+.*?(\r\n|\r|\n|$)', tokens.Comment.Single.Hint),
+ (r'(--|# )\+.*?(\r\n|\r|\n|$)', tokens.Comment.Single.Hint),
(r'/\*\+[\s\S]*?\*/', tokens.Comment.Multiline.Hint),
- (r'(--|//|# ).*?(\r\n|\r|\n|$)', tokens.Comment.Single),
+ (r'(--|# ).*?(\r\n|\r|\n|$)', tokens.Comment.Single),
(r'/\*[\s\S]*?\*/', tokens.Comment.Multiline),
(r'(\r\n|\r|\n)', tokens.Newline),
@@ -37,7 +38,7 @@
(r"`(``|[^`])*`", tokens.Name),
(r"´(´´|[^´])*´", tokens.Name),
- (r'(\$(?:[_A-ZÀ-Ü]\w*)?\$)[\s\S]*?\1', tokens.Literal),
+ (r'((?<!\S)\$(?:[_A-ZÀ-Ü]\w*)?\$)[\s\S]*?\1', tokens.Literal),
(r'\?', tokens.Name.Placeholder),
(r'%(\(\w+\))?s', tokens.Name.Placeholder),
@@ -47,9 +48,9 @@
# FIXME(andi): VALUES shouldn't be listed here
# see https://github.com/andialbrecht/sqlparse/pull/64
- # IN is special, it may be followed by a parenthesis, but
- # is never a function, see issue183
- (r'(CASE|IN|VALUES|USING|FROM)\b', tokens.Keyword),
+ # AS and IN are special, it may be followed by a parenthesis, but
+ # are never functions, see issue183 and issue507
+ (r'(CASE|IN|VALUES|USING|FROM|AS)\b', tokens.Keyword),
(r'(@|##|#)[A-ZÀ-Ü]\w+', tokens.Name),
@@ -63,8 +64,9 @@
(r'[A-ZÀ-Ü]\w*(?=\()', tokens.Name), # side effect: change kw to func
(r'-?0x[\dA-F]+', tokens.Number.Hexadecimal),
(r'-?\d*(\.\d+)?E-?\d+', tokens.Number.Float),
- (r'-?(\d+(\.\d*)|\.\d+)', tokens.Number.Float),
- (r'-?\d+(?![_A-ZÀ-Ü])', tokens.Number.Integer),
+ (r'(?![_A-ZÀ-Ü])-?(\d+(\.\d*)|\.\d+)(?![_A-ZÀ-Ü])',
+ tokens.Number.Float),
+ (r'(?![_A-ZÀ-Ü])-?\d+(?![_A-ZÀ-Ü])', tokens.Number.Integer),
(r"'(''|\\\\|\\'|[^'])*'", tokens.String.Single),
# not a real string literal in ANSI SQL:
(r'"(""|\\\\|\\"|[^"])*"', tokens.String.Symbol),
@@ -77,14 +79,18 @@
r'|(CROSS\s+|NATURAL\s+)?)?JOIN\b', tokens.Keyword),
(r'END(\s+IF|\s+LOOP|\s+WHILE)?\b', tokens.Keyword),
(r'NOT\s+NULL\b', tokens.Keyword),
+ (r'NULLS\s+(FIRST|LAST)\b', tokens.Keyword),
(r'UNION\s+ALL\b', tokens.Keyword),
(r'CREATE(\s+OR\s+REPLACE)?\b', tokens.Keyword.DDL),
(r'DOUBLE\s+PRECISION\b', tokens.Name.Builtin),
(r'GROUP\s+BY\b', tokens.Keyword),
(r'ORDER\s+BY\b', tokens.Keyword),
-
+ (r'(LATERAL\s+VIEW\s+)'
+ r'(EXPLODE|INLINE|PARSE_URL_TUPLE|POSEXPLODE|STACK)\b',
+ tokens.Keyword),
+ (r"(AT|WITH')\s+TIME\s+ZONE\s+'[^']+'", tokens.Keyword.TZCast),
+ (r'(NOT\s+)?(LIKE|ILIKE)\b', tokens.Operator.Comparison),
(r'[0-9_A-ZÀ-Ü][_$#\w]*', is_keyword),
-
(r'[;:()\[\],\.]', tokens.Punctuation),
(r'[<>=~!]+', tokens.Operator.Comparison),
(r'[+/@#%^&|`?^-]+', tokens.Operator),
@@ -191,7 +197,7 @@
'CONVERSION': tokens.Keyword,
'CONVERT': tokens.Keyword,
'COPY': tokens.Keyword,
- 'CORRESPONTING': tokens.Keyword,
+ 'CORRESPONDING': tokens.Keyword,
'COUNT': tokens.Keyword,
'CREATEDB': tokens.Keyword,
'CREATEUSER': tokens.Keyword,
@@ -426,11 +432,11 @@
'PARAMETER': tokens.Keyword,
'PARAMETERS': tokens.Keyword,
'PARAMETER_MODE': tokens.Keyword,
- 'PARAMATER_NAME': tokens.Keyword,
- 'PARAMATER_ORDINAL_POSITION': tokens.Keyword,
+ 'PARAMETER_NAME': tokens.Keyword,
+ 'PARAMETER_ORDINAL_POSITION': tokens.Keyword,
'PARAMETER_SPECIFIC_CATALOG': tokens.Keyword,
'PARAMETER_SPECIFIC_NAME': tokens.Keyword,
- 'PARAMATER_SPECIFIC_SCHEMA': tokens.Keyword,
+ 'PARAMETER_SPECIFIC_SCHEMA': tokens.Keyword,
'PARTIAL': tokens.Keyword,
'PASCAL': tokens.Keyword,
'PCTFREE': tokens.Keyword,
@@ -634,14 +640,20 @@
'DATE': tokens.Name.Builtin,
'DEC': tokens.Name.Builtin,
'DECIMAL': tokens.Name.Builtin,
+ 'FILE_TYPE': tokens.Name.Builtin,
'FLOAT': tokens.Name.Builtin,
'INT': tokens.Name.Builtin,
'INT8': tokens.Name.Builtin,
'INTEGER': tokens.Name.Builtin,
'INTERVAL': tokens.Name.Builtin,
'LONG': tokens.Name.Builtin,
+ 'NATURALN': tokens.Name.Builtin,
+ 'NVARCHAR': tokens.Name.Builtin,
'NUMBER': tokens.Name.Builtin,
'NUMERIC': tokens.Name.Builtin,
+ 'PLS_INTEGER': tokens.Name.Builtin,
+ 'POSITIVE': tokens.Name.Builtin,
+ 'POSITIVEN': tokens.Name.Builtin,
'REAL': tokens.Name.Builtin,
'ROWID': tokens.Name.Builtin,
'ROWLABEL': tokens.Name.Builtin,
@@ -649,11 +661,18 @@
'SERIAL': tokens.Name.Builtin,
'SERIAL8': tokens.Name.Builtin,
'SIGNED': tokens.Name.Builtin,
+ 'SIGNTYPE': tokens.Name.Builtin,
+ 'SIMPLE_DOUBLE': tokens.Name.Builtin,
+ 'SIMPLE_FLOAT': tokens.Name.Builtin,
+ 'SIMPLE_INTEGER': tokens.Name.Builtin,
'SMALLINT': tokens.Name.Builtin,
+ 'SYS_REFCURSOR': tokens.Name.Builtin,
'SYSDATE': tokens.Name,
'TEXT': tokens.Name.Builtin,
'TINYINT': tokens.Name.Builtin,
'UNSIGNED': tokens.Name.Builtin,
+ 'UROWID': tokens.Name.Builtin,
+ 'UTL_FILE': tokens.Name.Builtin,
'VARCHAR': tokens.Name.Builtin,
'VARCHAR2': tokens.Name.Builtin,
'VARYING': tokens.Name.Builtin,
@@ -854,3 +873,83 @@
'IN': tokens.Keyword,
'LOOP': tokens.Keyword,
}
+
+# Hive Syntax
+KEYWORDS_HQL = {
+ 'EXPLODE': tokens.Keyword,
+ 'DIRECTORY': tokens.Keyword,
+ 'DISTRIBUTE': tokens.Keyword,
+ 'INCLUDE': tokens.Keyword,
+ 'LOCATE': tokens.Keyword,
+ 'OVERWRITE': tokens.Keyword,
+ 'POSEXPLODE': tokens.Keyword,
+
+ 'ARRAY_CONTAINS': tokens.Keyword,
+ 'CMP': tokens.Keyword,
+ 'COLLECT_LIST': tokens.Keyword,
+ 'CONCAT': tokens.Keyword,
+ 'CONDITION': tokens.Keyword,
+ 'DATE_ADD': tokens.Keyword,
+ 'DATE_SUB': tokens.Keyword,
+ 'DECODE': tokens.Keyword,
+ 'DBMS_OUTPUT': tokens.Keyword,
+ 'ELEMENTS': tokens.Keyword,
+ 'EXCHANGE': tokens.Keyword,
+ 'EXTENDED': tokens.Keyword,
+ 'FLOOR': tokens.Keyword,
+ 'FOLLOWING': tokens.Keyword,
+ 'FROM_UNIXTIME': tokens.Keyword,
+ 'FTP': tokens.Keyword,
+ 'HOUR': tokens.Keyword,
+ 'INLINE': tokens.Keyword,
+ 'INSTR': tokens.Keyword,
+ 'LEN': tokens.Keyword,
+ 'MAXELEMENT': tokens.Keyword,
+ 'MAXINDEX': tokens.Keyword,
+ 'MAX_PART_DATE': tokens.Keyword,
+ 'MAX_PART_INT': tokens.Keyword,
+ 'MAX_PART_STRING': tokens.Keyword,
+ 'MINELEMENT': tokens.Keyword,
+ 'MININDEX': tokens.Keyword,
+ 'MIN_PART_DATE': tokens.Keyword,
+ 'MIN_PART_INT': tokens.Keyword,
+ 'MIN_PART_STRING': tokens.Keyword,
+ 'NOW': tokens.Keyword,
+ 'NVL': tokens.Keyword,
+ 'NVL2': tokens.Keyword,
+ 'PARSE_URL_TUPLE': tokens.Keyword,
+ 'PART_LOC': tokens.Keyword,
+ 'PART_COUNT': tokens.Keyword,
+ 'PART_COUNT_BY': tokens.Keyword,
+ 'PRINT': tokens.Keyword,
+ 'PUT_LINE': tokens.Keyword,
+ 'RANGE': tokens.Keyword,
+ 'REDUCE': tokens.Keyword,
+ 'REGEXP_REPLACE': tokens.Keyword,
+ 'RESIGNAL': tokens.Keyword,
+ 'RTRIM': tokens.Keyword,
+ 'SIGN': tokens.Keyword,
+ 'SIGNAL': tokens.Keyword,
+ 'SIN': tokens.Keyword,
+ 'SPLIT': tokens.Keyword,
+ 'SQRT': tokens.Keyword,
+ 'STACK': tokens.Keyword,
+ 'STR': tokens.Keyword,
+ 'SUBSTR': tokens.Keyword,
+ 'SUMMARY': tokens.Keyword,
+ 'TBLPROPERTIES': tokens.Keyword,
+ 'TIMESTAMP_ISO': tokens.Keyword,
+ 'TO_CHAR': tokens.Keyword,
+ 'TO_DATE': tokens.Keyword,
+ 'TO_TIMESTAMP': tokens.Keyword,
+ 'TRUNC': tokens.Keyword,
+ 'UNBOUNDED': tokens.Keyword,
+ 'UNIQUEJOIN': tokens.Keyword,
+ 'UNIX_TIMESTAMP': tokens.Keyword,
+ 'UTC_TIMESTAMP': tokens.Keyword,
+ 'VIEWS': tokens.Keyword,
+
+ 'EXIT': tokens.Keyword,
+ 'BREAK': tokens.Keyword,
+ 'LEAVE': tokens.Keyword,
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse/sql.py
new/sqlparse-0.3.1/sqlparse/sql.py
--- old/sqlparse-0.3.0/sqlparse/sql.py 2019-03-11 12:32:03.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse/sql.py 2020-02-02 21:21:46.000000000 +0100
@@ -16,6 +16,29 @@
from sqlparse.utils import imt, remove_quotes
+class NameAliasMixin:
+ """Implements get_real_name and get_alias."""
+
+ def get_real_name(self):
+ """Returns the real name (object name) of this identifier."""
+ # a.b
+ dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
+ return self._get_first_name(dot_idx, real_name=True)
+
+ def get_alias(self):
+ """Returns the alias for this identifier or ``None``."""
+
+ # "name AS alias"
+ kw_idx, kw = self.token_next_by(m=(T.Keyword, 'AS'))
+ if kw is not None:
+ return self._get_first_name(kw_idx + 1, keywords=True)
+
+ # "name alias" or "complicated column expression alias"
+ _, ws = self.token_next_by(t=T.Whitespace)
+ if len(self.tokens) > 2 and ws is not None:
+ return self._get_first_name(reverse=True)
+
+
@unicode_compatible
class Token(object):
"""Base class for all other classes in this module.
@@ -139,7 +162,7 @@
def __init__(self, tokens=None):
self.tokens = tokens or []
- [setattr(token, 'parent', self) for token in tokens]
+ [setattr(token, 'parent', self) for token in self.tokens]
super(TokenList, self).__init__(None, text_type(self))
self.is_group = True
@@ -239,15 +262,14 @@
ignored too.
"""
# this on is inconsistent, using Comment instead of T.Comment...
- funcs = lambda tk: not ((skip_ws and tk.is_whitespace)
- or (skip_cm and imt(tk,
- t=T.Comment, i=Comment)))
- return self._token_matching(funcs)[1]
+ def matcher(tk):
+ return not ((skip_ws and tk.is_whitespace)
+ or (skip_cm and imt(tk, t=T.Comment, i=Comment)))
+ return self._token_matching(matcher)[1]
def token_next_by(self, i=None, m=None, t=None, idx=-1, end=None):
- funcs = lambda tk: imt(tk, i, m, t)
idx += 1
- return self._token_matching(funcs, idx, end)
+ return self._token_matching(lambda tk: imt(tk, i, m, t), idx, end)
def token_not_matching(self, funcs, idx):
funcs = (funcs,) if not isinstance(funcs, (list, tuple)) else funcs
@@ -277,10 +299,11 @@
if idx is None:
return None, None
idx += 1 # alot of code usage current pre-compensates for this
- funcs = lambda tk: not ((skip_ws and tk.is_whitespace)
- or (skip_cm and imt(tk,
- t=T.Comment, i=Comment)))
- return self._token_matching(funcs, idx, reverse=_reverse)
+
+ def matcher(tk):
+ return not ((skip_ws and tk.is_whitespace)
+ or (skip_cm and imt(tk, t=T.Comment, i=Comment)))
+ return self._token_matching(matcher, idx, reverse=_reverse)
def token_index(self, token, start=0):
"""Return list index of token."""
@@ -341,16 +364,7 @@
def get_alias(self):
"""Returns the alias for this identifier or ``None``."""
-
- # "name AS alias"
- kw_idx, kw = self.token_next_by(m=(T.Keyword, 'AS'))
- if kw is not None:
- return self._get_first_name(kw_idx + 1, keywords=True)
-
- # "name alias" or "complicated column expression alias"
- _, ws = self.token_next_by(t=T.Whitespace)
- if len(self.tokens) > 2 and ws is not None:
- return self._get_first_name(reverse=True)
+ return None
def get_name(self):
"""Returns the name of this identifier.
@@ -363,9 +377,7 @@
def get_real_name(self):
"""Returns the real name (object name) of this identifier."""
- # a.b
- dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
- return self._get_first_name(dot_idx, real_name=True)
+ return None
def get_parent_name(self):
"""Return name of the parent object if any.
@@ -433,7 +445,7 @@
return 'UNKNOWN'
-class Identifier(TokenList):
+class Identifier(NameAliasMixin, TokenList):
"""Represents an identifier.
Identifiers may have aliases or typecasts.
@@ -477,6 +489,13 @@
yield token
+class TypedLiteral(TokenList):
+ """A typed literal, such as "date '2001-09-28'" or "interval '2 hours'"."""
+ M_OPEN = [(T.Name.Builtin, None), (T.Keyword, "TIMESTAMP")]
+ M_CLOSE = T.String.Single, None
+ M_EXTEND = T.Keyword, ("DAY", "HOUR", "MINUTE", "MONTH", "SECOND", "YEAR")
+
+
class Parenthesis(TokenList):
"""Tokens between parenthesis."""
M_OPEN = T.Punctuation, '('
@@ -599,7 +618,7 @@
return ret
-class Function(TokenList):
+class Function(NameAliasMixin, TokenList):
"""A function or procedure call."""
def get_parameters(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse.egg-info/PKG-INFO
new/sqlparse-0.3.1/sqlparse.egg-info/PKG-INFO
--- old/sqlparse-0.3.0/sqlparse.egg-info/PKG-INFO 2019-03-11
19:27:58.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse.egg-info/PKG-INFO 2020-02-29
14:05:39.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: sqlparse
-Version: 0.3.0
+Version: 0.3.1
Summary: Non-validating SQL parser
Home-page: https://github.com/andialbrecht/sqlparse
Author: Andi Albrecht
@@ -26,7 +26,7 @@
Formatting statements::
>>> sql = 'select * from foo where id in (select id from bar);'
- >>> print sqlparse.format(sql, reindent=True, keyword_case='upper')
+ >>> print(sqlparse.format(sql, reindent=True, keyword_case='upper'))
SELECT *
FROM foo
WHERE id IN
@@ -69,6 +69,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Database
Classifier: Topic :: Software Development
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/sqlparse.egg-info/SOURCES.txt
new/sqlparse-0.3.1/sqlparse.egg-info/SOURCES.txt
--- old/sqlparse-0.3.0/sqlparse.egg-info/SOURCES.txt 2019-03-11
19:27:59.000000000 +0100
+++ new/sqlparse-0.3.1/sqlparse.egg-info/SOURCES.txt 2020-02-29
14:05:39.000000000 +0100
@@ -17,6 +17,7 @@
docs/source/index.rst
docs/source/indices.rst
docs/source/intro.rst
+docs/source/license.rst
docs/source/ui.rst
sqlparse/__init__.py
sqlparse/__main__.py
@@ -67,6 +68,5 @@
tests/files/function_psql3.sql
tests/files/function_psql4.sql
tests/files/huge_select.sql
-tests/files/slashcomment.sql
tests/files/stream.sql
tests/files/test_cp1251.sql
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/files/slashcomment.sql
new/sqlparse-0.3.1/tests/files/slashcomment.sql
--- old/sqlparse-0.3.0/tests/files/slashcomment.sql 2019-03-10
08:54:03.000000000 +0100
+++ new/sqlparse-0.3.1/tests/files/slashcomment.sql 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-select * from user;
-//select * from host;
-select * from user;
-select * // foo;
-from foo;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/test_grouping.py
new/sqlparse-0.3.1/tests/test_grouping.py
--- old/sqlparse-0.3.0/tests/test_grouping.py 2019-03-10 08:59:54.000000000
+0100
+++ new/sqlparse-0.3.1/tests/test_grouping.py 2020-02-02 21:21:46.000000000
+0100
@@ -33,6 +33,40 @@
assert isinstance(parsed.tokens[0], sql.Assignment)
[email protected]('s', ["x > DATE '2020-01-01'", "x > TIMESTAMP
'2020-01-01 00:00:00'"])
+def test_grouping_typed_literal(s):
+ parsed = sqlparse.parse(s)[0]
+ assert isinstance(parsed[4], sql.TypedLiteral)
+
+
[email protected]('s, a, b', [
+ ('select a from b where c < d + e', sql.Identifier, sql.Identifier),
+ ('select a from b where c < d + interval \'1 day\'', sql.Identifier,
sql.TypedLiteral),
+ ('select a from b where c < d + interval \'6\' month', sql.Identifier,
sql.TypedLiteral),
+ ('select a from b where c < current_timestamp - interval \'1 day\'',
sql.Token, sql.TypedLiteral),
+])
+def test_compare_expr(s, a, b):
+ parsed = sqlparse.parse(s)[0]
+ assert str(parsed) == s
+ assert isinstance(parsed.tokens[2], sql.Identifier)
+ assert isinstance(parsed.tokens[6], sql.Identifier)
+ assert isinstance(parsed.tokens[8], sql.Where)
+ assert len(parsed.tokens) == 9
+ where = parsed.tokens[8]
+ assert isinstance(where.tokens[2], sql.Comparison)
+ assert len(where.tokens) == 3
+ comparison = where.tokens[2]
+ assert isinstance(comparison.tokens[0], sql.Identifier)
+ assert comparison.tokens[2].ttype is T.Operator.Comparison
+ assert isinstance(comparison.tokens[4], sql.Operation)
+ assert len(comparison.tokens) == 5
+ operation = comparison.tokens[4]
+ assert isinstance(operation.tokens[0], a)
+ assert operation.tokens[2].ttype is T.Operator
+ assert isinstance(operation.tokens[4], b)
+ assert len(operation.tokens) == 5
+
+
def test_grouping_identifiers():
s = 'select foo.bar from "myscheme"."table" where fail. order'
parsed = sqlparse.parse(s)[0]
@@ -127,6 +161,14 @@
assert p[3].ttype == T.Whitespace
assert str(p[2]) == 'foo.'
[email protected]('s', ['foo as (select *)', 'foo as(select *)'])
+def test_grouping_identifer_as(s):
+ # issue507
+ p = sqlparse.parse(s)[0]
+ assert isinstance(p.tokens[0], sql.Identifier)
+ token = p.tokens[0].tokens[2]
+ assert token.ttype == T.Keyword
+ assert token.normalized == 'AS'
def test_grouping_identifier_as_invalid():
# issue8
@@ -294,9 +336,10 @@
assert isinstance(p.tokens[0], sql.Case)
-def test_grouping_alias_returns_none():
- # see issue185
- p = sqlparse.parse('foo.bar')[0]
[email protected]('s', ['foo.bar', 'x, y', 'x > y', 'x / y'])
+def test_grouping_alias_returns_none(s):
+ # see issue185 and issue445
+ p = sqlparse.parse(s)[0]
assert len(p.tokens) == 1
assert p.tokens[0].get_alias() is None
@@ -435,15 +478,54 @@
assert comp.right.ttype is T.Number.Integer
-def test_comparison_with_strings():
[email protected]('operator', (
+ '=', '!=', '>', '<', '<=', '>=', '~', '~~', '!~~',
+ 'LIKE', 'NOT LIKE', 'ILIKE', 'NOT ILIKE',
+))
+def test_comparison_with_strings(operator):
# issue148
- p = sqlparse.parse("foo = 'bar'")[0]
+ p = sqlparse.parse("foo {0} 'bar'".format(operator))[0]
assert len(p.tokens) == 1
assert isinstance(p.tokens[0], sql.Comparison)
assert p.tokens[0].right.value == "'bar'"
assert p.tokens[0].right.ttype == T.String.Single
+def test_like_and_ilike_comparison():
+ def validate_where_clause(where_clause, expected_tokens):
+ assert len(where_clause.tokens) == len(expected_tokens)
+ for where_token, expected_token in zip(where_clause, expected_tokens):
+ expected_ttype, expected_value = expected_token
+ if where_token.ttype is not None:
+ assert where_token.match(expected_ttype, expected_value,
regex=True)
+ else:
+ # Certain tokens, such as comparison tokens, do not define a
ttype that can be
+ # matched against. For these tokens, we ensure that the token
instance is of
+ # the expected type and has a value conforming to specified
regular expression
+ import re
+ assert (isinstance(where_token, expected_ttype)
+ and re.match(expected_value, where_token.value))
+
+ [p1] = sqlparse.parse("select * from mytable where mytable.mycolumn LIKE
'expr%' limit 5;")
+ [p1_where] = [token for token in p1 if isinstance(token, sql.Where)]
+ validate_where_clause(p1_where, [
+ (T.Keyword, "where"),
+ (T.Whitespace, None),
+ (sql.Comparison, r"mytable.mycolumn LIKE.*"),
+ (T.Whitespace, None),
+ ])
+
+ [p2] = sqlparse.parse(
+ "select * from mytable where mycolumn NOT ILIKE '-expr' group by
othercolumn;")
+ [p2_where] = [token for token in p2 if isinstance(token, sql.Where)]
+ validate_where_clause(p2_where, [
+ (T.Keyword, "where"),
+ (T.Whitespace, None),
+ (sql.Comparison, r"mycolumn NOT ILIKE.*"),
+ (T.Whitespace, None),
+ ])
+
+
def test_comparison_with_functions():
# issue230
p = sqlparse.parse('foo = DATE(bar.baz)')[0]
@@ -550,3 +632,11 @@
p = sqlparse.parse('1 foo')[0].tokens
assert len(p) == 1
assert p[0].get_alias() == 'foo'
+
+
+def test_grouping_as_cte():
+ p = sqlparse.parse('foo AS WITH apple AS 1, banana AS 2')[0].tokens
+ assert len(p) > 4
+ assert p[0].get_alias() is None
+ assert p[2].value == 'AS'
+ assert p[4].value == 'WITH'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/test_parse.py
new/sqlparse-0.3.1/tests/test_parse.py
--- old/sqlparse-0.3.0/tests/test_parse.py 2019-03-10 06:56:32.000000000
+0100
+++ new/sqlparse-0.3.1/tests/test_parse.py 2019-10-09 11:11:29.000000000
+0200
@@ -431,8 +431,8 @@
s = u"update a t set t.b=1"
stmts = sqlparse.parse(s)
assert len(stmts) == 1
- assert 'a' == stmts[0].get_real_name()
- assert 't' == stmts[0].get_alias()
+ assert 'a' == stmts[0].tokens[2].get_real_name()
+ assert 't' == stmts[0].tokens[2].get_alias()
def test_from_subquery():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/test_regressions.py
new/sqlparse-0.3.1/tests/test_regressions.py
--- old/sqlparse-0.3.0/tests/test_regressions.py 2019-03-11
12:42:41.000000000 +0100
+++ new/sqlparse-0.3.1/tests/test_regressions.py 2019-10-09
10:03:19.000000000 +0200
@@ -373,3 +373,36 @@
'\\copy select * from foo',
keyword_case='upper', identifier_case='capitalize')
assert formatted == '\\copy SELECT * FROM Foo'
+
+
[email protected](reason='Needs to be fixed')
+def test_issue484_comments_and_newlines():
+ formatted = sqlparse.format('\n'.join([
+ 'Create table myTable',
+ '(',
+ ' myId TINYINT NOT NULL, --my special comment',
+ ' myName VARCHAR2(100) NOT NULL',
+ ')']),
+ strip_comments=True)
+ assert formatted == ('\n'.join([
+ 'Create table myTable',
+ '(',
+ ' myId TINYINT NOT NULL,',
+ ' myName VARCHAR2(100) NOT NULL',
+ ')']))
+
+
+def test_issue485_split_multi():
+ p_sql = '''CREATE OR REPLACE RULE ruled_tab_2rules AS ON INSERT
+TO public.ruled_tab
+DO instead (
+select 1;
+select 2;
+);'''
+ assert len(sqlparse.split(p_sql)) == 1
+
+
+def test_issue489_tzcasts():
+ p = sqlparse.parse('select bar at time zone \'UTC\' as foo')[0]
+ assert p.tokens[-1].has_alias() is True
+ assert p.tokens[-1].get_alias() == 'foo'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/test_split.py
new/sqlparse-0.3.1/tests/test_split.py
--- old/sqlparse-0.3.0/tests/test_split.py 2019-03-10 08:54:03.000000000
+0100
+++ new/sqlparse-0.3.1/tests/test_split.py 2019-10-09 10:03:19.000000000
+0200
@@ -52,22 +52,6 @@
assert len(stmts) == 1
-def test_split_slashcomments(load_file):
- sql = load_file('slashcomment.sql')
- stmts = sqlparse.parse(sql)
- assert len(stmts) == 3
- assert ''.join(str(q) for q in stmts) == sql
-
-
[email protected]('s', ['select foo; // comment\n',
- 'select foo; // comment\r',
- 'select foo; // comment\r\n',
- 'select foo; // comment'])
-def test_split_slashcomments_eol(s):
- stmts = sqlparse.parse(s)
- assert len(stmts) == 1
-
-
def test_split_begintag(load_file):
sql = load_file('begintag.sql')
stmts = sqlparse.parse(sql)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/sqlparse-0.3.0/tests/test_tokenize.py
new/sqlparse-0.3.1/tests/test_tokenize.py
--- old/sqlparse-0.3.0/tests/test_tokenize.py 2019-03-11 12:41:06.000000000
+0100
+++ new/sqlparse-0.3.1/tests/test_tokenize.py 2020-01-16 09:20:33.000000000
+0100
@@ -171,6 +171,13 @@
assert p.tokens[0].ttype is T.Keyword
[email protected]('s', ['NULLS FIRST', 'NULLS LAST'])
+def test_parse_nulls(s): # issue487
+ p = sqlparse.parse(s)[0]
+ assert len(p.tokens) == 1
+ assert p.tokens[0].ttype is T.Keyword
+
+
@pytest.mark.parametrize('s', [
'foo',
'Foo',
@@ -197,6 +204,34 @@
assert p.tokens[0].ttype is T.Keyword
[email protected]('s', (
+ "LIKE", "ILIKE", "NOT LIKE", "NOT ILIKE",
+ "NOT LIKE", "NOT ILIKE",
+))
+def test_like_and_ilike_parsed_as_comparisons(s):
+ p = sqlparse.parse(s)[0]
+ assert len(p.tokens) == 1
+ assert p.tokens[0].ttype == T.Operator.Comparison
+
+
[email protected]('s', (
+ "LIKEaaa", "bILIKE", "aaILIKEbb", "NOTLIKE", "NOTILIKE",
+))
+def test_near_like_and_ilike_parsed_appropriately(s):
+ p = sqlparse.parse(s)[0]
+ assert len(p.tokens) == 1
+ assert isinstance(p.tokens[0], sql.Identifier)
+
+
[email protected]('s', (
+ 'AT TIME ZONE \'UTC\'',
+))
+def test_parse_tzcast(s):
+ p = sqlparse.parse(s)[0]
+ assert len(p.tokens) == 1
+ assert p.tokens[0].ttype == T.Keyword.TZCast
+
+
def test_cli_commands():
p = sqlparse.parse('\\copy')[0]
assert len(p.tokens) == 1