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


Reply via email to