├── tests
├── __init__.py
├── test_grouping_sets.yml
├── test_datetime.yml
├── test_additional_lang_support.yml
├── test_parser_convert.yml
├── test_examples.py
├── v0.4.yml
├── v0.3.yml
├── visual_checks.yml
└── test_ast.py
├── MANIFEST.in
├── requirements.txt
├── antlr_tsql
├── __init__.py
├── antlr_py
│ └── __init__.py
├── ast.py
└── tsql.g4
├── pytest.ini
├── Makefile
├── Dockerfile
├── .travis.yml
├── .gitignore
├── setup.py
├── README.md
└── LICENSE
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include requirements.txt
3 | include antlr_tsql/antlr_py/*
4 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | antlr4-python3-runtime~=4.7.2
2 | antlr-ast~=0.7.0
3 | pyyaml~=5.1
4 | pytest~=3.8.1
5 |
--------------------------------------------------------------------------------
/antlr_tsql/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.12.6"
2 | from . import antlr_py as grammar
3 | from . import ast
4 |
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | testpaths = tests
3 |
4 | # TODO: awaiting PR
5 | # https://github.com/RKrahl/pytest-dependency/pull/25
6 | filterwarnings =
7 | ignore::DeprecationWarning
8 |
--------------------------------------------------------------------------------
/antlr_tsql/antlr_py/__init__.py:
--------------------------------------------------------------------------------
1 | from .tsqlLexer import tsqlLexer as Lexer
2 | from .tsqlListener import tsqlListener as Listener
3 | from .tsqlParser import tsqlParser as Parser
4 | from .tsqlVisitor import tsqlVisitor as Visitor
5 |
--------------------------------------------------------------------------------
/tests/test_grouping_sets.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | select_statement:
4 | - "SELECT *
5 | GROUP BY GROUPING SETS
6 | (
7 | (c.CalendarMonth, c.CalendarQuarterName, c.CalendarYear),
8 | (c.CalendarYear),
9 | -- This remains blank; it gives us the grand total
10 | ()
11 | );"
12 |
--------------------------------------------------------------------------------
/tests/test_datetime.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | select_statement:
4 | - "SELECT DATETIMEOFFSETFROMPARTS(2038, 01, 19, 03, 14, 08, 0, 0, 0, 3);"
5 | - "SELECT DATETIMEOFFSETFROMPARTS(2038, 01, 19, 03, 14, 08, 0, 0, 0, 3) AS TimeForChaos;"
6 | - "SELECT DATETIMEOFFSETFROMPARTS(2038, 01, 19, 03, 14, 08, 0, 0, 0, 3) AT TIME ZONE 'Eastern Standard Time' AS TimeForChaos;"
7 |
--------------------------------------------------------------------------------
/tests/test_additional_lang_support.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | select_statement:
4 | - "SELECT STRING_AGG(bean_origin, ',') WITHIN GROUP (ORDER BY bean_origin) AS bean_origins
5 | FROM ratings;"
6 | - "SELECT value
7 | FROM STRING_SPLIT(@phrase, '.');"
8 | - "SELECT
9 | LAST_VALUE(birthdate)
10 | OVER (PARTITION BY country ORDER BY birthdate ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
11 | ) AS youngest_voter
12 | FROM voters;"
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | JS_DIR=antlr_tsql/js
2 | PY_DIR=antlr_tsql/antlr_py
3 |
4 | .PHONY: clean
5 |
6 | all: clean test
7 |
8 | buildpy:
9 | antlr4 -Dlanguage=Python3 -o $(PY_DIR) -visitor antlr_tsql/tsql.g4 \
10 | && mv $(PY_DIR)/antlr_tsql/* $(PY_DIR) && rmdir $(PY_DIR)/antlr_tsql
11 |
12 | buildjs:
13 | antlr4 -Dlanguage=JavaScript -o $(JS_DIR) antlr_tsql/tsql.g4 \
14 | && mv $(JS_DIR)/antlr_tsql/* $(JS_DIR) && rmdir $(JS_DIR)/antlr_tsql
15 |
16 | build: buildpy
17 |
18 | clean:
19 | find . \( -name \*.pyc -o -name \*.pyo -o -name __pycache__ \) -prune -exec rm -rf {} +
20 | rm -rf antlr_tsql.egg-info
21 |
22 | test: clean
23 | pytest
24 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.5
2 |
3 | RUN apt-get update && apt-get install -y \
4 | build-essential \
5 | default-jdk \
6 | maven
7 |
8 | RUN cd /usr/local/lib && curl -O https://www.antlr.org/download/antlr-4.7.1-complete.jar
9 | ENV CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH"
10 | RUN echo "java -Xmx500M -cp \"/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH\" org.antlr.v4.Tool \$@" >> /usr/local/bin/antlr4 && chmod u+x /usr/local/bin/antlr4
11 | RUN echo "alias grun='java org.antlr.v4.runtime.misc.TestRig'" >> ~/.bashrc
12 |
13 | COPY . /usr/src/app
14 | WORKDIR /usr/src/app
15 |
16 | RUN pip install -r requirements.txt
17 | RUN pip install -e .
18 |
--------------------------------------------------------------------------------
/tests/test_parser_convert.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | select_statement:
4 | - "SELECT PARSE(DateText AS DATE USING 'de-de');"
5 | - "SELECT PARSE(DateText AS DATE USING 'de-de') AS StringAsDate;"
6 | - "SELECT PARSE(DateText AS DATETIME2(7) USING 'de-de') AS StringAsDateTime2;"
7 | - "SELECT TRY_CONVERT(DATETIME2(3), it.EventDate);"
8 | - "SELECT PERCENTILE_CONT(0.5)
9 | WITHIN GROUP (ORDER BY ir.NumberOfIncidents DESC)
10 | OVER (PARTITION BY it.IncidentType)"
11 | - "SELECT TRY_CONVERT(DATETIME2(3), @GoodDateINTL);"
12 | - "SELECT TRY_CAST(@GoodDateDE AS DATE);"
13 | - "SELECT TRY_PARSE(@GoodDateDE AS DATE USING 'de-de');"
14 |
--------------------------------------------------------------------------------
/tests/test_examples.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import os
3 | from antlr_tsql import ast
4 | from tests.test_ast import ast_examples_parse
5 |
6 |
7 | def load_dump(fname):
8 | import yaml
9 |
10 | dirname = os.path.dirname(__file__)
11 | dump_data = yaml.safe_load(open(dirname + "/" + fname))
12 |
13 | all_cmds = []
14 | for start, cmds in dump_data.items():
15 | for cmd, res in cmds:
16 | all_cmds.append((start, cmd, res))
17 | return all_cmds
18 |
19 |
20 | @pytest.mark.parametrize(
21 | "start,cmd,res",
22 | [
23 | *load_dump(ast_examples_parse("visual_checks.yml")),
24 | *load_dump(ast_examples_parse("v0.3.yml")),
25 | *load_dump(ast_examples_parse("v0.4.yml")),
26 | *load_dump(ast_examples_parse("test_datetime.yml")),
27 | *load_dump(ast_examples_parse("test_parser_convert.yml")),
28 | *load_dump(ast_examples_parse("test_grouping_sets.yml")),
29 | *load_dump(ast_examples_parse("test_additional_lang_support.yml"))
30 | ],
31 | )
32 | def test_dump(start, cmd, res):
33 | assert repr(ast.parse(cmd, start, strict=True)) == res
34 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: python
3 | python:
4 | - '3.5'
5 | services:
6 | - docker
7 | before_install:
8 | - docker build -t antlr_tsql .
9 | script: docker run -v $(pwd):/usr/src/app antlr_tsql make build test
10 | deploy:
11 | provider: pypi
12 | user: datacamp
13 | password:
14 | secure: FtfGuRIwye1Va1uU4iOgESpRl5FSxbhi6hqQ/4QIhyZdpr8+YJrjRw8LbiSpPKCgQBXwN37Xif16k2ySEearae0pGmB7Kg8FXpo9VubNBtcUyfa0EmJAVGQRgjFFz90nvB75UvV5r8QMSVq9erZjZ36VR+OqKb/GdiZVDDygktIEGTJkR3pS0Hzwy5UfpuTpnGIMRDDrGBQKcLqXKCUa3uytXttul7BwP0wrhvnpEdCAN/LMUS+K0fWweBwrd3zQ5f6Ee3HrZpXrX5d5sE7TxSwhz4/o20I0nE21q78gjvoDziEKOxP96aNEeWTGgdRUljIm+Hv0rsV6FcURnGLfqmHdynM5mcrAF9KS39i19jZPVzDK4r/HhsfN+3E+ZVubOsjXcunwhTDXWqpoNuxExzBE2Gw8HJ9BEf9PJZ3bQH61FiKoaiOHgfOccH3E20zOkEjG6X9pKdHzUF0DcxKnntv5D1kGMhsAO8dm3/cV7xJiu8fjgn3tzPOVzxXG3Wxc7w/icL/MMCUFrfNRZG8NWY82GGJB3qwBkIRoSiYWtcz1BMwUIo4kPU/AqRlhetrlWAP/StJ3walREgrk14snTwT6MzrHspNwbhWRaoNJzVa4dAlN1cnAL7KAoJVPEtca/gW6CFlBD1JlY11PXVjHCdVdk78UDrUszHZig4w7dEA=
15 | on:
16 | tags: true
17 | distributions: sdist bdist_wheel
18 | repo: datacamp/antlr-tsql
19 | skip_cleanup: true
20 | skip_upload_docs: true
21 |
--------------------------------------------------------------------------------
/tests/v0.4.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | function_call:
4 | - "IIF( 1 > 2, 'yes', 'no')"
5 | insert_statement:
6 | # TODO with clause shaping
7 | - "WITH somevar AS (SELECT x FROM y) INSERT INTO simple VALUES (1,2,3), (4,5,6)"
8 | - |
9 | INSERT INTO SalesLT.Product (Name, ProductNumber, StandardCost, ListPrice, ProductCategoryID, SellStartDate)
10 | VALUES
11 | ('A', 'B', 1, 2, 3, GETDATE())
12 | ('X', 'Y', 2.1, 3.1, 4, GETDATE())
13 | delete_statement:
14 | - |
15 | DELETE FROM SalesLT.Product
16 | WHERE ProductCategoryID =
17 | (SELECT ProductCategoryID FROM SalesLT.ProductCategory WHERE Name = 'Bells and Horns');
18 | update_statement:
19 | - |
20 | UPDATE SalesLT.Product
21 | SET ListPrice = ListPrice * 1.1
22 | WHERE ProductCategoryID =
23 | (SELECT ProductCategoryID FROM SalesLT.ProductCategory WHERE Name = 'Bells and Horns');
24 | value_list:
25 | - "(1,2,a), (4,s,6+1)"
26 | # TODO: fix sqlwhat-viewer to not try to call [somelist].dump
27 | #column_name_list:
28 | # - "a, b, c, [d]"
29 |
--------------------------------------------------------------------------------
/tests/v0.3.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | simple_id:
4 | - "size"
5 | query_specification:
6 | - "SELECT DISTINCT x FROM y" # fixed
7 | query_expression:
8 | - "( SELECT x FROM y )"
9 | - "SELECT x FROM y UNION SELECT a FROM b"
10 | select_statement:
11 | - "WITH somevar AS (SELECT x FROM y ORDER BY id) SELECT a FROM b"
12 | - "SELECT a FROM b ORDER by id"
13 | - "SELECT a FROM b OPTION ( FAST 1 )"
14 | - "SELECT a FROM b FOR BROWSE"
15 | - "SELECT a FROM b UNION SELECT x FROM y ORDER BY id"
16 | - "SELECT a FROM b JOIN c ON id = id UNION SELECT x FROM y as z ORDER by id"
17 | order_by_clause:
18 | - "ORDER BY id ASC"
19 | - "ORDER BY id ASC, name DESC"
20 | - "ORDER BY id OFFSET 10 ROWS"
21 | - "ORDER BY id OFFSET 10 ROWS FETCH FIRST 2 ROWS ONLY"
22 | table_source:
23 | - "(a JOIN b on id = id)"
24 | - "a JOIN b on id = id"
25 | - "a JOIN b ON a.id = b.id"
26 | - "a JOIN b on ida = idb JOIN c on idb = idc"
27 | - "a INNER JOIN b on id = id"
28 | - "a OUTER HASH JOIN b on id =id"
29 | - "a CROSS JOIN b"
30 | - "a CROSS APPLY b"
31 | - "a LEFT OUTER APPLY b"
32 | table_source_item:
33 | - "a AS b"
34 | # TODO
35 | - "a AS b WITH (INDEX = x)"
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore hidden vagrant folder
2 | .vagrant
3 | # Ignore java files
4 | *.java
5 | *.class
6 | # Vim swapfiles
7 | .*.swp
8 |
9 | # Python ----------------------------------------------------------------------
10 | # Byte-compiled / optimized / DLL files
11 | __pycache__/
12 | *.py[cod]
13 | *$py.class
14 |
15 | # C extensions
16 | *.so
17 |
18 | # Distribution / packaging
19 | .Python
20 | env/
21 | build/
22 | develop-eggs/
23 | dist/
24 | downloads/
25 | eggs/
26 | .eggs/
27 | lib/
28 | lib64/
29 | parts/
30 | sdist/
31 | var/
32 | *.egg-info/
33 | .installed.cfg
34 | *.egg
35 |
36 | # PyInstaller
37 | # Usually these files are written by a python script from a template
38 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
39 | *.manifest
40 | *.spec
41 |
42 | # Installer logs
43 | pip-log.txt
44 | pip-delete-this-directory.txt
45 |
46 | # Unit test / coverage reports
47 | htmlcov/
48 | .tox/
49 | .coverage
50 | .coverage.*
51 | .cache
52 | nosetests.xml
53 | coverage.xml
54 | *,cover
55 | .hypothesis/
56 |
57 | # Translations
58 | *.mo
59 | *.pot
60 |
61 | # Django stuff:
62 | *.log
63 | local_settings.py
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Ipython Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # Mac stuff -------------------------------------------------------------------
78 | .DS_Store
79 | tests/.DS_Store
80 |
81 | # Custom stuff ------------
82 | tests/dump_*.yml
83 | antlr_tsql/js/*
84 | !antlr_tsql/js/index.js
85 | antlr_tsql/antlr_py/*
86 | !antlr_tsql/antlr_py/__init__.py
87 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import re
4 | import ast
5 | from os import path
6 | from setuptools import setup
7 |
8 | PACKAGE_NAME = "antlr_tsql"
9 | REQUIREMENT_NAMES = ["antlr-ast", "antlr4-python3-runtime", "pyyaml"]
10 |
11 | HERE = path.abspath(path.dirname(__file__))
12 | VERSION_FILE = path.join(HERE, PACKAGE_NAME, "__init__.py")
13 | REQUIREMENTS_FILE = path.join(HERE, "requirements.txt")
14 | README_FILE = path.join(HERE, "README.md")
15 |
16 | with open(VERSION_FILE, encoding="utf-8") as fp:
17 | _version_re = re.compile(r"__version__\s+=\s+(.*)")
18 | VERSION = str(ast.literal_eval(_version_re.search(fp.read()).group(1)))
19 | with open(REQUIREMENTS_FILE, encoding="utf-8") as fp:
20 | req_txt = fp.read()
21 | _requirements_re_template = r"^({}(?:\s*[~<>=]+\s*\S*)?)\s*(?:#.*)?$"
22 | REQUIREMENTS = [
23 | re.search(_requirements_re_template.format(requirement), req_txt, re.M).group(0)
24 | for requirement in REQUIREMENT_NAMES
25 | ]
26 | with open(README_FILE, encoding="utf-8") as fp:
27 | README = fp.read()
28 |
29 | setup(
30 | name=PACKAGE_NAME.replace("_", "-"),
31 | version=VERSION,
32 | packages=[PACKAGE_NAME],
33 | install_requires=REQUIREMENTS,
34 | description="A transact sql parser, written in Antlr4",
35 | long_description=README,
36 | long_description_content_type="text/markdown",
37 | author="Michael Chow",
38 | author_email="michael@datacamp.com",
39 | maintainer="Jeroen Hermans",
40 | maintainer_email="content-engineering@datacamp.com",
41 | url="https://github.com/datacamp/antlr-tsql",
42 | include_package_data=True,
43 | classifiers=[
44 | "Programming Language :: Python :: 3",
45 | "License :: OSI Approved :: GNU Affero General Public License v3",
46 | "Operating System :: OS Independent",
47 | ],
48 | )
49 |
--------------------------------------------------------------------------------
/tests/visual_checks.yml:
--------------------------------------------------------------------------------
1 | parser_name: tsql
2 | code:
3 | tsql_file:
4 | - "SELECT * FROM a.b;\nSELECT * FROM x.y;\nGO"
5 | query_specification:
6 | - "SELECT * FROM x.y"
7 | - "SELECT * FROM x.y WHERE id > 2 AND name NOT LIKE '%ichael'"
8 | search_condition:
9 | - "id > 111 AND id < 222 OR NOT id = 333"
10 | select_list_elem:
11 | # TODO what is the "$" all about?
12 | - "x.y"
13 | - "x.*"
14 | # aliasing
15 | - "x"
16 | - "x as y"
17 | - "x = y"
18 | full_column_name:
19 | - "some_column"
20 | - "some_table.some_column"
21 | full_table_name:
22 | - "serv.db.sch.tab"
23 | - "db.sch.tab"
24 | - "sch.tab"
25 | expression:
26 | # binary_operator_expression
27 | - "1 * 1"
28 | - "1 + 1"
29 | - "1 < 2"
30 | # constant
31 | - "-1.0"
32 | # subquery_expression
33 | - "(SELECT x FROM sys.y)"
34 | # bracket_expression
35 | - "( 1 + 1 )"
36 | # unary_operator_expression
37 | - "-id"
38 | # case_expression
39 | - "CASE WHEN ShipDate IS NULL THEN 'Awaiting Shipment' WHEN 1 > 2 THEN 'c' ELSE 'Shipped' END"
40 | predicate:
41 | - "EXISTS (SELECT x FROM y)"
42 | - "a > b"
43 | - "a > ALL ( SELECT x FROM y)"
44 | - "a BETWEEN 1 AND 5"
45 | - "a NOT BETWEEN 1 AND 5"
46 | - "a IN (1,2,3)"
47 | - "a IN (SELECT x FROM y)"
48 | - "a LIKE '%abc'"
49 | - "a LIKE '%abc' ESCAPE ''"
50 | - "(a > b)"
51 | function_call:
52 | # aggregate_windowed_function
53 | - "cOuNt ( * )"
54 | - "COUNT(ALL id = 1) OVER ( PARTITION BY a + b ORDER BY a)"
55 | - "COUNT(*)"
56 | - "AVG ( ALL id )"
57 | - "GROUPING_ID ( a, b )"
58 | # ranking windowed_function
59 | - "RANK () OVER ( PARTITION BY a + b ORDER BY a)"
60 | - "NTILE ( a + b )"
61 | # standard_call
62 | - "COALESCE ( a, b )"
63 | - "BINARY_CHECKSUM (*)"
64 | - "DATEADD ( a, 1 + 1, 2 + 2)"
65 | - "RIGHT ( 1 + 1, 2 + 2 )"
66 | # simple_call
67 | - "SESSION_USER"
68 | # cast_call
69 | - "CAST ( a as varchar )"
70 |
--------------------------------------------------------------------------------
/tests/test_ast.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import os
3 | from antlr_ast.ast import AntlrException
4 | from antlr_tsql import ast
5 |
6 |
7 | def test_ast_parse_strict():
8 | with pytest.raises(AntlrException):
9 | ast.parse("SELECT x FROM ____!", strict=True) # ____! is ungrammatical
10 | # Test export of exception class
11 | with pytest.raises(ast.ParseError):
12 | ast.parse("SELECT x FROM ____!", strict=True) # ____! is ungrammatical
13 |
14 |
15 | # def test_ast_parsing_unshaped():
16 | # sql_txt = "INSERT INTO sometable VALUES (1, 2, 3);"
17 | # tree = ast.parse(sql_txt)
18 | # assert isinstance(tree, ast.Script)
19 | # assert sql_txt.replace(" ", "") == tree.batch[0].replace(
20 | # " ", ""
21 | # ) # currently is just raw text
22 |
23 |
24 | def ast_examples_parse(fname):
25 | # just make sure they don't throw error for now..
26 | import yaml
27 |
28 | dirname = os.path.dirname(__file__)
29 | data = yaml.safe_load(open(dirname + "/" + fname))
30 | res = {}
31 | for start, cmds in data["code"].items():
32 | res[start] = []
33 | for cmd in cmds:
34 | res[start].append([cmd, repr(ast.parse(cmd, start, strict=True))])
35 | print(res)
36 | filename = "dump_" + fname
37 | with open(dirname + "/" + filename, "w") as out_f:
38 | yaml.dump(res, out_f)
39 | return filename
40 |
41 |
42 | @pytest.mark.parametrize("fname", ["visual_checks.yml", "v0.3.yml", "v0.4.yml"])
43 | def test_ast_examples_parse(fname):
44 | return ast_examples_parse(fname)
45 |
46 |
47 | @pytest.mark.parametrize(
48 | "stu",
49 | [
50 | "SELECT \"Preserve\" FROM B WHERE B.NAME = 'Casing'",
51 | "SELECT \"Preserve\" FROM b WHERE b.NAME = 'Casing'",
52 | "SELECT \"Preserve\" FROM b WHERE b.name = 'Casing'",
53 | "select \"Preserve\" FROM B WHERE B.NAME = 'Casing'",
54 | "select \"Preserve\" from B where B.NAME = 'Casing'",
55 | "select \"Preserve\" from b WHERE b.name = 'Casing'",
56 | ],
57 | )
58 | def test_case_insensitivity(stu):
59 | lowercase = "select \"Preserve\" from b where b.name = 'Casing'"
60 | assert repr(ast.parse(lowercase, strict=True)) == repr(
61 | ast.parse(stu, strict=True)
62 | )
63 |
64 |
65 | @pytest.mark.parametrize(
66 | "stu",
67 | [
68 | "SELECT \"Preserve\" FROM B WHERE B.NAME = 'casing'",
69 | "SELECT \"Preserve\" FROM b WHERE b.NAME = 'CASING'",
70 | "SELECT \"preserve\" FROM b WHERE b.name = 'Casing'",
71 | "select \"PRESERVE\" FROM B WHERE B.NAME = 'Casing'",
72 | ],
73 | )
74 | def test_case_sensitivity(stu):
75 | lowercase = "select \"Preserve\" from b where b.name = 'Casing'"
76 | assert repr(ast.parse(lowercase, strict=True)) != repr(
77 | ast.parse(stu, strict=True)
78 | )
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # antlr-tsql
2 |
3 | [](https://travis-ci.org/datacamp/antlr-tsql)
4 | [](https://badge.fury.io/py/antlr-tsql)
5 |
6 | ## Development
7 |
8 | ANTLR requires Java, so we suggest you use Docker when building grammars. The `Makefile` contains directives to clean, build, test and deploy the ANTLR grammar. It does not run Docker itself, so run `make` inside Docker.
9 |
10 | ### Build the grammar
11 |
12 | ```bash
13 | # Build the docker container
14 | docker build -t antlr_tsql .
15 |
16 | # Run the container to build the python grammar
17 | # Write parser files to local file system through volume mounting
18 | docker run -it -v ${PWD}:/usr/src/app antlr_tsql make build
19 | ```
20 |
21 | ### Set up the Python module
22 |
23 | Now that the Python parsing files are available, you can install them with `pip`:
24 |
25 | ```bash
26 | pip install -r requirements.txt
27 | pip install -e .
28 | ```
29 |
30 | And parse SQL code in Python:
31 |
32 | ```python
33 | from antlr_tsql import ast
34 | ast.parse("SELECT a from b")
35 | ```
36 |
37 | ### Using the AST viewer
38 |
39 | If you're actively developing on the ANLTR grammar or the tree shaping, it's a good idea to set up the [AST viewer](https://github.com/datacamp/ast-viewer) locally so you can immediately see the impact of your changes in a visual way.
40 |
41 | - Clone the ast-viewer repo and build the Docker image according to the instructions.
42 | - Spin up a docker container that volume mounts the Python package, symlink-installs the package and runs the server on port 3000:
43 |
44 | ```bash
45 | docker run -it \
46 | -u root \
47 | -v ~/workspace/antlr-tsql:/app/app/antlr-tsql \
48 | -p 3000:3000 \
49 | ast-viewer \
50 | /bin/bash -c "echo 'Install development requirements in development:' \
51 | && pip install --no-deps -e app/antlr-tsql \
52 | && python3 run.py"
53 | ```
54 |
55 | When simultaneously developing other packages, volume mount and install those too:
56 |
57 | ```bash
58 | docker run -it \
59 | -u root \
60 | -v ~/workspace/antlr-ast:/app/app/antlr-ast \
61 | -v ~/workspace/antlr-plsql:/app/app/antlr-plsql \
62 | -v ~/workspace/antlr-tsql:/app/app/antlr-tsql \
63 | -p 3000:3000 \
64 | ast-viewer \
65 | /bin/bash -c "echo 'Install development requirements in development:' \
66 | && pip install --no-deps -e app/antlr-ast \
67 | && pip install --no-deps -e app/antlr-plsql \
68 | && pip install --no-deps -e app/antlr-tsql \
69 | && python3 run.py"
70 | ```
71 |
72 | - If you update the tree shaping logic in this repo, the app will auto-update.
73 | - If you change the grammar, you will have to first rebuild the grammar (with the `antlr_tsql` docker image) and restart the `ast-viewer` container.
74 |
75 | ### Run tests
76 |
77 | ```bash
78 | # Similar to building the grammar, but running tests
79 | # and not saving the generated files
80 | docker build -t antlr_tsql .
81 | docker run -t antlr_tsql make build test
82 | ```
83 |
84 | Or run the test locally, first build the grammar then run:
85 |
86 | ```python
87 | pytest
88 | ```
89 |
90 | ## Travis deployment
91 |
92 | - Builds the Docker image.
93 | - Runs the Docker image to build the grammar and run the unit tests.
94 | - Deploys the resulting python files to PyPi when a new release is made, so they can be installed easily.
95 |
--------------------------------------------------------------------------------
/antlr_tsql/ast.py:
--------------------------------------------------------------------------------
1 | # TODO: create speaker
2 | import yaml
3 | import pkg_resources
4 | import inspect
5 |
6 | from antlr_ast.ast import (
7 | parse as parse_ast,
8 | process_tree,
9 | AliasNode,
10 | BaseNodeTransformer,
11 | get_alias_nodes,
12 | Speaker,
13 | # references for export: # TODO: put package exports in __init__?
14 | Terminal,
15 | BaseNode as AstNode,
16 | AntlrException as ParseError,
17 | dump_node, # TODO only used in tests
18 | BaseAstVisitor,
19 | )
20 | from antlr_ast.inputstream import CaseTransformInputStream
21 |
22 | from antlr_tsql import grammar
23 |
24 |
25 | def parse(sql_text, start="tsql_file", **kwargs):
26 | antlr_tree = parse_ast(
27 | grammar, sql_text, start, transform=CaseTransformInputStream.UPPER, **kwargs
28 | )
29 | simple_tree = process_tree(
30 | antlr_tree, base_visitor_cls=AstVisitor, transformer_cls=Transformer
31 | )
32 |
33 | return simple_tree
34 |
35 |
36 | # AliasNodes
37 |
38 |
39 | class Script(AliasNode):
40 | _fields_spec = ["batch"]
41 | _rules = ["tsql_file"]
42 | _priority = 0
43 |
44 |
45 | class Batch(AliasNode):
46 | _fields_spec = ["statements=sql_clauses"]
47 | _rules = ["batch"]
48 | _priority = 0
49 |
50 |
51 | class SelectStmt(AliasNode):
52 | _fields_spec = [
53 | "pref",
54 | "target_list=select_list",
55 | "top_clause",
56 | "into_clause=table_name",
57 | "from_clause=table_sources",
58 | "where_clause=where",
59 | "group_by_clause=group_by_item",
60 | "having",
61 | "with_expr=with_expression",
62 | "order_by_clause",
63 | "for_clause",
64 | "option_clause",
65 | "group_by_grouping_sets",
66 | ]
67 |
68 | _rules = ["query_specification", ("select_statement", "_from_select_rule")]
69 |
70 | @classmethod
71 | def _from_select_rule(cls, node, helper):
72 | # This node may be a Union
73 | query_node = node
74 | while query_node.query_expression and not helper.isinstance(
75 | query_node, "Union_query_expression"
76 | ):
77 | query_node = query_node.query_expression
78 |
79 | if query_node.query_specification:
80 | query_node = cls.from_spec(query_node.query_specification)
81 |
82 | # combine with fields from outer node
83 | outer = cls.from_spec(node)
84 | for field in cls._fields:
85 | value = getattr(outer, field)
86 | if value:
87 | setattr(query_node, field, value)
88 |
89 | return query_node
90 | else:
91 | return query_node
92 |
93 |
94 | class InsertStmt(AliasNode):
95 | _fields_spec = [
96 | "with_expr=with_expression",
97 | "top_clause=top_clause_dm",
98 | "into=INTO",
99 | "target=ddl_object",
100 | "target=rowset_function_limited", # TODO make these own rule in grammar?
101 | "table_hints=insert_with_table_hints",
102 | "column_names=column_name_list",
103 | "output_clause",
104 | "values_clause=insert_statement_value",
105 | "for_clause",
106 | "option_clause",
107 | ]
108 |
109 | _rules = ["insert_statement"]
110 |
111 |
112 | class ValueList(AliasNode):
113 | _fields_spec = ["values=expression_list"]
114 | _rules = ["value_list"]
115 |
116 |
117 | class DeleteStmt(AliasNode):
118 | _fields_spec = [
119 | "with_expr=with_expression",
120 | "top_clause=top_clause_dm",
121 | "from_clause",
122 | "from_clause=delete_statement_from",
123 | "table_hints=insert_with_table_hints",
124 | "output_clause",
125 | "from_source=table_sources",
126 | "where_clause=where_clause_dml",
127 | "for_clause",
128 | "option_clause",
129 | ]
130 |
131 | _rules = ["delete_statement"]
132 |
133 |
134 | class UpdateStmt(AliasNode):
135 | _fields_spec = [
136 | "with_expr=with_expression",
137 | "top_clause=top_clause_dm",
138 | "target=ddl_object",
139 | "target=rowset_function_limited", # TODO make these own rule in grammar?
140 | "table_hints=insert_with_table_hints",
141 | "set_clause=update_elem",
142 | "output_clause",
143 | "from_source=table_sources",
144 | "where_clause=where_clause_dml",
145 | "for_clause",
146 | "option_clause",
147 | ]
148 |
149 | _rules = ["update_statement"]
150 |
151 |
152 | class UpdateElem(AliasNode):
153 | _fields_spec = ["name=full_column_name", "name", "expression"]
154 | _rules = ["update_elem"]
155 |
156 |
157 | class DeclareStmt(AliasNode):
158 | _fields_spec = [
159 | "variable=LOCAL_ID",
160 | "variable=cursor_name",
161 | "value=declare_set_cursor_common",
162 | "declare_local",
163 | "table_type_definition", # TODO: improve
164 | ]
165 | _rules = ["declare_statement", "declare_cursor"]
166 |
167 |
168 | class DeclareLocal(AliasNode):
169 | _fields_spec = ["name=LOCAL_ID", "type=data_type", "value=expression"]
170 | _rules = ["declare_local"]
171 |
172 |
173 | class CursorStmt(AliasNode):
174 | _fields_spec = ["type", "variable=cursor_name"]
175 | _rules = [("cursor_statement", "_from_cursor")]
176 |
177 | @classmethod
178 | def _from_cursor(cls, node):
179 | has_own_cursor_alias = node.declare_cursor or node.fetch_cursor
180 | if has_own_cursor_alias:
181 | return has_own_cursor_alias
182 | alias = cls.from_spec(node)
183 | # TODO: combine() instead of children + keyword case convention
184 | alias.type = node.children[0].get_text().upper()
185 | return alias
186 |
187 |
188 | class FetchStmt(AliasNode):
189 | _fields_spec = ["type=FETCH", "source=cursor_name", "vars=LOCAL_ID"]
190 | _rules = ["fetch_cursor"]
191 |
192 |
193 | # TODO FetchType(type, number)
194 |
195 | # TODO primitive expression
196 |
197 |
198 | # TODO
199 | class SetStmt(AliasNode):
200 | _fields_spec = [
201 | "type=set_special.set_type",
202 | "key=set_special.key",
203 | "value=set_special.value",
204 | "value=set_special.constant_LOCAL_ID",
205 | "value=set_special.on_off",
206 | ]
207 | _rules = ["set_statement"]
208 |
209 |
210 | # TODO
211 | class PrintStmt(AliasNode):
212 | _fields_spec = []
213 | _rules = ["print_statement"]
214 |
215 |
216 | class Union(AliasNode):
217 | _fields_spec = ["left", "op", "right"]
218 | _rules = ["union_query_expression"]
219 |
220 |
221 | class Identifier(AliasNode):
222 | # should have server, database, schema, table, name
223 | _fields_spec = ["server", "database", "schema", "table", "name", "name=procedure"]
224 | _rules = [
225 | "full_table_name",
226 | "table_name",
227 | "func_proc_name",
228 | ("full_column_name", "_from_full_column_name"),
229 | ]
230 |
231 | @classmethod
232 | def _from_full_column_name(cls, node):
233 | if node.table:
234 | ident = cls.from_spec(node.table)
235 | ident.name = node.name
236 | return ident
237 |
238 | return cls.from_spec(node)
239 |
240 |
241 | class WhileStmt(AliasNode):
242 | _fields_spec = ["search_condition", "body=sql_clause"]
243 | _rules = ["while_statement"]
244 |
245 |
246 | class Body(AliasNode):
247 | _fields_spec = ["statements=sql_clauses"]
248 | _rules = ["block_statement"]
249 |
250 |
251 | class TableAliasExpr(AliasNode):
252 | _fields_spec = ["alias=r_id", "alias_columns=column_name_list", "select_statement"]
253 | _rules = ["common_table_expression"]
254 |
255 |
256 | class AliasExpr(AliasNode):
257 | _fields_spec = ["expr=expression", "alias=table_alias.r_id", "alias=column_alias"]
258 | _rules = [
259 | (
260 | "table_source_item_name",
261 | "_from_source_table_item",
262 | ), # TODO: vs TableAliasExpr?
263 | ("select_list_elem", "_from_select_list_elem"),
264 | ]
265 |
266 | @classmethod
267 | def _from_select_list_elem(cls, node):
268 | if node.alias:
269 | return cls.from_spec(node)
270 | elif node.a_star:
271 | tab = node.table_name
272 | ident = tab or Identifier.from_spec(node)
273 | ident.name = node.a_star
274 | return ident
275 | else:
276 | return node.expression # TODO visitChildren -> fields
277 |
278 | @classmethod
279 | def _from_source_table_item(cls, node):
280 | if node.with_table_hints:
281 | return node # TODO visitChildren -> fields
282 |
283 | if node.table_alias:
284 | alias = cls.from_spec(node)
285 | alias.expr = node.children[0]
286 | return alias
287 | else:
288 | return node # TODO visitChildren -> fields
289 |
290 |
291 | class Star(AliasNode):
292 | _fields_spec = []
293 |
294 |
295 | class BinaryExpr(AliasNode):
296 | _fields_spec = [
297 | "left",
298 | "op",
299 | "op=comparison_operator",
300 | "right",
301 | "right=subquery",
302 | "right=expression_list",
303 | ]
304 |
305 | _rules = [
306 | "binary_operator_expression",
307 | "binary_operator_expression2",
308 | "search_cond_and",
309 | "search_cond_or",
310 | ("binary_mod_expression", "_from_mod"),
311 | ("binary_in_expression", "_from_mod"),
312 | ]
313 |
314 | @classmethod
315 | def _from_mod(cls, node):
316 | bin_expr = BinaryExpr.from_spec(node)
317 | if node.NOT:
318 | return UnaryExpr(node, {"op": node.NOT, "expr": bin_expr})
319 |
320 | return bin_expr
321 |
322 |
323 | class UnaryExpr(AliasNode):
324 | _fields_spec = ["op", "expr=expression"]
325 | _rules = ["unary_operator_expression%s" % ii for ii in ("", 2, 3)]
326 |
327 |
328 | class TopExpr(AliasNode):
329 | _fields_spec = ["expr=expression", "percent=PERCENT", "with_ties=WITH"]
330 | _rules = ["top_clause", "top_clause_dm"]
331 |
332 |
333 | class OrderByExpr(AliasNode):
334 | _fields_spec = ["expr=order_by_expression", "offset", "fetch=fetch_expression"]
335 | _rules = ["order_by_clause"]
336 |
337 |
338 | class GroupByGroupingSets(AliasNode):
339 | _fields_spec = ["grouping_set"]
340 | _rules = ["group_by_grouping_sets"]
341 |
342 |
343 | class SortBy(AliasNode):
344 | _fields_spec = ["expr=expression", "direction"]
345 | _rules = ["order_by_expression"]
346 |
347 |
348 | class TimeZoneConversion(AliasNode):
349 | _fields_spec = ["expr=left", "timezone=right"]
350 | _rules = ["conversion_expression"]
351 |
352 |
353 | class JoinExpr(AliasNode):
354 | _fields_spec = [
355 | "left",
356 | "join_type=op",
357 | "join_type",
358 | "right" "source=table_source",
359 | "cond=search_condition",
360 | ]
361 | _rules = ["standard_join", "cross_join", ("apply_join", "_from_apply")]
362 |
363 | @classmethod
364 | def _from_apply(cls, node):
365 | join_expr = JoinExpr.from_spec(node)
366 | if node.APPLY: # TODO convention for keywords
367 | join_expr.join_type = str(join_expr.join_type) + " APPLY"
368 |
369 | return join_expr
370 |
371 | @classmethod
372 | def _from_table_source_item_joined(cls, node):
373 | return node.join_part # TODO: no return before?
374 |
375 |
376 | class Case(AliasNode):
377 | _fields_spec = [
378 | "input=caseExpr",
379 | "switches=switch_search_condition_section",
380 | "switches=switch_section",
381 | "else_expr=elseExpr",
382 | ]
383 | _rules = ["case_expression"]
384 |
385 |
386 | class CaseWhen(AliasNode):
387 | _fields_spec = ["when=whenExpr", "then=thenExpr"]
388 | _rules = ["switch_section", "switch_search_condition_section"]
389 |
390 |
391 | class IfElse(AliasNode):
392 | _fields_spec = ["search_condition", "if_expr", "else_expr"]
393 | _rules = ["if_statement"]
394 |
395 |
396 | class OverClause(AliasNode):
397 | _fields_spec = [
398 | "partition=expression_list",
399 | "order_by_clause",
400 | "row_or_range_clause",
401 | ]
402 | _rules = ["over_clause"]
403 |
404 |
405 | class Sublink(AliasNode):
406 | _fields_spec = ["test_expr", "op", "pref", "select=subquery"]
407 | _rules = ["sublink_expression"]
408 |
409 |
410 | from collections.abc import Sequence
411 |
412 |
413 | class Call(AliasNode):
414 | _fields_spec = [
415 | "name",
416 | "pref=all_distinct",
417 | "args=expression_list",
418 | "args=expression",
419 | "over_clause",
420 | "using",
421 | ]
422 |
423 | _rules = [
424 | ("standard_call", "_from_standard"),
425 | ("simple_call", "_from_simple"),
426 | ("aggregate_windowed_function", "_from_aggregate"),
427 | ("ranking_windowed_function", "_from_aggregate"),
428 | ("next_value_for_function", "_from_aggregate"),
429 | ("cast_call", "_from_cast"),
430 | ("expression_call", "_from_expression"),
431 | ]
432 |
433 | @classmethod
434 | def _from_standard(cls, node):
435 | alias = cls.from_spec(node)
436 | alias.name = node.children[0]
437 |
438 | # calls where the expression_list rule handles the args
439 | if node.expression_list:
440 | alias.args = node.expression_list
441 | # calls where args are explicitly comma separated
442 | else:
443 | # TODO use combine()?
444 | # find commas
445 | alias.args = []
446 | for ii, c in enumerate(node.children[2:-1], 2): # skip name and '('
447 | if not c == ",":
448 | alias.args.append(c)
449 |
450 | return alias
451 |
452 | @staticmethod
453 | def get_name(node): # TODO
454 | return node.children[0]
455 |
456 | @classmethod
457 | def _from_simple(cls, node):
458 | return cls(node, {"name": cls.get_name(node), "args": []})
459 |
460 | @classmethod
461 | def _from_aggregate(cls, node):
462 | alias = cls.from_spec(node)
463 | alias.name = cls.get_name(node)
464 |
465 | if alias.args is None:
466 | alias.args = []
467 | elif not isinstance(alias.args, Sequence):
468 | alias.args = [alias.args]
469 | return alias
470 |
471 | @classmethod
472 | def _from_cast(cls, node):
473 | return cls(
474 | node,
475 | {
476 | "name": cls.get_name(node),
477 | "args": [
478 | AliasExpr(node, {"expr": node.expression, "alias": node.alias})
479 | ],
480 | },
481 | )
482 |
483 | @classmethod
484 | def _from_expression(cls, node):
485 | return cls(
486 | node,
487 | {
488 | "name": cls.get_name(node),
489 | "args": [AliasExpr(node, {"expr": node.left, "alias": node.alias})],
490 | "using": node.right,
491 | },
492 | )
493 |
494 |
495 | # PARSE TREE VISITOR ----------------------------------------------------------
496 |
497 |
498 | class Transformer(BaseNodeTransformer):
499 | @staticmethod
500 | def visit_Constant(node):
501 | return node
502 |
503 | @staticmethod
504 | def visit_Sign(node):
505 | # TODO strip + sign from int?
506 | return Terminal.from_text(node.get_text(), node._ctx)
507 |
508 | @staticmethod
509 | def visit_Comparison_operator(node):
510 | return Terminal.from_text(node.get_text(), node._ctx)
511 |
512 | @staticmethod
513 | def visit_With_expression(node):
514 | return node.common_table_expression
515 |
516 | @staticmethod
517 | def visit_Table_value_constructor(node):
518 | return node.value_list
519 |
520 |
521 | # TODO: port from remove_terminal:
522 | # - "where_clause_dml",
523 | # - "declare_set_cursor_common",
524 |
525 |
526 | # Add visit methods to Transformer for all nodes (in _rules) that convert to AliasNode instances
527 |
528 | alias_nodes = get_alias_nodes(globals().values())
529 | Transformer.bind_alias_nodes(alias_nodes)
530 |
531 |
532 | class AstVisitor(BaseAstVisitor):
533 | def visitTerminal(self, ctx):
534 | """Converts case insensitive keywords and identifiers to lowercase
535 | Identifiers in quotes are not lowercased even though there is case sensitivity in quotes for identifiers,
536 | to prevent lowercasing quoted values.
537 | """
538 | text = str(super().visitTerminal(ctx))
539 | quotes = ["'", '"']
540 | if not (text[0] in quotes and text[-1] in quotes):
541 | text = text.lower()
542 | return Terminal.from_text(text, ctx)
543 |
544 |
545 | if __name__ == "__main__":
546 | query = """
547 | SELECT id FROM artists WHERE id > 100
548 | """
549 | parse(query)
550 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/antlr_tsql/tsql.g4:
--------------------------------------------------------------------------------
1 | /*
2 | T-SQL (Transact-SQL, MSSQL) grammar.
3 | The MIT License (MIT).
4 | Copyright (c) 2015-2016, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies.
5 | Copyright (c) 2016, Scott Ure (scott@redstormsoftware.com).
6 | Copyright (c) 2016, Rui Zhang (ruizhang.ccs@gmail.com).
7 | Copyright (c) 2016, Marcus Henriksson (kuseman80@gmail.com).
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in
17 | all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | THE SOFTWARE.
26 | */
27 |
28 | grammar tsql;
29 |
30 | tsql_file
31 | : batch* EOF
32 | ;
33 |
34 | batch
35 | : sql_clauses go_statement?
36 | ;
37 |
38 | sql_clauses
39 | : (sql_clause SEMI?)+
40 | ;
41 |
42 | sql_clause
43 | : dml_clause
44 |
45 | | ddl_clause
46 |
47 | | cfl_statement
48 |
49 | | another_statement
50 | ;
51 |
52 | // Data Manipulation Language: https://msdn.microsoft.com/en-us/library/ff848766(v=sql.120).aspx
53 | dml_clause
54 | : delete_statement
55 | | insert_statement
56 | | select_statement
57 | | update_statement
58 | ;
59 |
60 | // Data Definition Language: https://msdn.microsoft.com/en-us/library/ff848799.aspx)
61 | ddl_clause
62 | : create_database
63 | | create_index
64 | | create_or_alter_function
65 | | create_or_alter_procedure
66 | | create_statistics
67 | | create_table
68 | | create_type
69 | | create_view
70 |
71 | | alter_table
72 | | alter_database
73 |
74 | | drop_index
75 | | drop_procedure
76 | | drop_statistics
77 | | drop_table
78 | | drop_type
79 | | drop_view
80 | ;
81 |
82 | // Control-of-Flow Language: https://msdn.microsoft.com/en-us/library/ms174290.aspx
83 | // Labels for better AST traverse.
84 | cfl_statement
85 | // https://msdn.microsoft.com/en-us/library/ms190487.aspx
86 | : BEGIN ';'? sql_clauses? END ';'? #block_statement
87 | // https://msdn.microsoft.com/en-us/library/ms181271.aspx
88 | | BREAK ';'? #break_statement
89 | // https://msdn.microsoft.com/en-us/library/ms174366.aspx
90 | | CONTINUE ';'? #continue_statement
91 | // https://msdn.microsoft.com/en-us/library/ms180188.aspx
92 | | GOTO r_id ';'? #goto_statement
93 | | r_id ':' ';'? #goto_statement
94 | // https://msdn.microsoft.com/en-us/library/ms182717.aspx
95 | | IF search_condition if_expr=sql_clause (ELSE else_expr=sql_clause)? ';'? #if_statement
96 | // https://msdn.microsoft.com/en-us/library/ms174998.aspx
97 | | RETURN expression? ';'? #return_statement
98 | // https://msdn.microsoft.com/en-us/library/ee677615.aspx
99 | | THROW (
100 | error_number=(DECIMAL | LOCAL_ID) ',' message=(STRING | LOCAL_ID) ','
101 | state=(DECIMAL | LOCAL_ID))? ';'? #throw_statement
102 | // https://msdn.microsoft.com/en-us/library/ms175976.aspx
103 | | BEGIN TRY ';'? try_clauses=sql_clauses? END TRY ';'?
104 | BEGIN CATCH ';'? catch_clauses=sql_clauses? END CATCH ';'? #try_catch_statement
105 | // https://msdn.microsoft.com/en-us/library/ms187331.aspx
106 | | WAITFOR (DELAY | TIME) expression ';'? #waitfor_statement
107 | // https://msdn.microsoft.com/en-us/library/ms178642.aspx
108 | | WHILE search_condition (sql_clause | BREAK ';'? | CONTINUE ';'?) #while_statement
109 | // https://msdn.microsoft.com/en-us/library/ms176047.aspx.
110 | | PRINT expression ';'? #print_statement
111 | // https://msdn.microsoft.com/en-us/library/ms178592.aspx
112 | | RAISERROR '(' msg=(DECIMAL | STRING | LOCAL_ID) ',' severity=constant_LOCAL_ID ','
113 | state=constant_LOCAL_ID (',' constant_LOCAL_ID)* ')' ';'? #raiseerror_statement
114 | ;
115 |
116 | another_statement
117 | : declare_statement
118 | | cursor_statement
119 | | execute_statement
120 | | security_statement
121 | | set_statement
122 | | transaction_statement
123 | | use_statement
124 | ;
125 |
126 | // DML
127 |
128 | // https://msdn.microsoft.com/en-us/library/ms189835.aspx
129 | delete_statement
130 | : with_expression?
131 | DELETE top_clause_dm?
132 | FROM? delete_statement_from
133 | insert_with_table_hints?
134 | output_clause?
135 | (FROM table_sources)?
136 | where_clause_dml?
137 | for_clause? option_clause? ';'?
138 | ;
139 |
140 | // MC-Note: with_table_hints was originally inside table_alias, don't know if it
141 | // applies here
142 | delete_statement_from
143 | : r_id with_table_hints?
144 | | ddl_object
145 | | rowset_function_limited
146 | | table_var=LOCAL_ID
147 | ;
148 |
149 | // https://msdn.microsoft.com/en-us/library/ms174335.aspx
150 | insert_statement
151 | : with_expression?
152 | INSERT top_clause_dm?
153 | INTO? (ddl_object | rowset_function_limited)
154 | insert_with_table_hints?
155 | ('(' column_name_list ')')?
156 | output_clause?
157 | insert_statement_value
158 | for_clause? option_clause? ';'?
159 | ;
160 |
161 | insert_statement_value
162 | : table_value_constructor
163 | | derived_table
164 | | execute_statement
165 | | DEFAULT VALUES
166 | ;
167 |
168 | // https://msdn.microsoft.com/en-us/library/ms189499.aspx
169 | select_statement
170 | : with_expression? query_expression order_by_clause? for_clause? option_clause? ';'?
171 | ;
172 |
173 | // https://msdn.microsoft.com/en-us/library/ms177523.aspx
174 | update_statement
175 | : with_expression?
176 | UPDATE top_clause_dm?
177 | (ddl_object | rowset_function_limited)
178 | with_table_hints?
179 | SET update_elem (',' update_elem)*
180 | output_clause?
181 | (FROM table_sources)?
182 | where_clause_dml?
183 | for_clause? option_clause? ';'?
184 | ;
185 |
186 | where_clause_dml
187 | : WHERE (search_condition_list | CURRENT OF (GLOBAL? cursor_name | cursor_var=LOCAL_ID))
188 | ;
189 | // https://msdn.microsoft.com/en-us/library/ms177564.aspx
190 | output_clause
191 | : OUTPUT output_dml_list_elem (',' output_dml_list_elem)*
192 | (INTO (LOCAL_ID | table_name) ('(' column_name_list ')')? )?
193 | ;
194 |
195 | output_dml_list_elem
196 | : (output_column_name | expression) (AS? column_alias)? // TODO: scalar_expression
197 | ;
198 |
199 | output_column_name
200 | : (DELETED | INSERTED | table_name) '.' (STAR | r_id)
201 | | DOLLAR_ACTION
202 | ;
203 |
204 | // DDL
205 |
206 | // https://msdn.microsoft.com/en-ie/library/ms176061.aspx
207 | create_database
208 | : CREATE DATABASE (database=r_id)
209 | ( CONTAINMENT '=' ( NONE | PARTIAL ) )?
210 | ( ON PRIMARY? database_file_spec ( ',' database_file_spec )* )?
211 | ( LOG ON database_file_spec ( ',' database_file_spec )* )?
212 | ( COLLATE collation_name = r_id )?
213 | ( WITH create_database_option ( ',' create_database_option )* )?
214 | ;
215 |
216 | // https://msdn.microsoft.com/en-us/library/ms188783.aspx
217 | create_index
218 | : CREATE UNIQUE? clustered? INDEX r_id ON table_name_with_hint '(' column_name_list (ASC | DESC)? ')'
219 | (index_options)?
220 | (ON r_id)?
221 | ';'?
222 | ;
223 |
224 | // https://msdn.microsoft.com/en-us/library/ms188038.aspx
225 | create_statistics
226 | : CREATE STATISTICS r_id ON table_name_with_hint '(' column_name_list ')'
227 | (WITH (FULLSCAN | SAMPLE DECIMAL (PERCENT | ROWS) | STATS_STREAM)
228 | (',' NORECOMPUTE)? (',' INCREMENTAL EQUAL on_off)? )? ';'?
229 | ;
230 |
231 | // https://msdn.microsoft.com/en-us/library/ms174979.aspx
232 | create_table
233 | : CREATE TABLE table_name '(' column_def_table_constraints ','? ')' (ON r_id | DEFAULT)? (TEXTIMAGE_ON r_id | DEFAULT)?';'?
234 | ;
235 |
236 | // https://msdn.microsoft.com/en-us/library/ms187956.aspx
237 | create_view
238 | : CREATE VIEW simple_name ('(' column_name_list ')')?
239 | (WITH view_attribute (',' view_attribute)*)?
240 | AS select_statement (WITH CHECK OPTION)? ';'?
241 | ;
242 |
243 | view_attribute
244 | : ENCRYPTION | SCHEMABINDING | VIEW_METADATA
245 | ;
246 |
247 | // https://msdn.microsoft.com/en-us/library/ms190273.aspx
248 | alter_table
249 | : ALTER TABLE table_name (SET '(' LOCK_ESCALATION '=' (AUTO | TABLE | DISABLE) ')'
250 | | ADD column_def_table_constraint
251 | | DROP CONSTRAINT constraint=r_id
252 | | WITH CHECK ADD CONSTRAINT constraint=r_id FOREIGN KEY '(' fk = column_name_list ')' REFERENCES table_name '(' pk = column_name_list')'
253 | | CHECK CONSTRAINT constraint=r_id
254 | )
255 | ';'?
256 | ;
257 |
258 | // https://msdn.microsoft.com/en-us/library/ms174269.aspx
259 | alter_database
260 | : ALTER DATABASE (database=r_id | CURRENT)
261 | (MODIFY NAME '=' new_name=r_id | COLLATE collation=r_id | SET database_optionspec (WITH termination)? ) ';'?
262 | ;
263 |
264 | // https://msdn.microsoft.com/en-us/library/bb522682.aspx
265 | // Runtime check.
266 | database_optionspec
267 | : auto_option
268 | | change_tracking_option
269 | | containment_option
270 | | cursor_option
271 | // | database_mirroring_option
272 | | date_correlation_optimization_option
273 | | db_encryption_option
274 | | db_state_option
275 | | db_update_option
276 | | db_user_access_option
277 | | delayed_durability_option
278 | | external_access_option
279 | | FILESTREAM database_filestream_option
280 | | HADR_options
281 | | mixed_page_allocation_option
282 | | parameterization_option
283 | // | query_store_options
284 | | recovery_option
285 | // | remote_data_archive_option
286 | | service_broker_option
287 | | snapshot_option
288 | | sql_option
289 | | target_recovery_time_option
290 | | termination
291 | ;
292 |
293 | auto_option:
294 | AUTO_CLOSE on_off
295 | | AUTO_CREATE_STATISTICS OFF | ON ( INCREMENTAL EQUAL ON | OFF )
296 | | AUTO_SHRINK on_off
297 | | AUTO_UPDATE_STATISTICS on_off
298 | | AUTO_UPDATE_STATISTICS_ASYNC (ON | OFF )
299 | ;
300 |
301 | change_tracking_option:
302 | CHANGE_TRACKING EQUAL ( OFF | ON (change_tracking_option_list (',' change_tracking_option_list)*)* )
303 | ;
304 |
305 | change_tracking_option_list:
306 | AUTO_CLEANUP EQUAL on_off
307 | | CHANGE_RETENTION EQUAL ( DAYS | HOURS | MINUTES )
308 | ;
309 |
310 | containment_option:
311 | CONTAINMENT EQUAL ( NONE | PARTIAL )
312 | ;
313 |
314 | cursor_option:
315 | CURSOR_CLOSE_ON_COMMIT on_off
316 | | CURSOR_DEFAULT ( LOCAL | GLOBAL )
317 | ;
318 |
319 | /* Will visit later
320 | database_mirroring_option:
321 | ALTER DATABASE Database Mirroring
322 | ;
323 | */
324 |
325 | date_correlation_optimization_option:
326 | DATE_CORRELATION_OPTIMIZATION on_off
327 | ;
328 |
329 | db_encryption_option:
330 | ENCRYPTION on_off
331 | ;
332 | db_state_option:
333 | ( ONLINE | OFFLINE | EMERGENCY )
334 | ;
335 |
336 | db_update_option:
337 | READ_ONLY | READ_WRITE
338 | ;
339 |
340 | db_user_access_option:
341 | ( SINGLE_USER | RESTRICTED_USER | MULTI_USER )
342 | ;
343 | delayed_durability_option:
344 | DELAYED_DURABILITY EQUAL ( DISABLED | ALLOWED | FORCED )
345 | ;
346 |
347 | external_access_option:
348 | DB_CHAINING on_off
349 | | TRUSTWORTHY on_off
350 | | DEFAULT_LANGUAGE EQUAL ( r_id | STRING )
351 | | DEFAULT_FULLTEXT_LANGUAGE EQUAL ( r_id | STRING )
352 | | NESTED_TRIGGERS EQUAL ( OFF | ON )
353 | | TRANSFORM_NOISE_WORDS EQUAL ( OFF | ON )
354 | | TWO_DIGIT_YEAR_CUTOFF EQUAL DECIMAL
355 | ;
356 |
357 | HADR_options:
358 | ALTER DATABASE SET HADR
359 | ;
360 |
361 | mixed_page_allocation_option:
362 | MIXED_PAGE_ALLOCATION ( OFF | ON )
363 | ;
364 |
365 | parameterization_option:
366 | PARAMETERIZATION ( SIMPLE | FORCED )
367 | ;
368 |
369 | /* Will visit later
370 | query_store_options:
371 | ;
372 | */
373 |
374 | recovery_option:
375 | RECOVERY ( FULL | BULK_LOGGED | SIMPLE )
376 | | TORN_PAGE_DETECTION on_off
377 | | PAGE_VERIFY ( CHECKSUM | TORN_PAGE_DETECTION | NONE )
378 | ;
379 |
380 | /*Will visit later
381 | remote_data_archive_option:
382 | ;
383 | */
384 |
385 | service_broker_option:
386 | ENABLE_BROKER
387 | | DISABLE_BROKER
388 | | NEW_BROKER
389 | | ERROR_BROKER_CONVERSATIONS
390 | | HONOR_BROKER_PRIORITY on_off
391 | ;
392 | snapshot_option:
393 | ALLOW_SNAPSHOT_ISOLATION on_off
394 | | READ_COMMITTED_SNAPSHOT (ON | OFF )
395 | | MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = (ON | OFF )
396 | ;
397 |
398 | sql_option:
399 | ANSI_NULL_DEFAULT on_off
400 | | ANSI_NULLS on_off
401 | | ANSI_PADDING on_off
402 | | ANSI_WARNINGS on_off
403 | | ARITHABORT on_off
404 | | COMPATIBILITY_LEVEL EQUAL DECIMAL
405 | | CONCAT_NULL_YIELDS_NULL on_off
406 | | NUMERIC_ROUNDABORT on_off
407 | | QUOTED_IDENTIFIER on_off
408 | | RECURSIVE_TRIGGERS on_off
409 | ;
410 |
411 | target_recovery_time_option:
412 | TARGET_RECOVERY_TIME EQUAL DECIMAL ( SECONDS | MINUTES )
413 | ;
414 |
415 | termination:
416 | ROLLBACK AFTER seconds = DECIMAL
417 | | ROLLBACK IMMEDIATE
418 | | NO_WAIT
419 | ;
420 |
421 | // https://msdn.microsoft.com/en-us/library/ms176118.aspx
422 | drop_index
423 | : DROP INDEX (IF EXISTS)? name=r_id (ON table_name)? ';'?
424 | ;
425 |
426 | // https://msdn.microsoft.com/en-us/library/ms174969.aspx
427 | drop_procedure
428 | : DROP PROCEDURE (IF EXISTS)? func_proc_name ';'?
429 | ;
430 |
431 | // https://msdn.microsoft.com/en-us/library/ms175075.aspx
432 | drop_statistics
433 | : DROP STATISTICS (table_name '.')? name=r_id ';'
434 | ;
435 |
436 | // https://msdn.microsoft.com/en-us/library/ms173790.aspx
437 | drop_table
438 | : DROP TABLE (IF EXISTS)? table_name ';'?
439 | ;
440 |
441 | // https://msdn.microsoft.com/en-us/library/ms173492.aspx
442 | drop_view
443 | : DROP VIEW (IF EXISTS)? simple_name (',' simple_name)* ';'?
444 | ;
445 |
446 | create_type:
447 | CREATE TYPE name = simple_name FROM data_type default_value
448 | ;
449 |
450 | drop_type:
451 | DROP TYPE ( IF EXISTS )? name = simple_name
452 | ;
453 |
454 | rowset_function_limited
455 | : openquery
456 | | opendatasource
457 | ;
458 |
459 | // https://msdn.microsoft.com/en-us/library/ms188427(v=sql.120).aspx
460 | openquery
461 | : OPENQUERY '(' linked_server=r_id ',' query=STRING ')'
462 | ;
463 |
464 | // https://msdn.microsoft.com/en-us/library/ms179856.aspx
465 | opendatasource
466 | : OPENDATASOURCE '(' provider=STRING ',' init=STRING ')'
467 | '.' (database=r_id)? '.' (scheme=r_id)? '.' (table=r_id)
468 | ;
469 |
470 | // Other statements.
471 |
472 | // https://msdn.microsoft.com/en-us/library/ms188927.aspx
473 | declare_statement
474 | : DECLARE LOCAL_ID AS? table_type_definition ';'?
475 | | DECLARE declare_local (',' declare_local)* ';'?
476 | ;
477 |
478 | // https://msdn.microsoft.com/en-us/library/ms181441(v=sql.120).aspx
479 | cursor_statement
480 | // https://msdn.microsoft.com/en-us/library/ms175035(v=sql.120).aspx
481 | : CLOSE GLOBAL? cursor_name ';'?
482 | // https://msdn.microsoft.com/en-us/library/ms188782(v=sql.120).aspx
483 | | DEALLOCATE GLOBAL? cursor_name ';'?
484 | // https://msdn.microsoft.com/en-us/library/ms180169(v=sql.120).aspx
485 | | declare_cursor
486 | // https://msdn.microsoft.com/en-us/library/ms180152(v=sql.120).aspx
487 | | fetch_cursor
488 | // https://msdn.microsoft.com/en-us/library/ms190500(v=sql.120).aspx
489 | | OPEN GLOBAL? cursor_name ';'?
490 | ;
491 |
492 | // https://msdn.microsoft.com/en-us/library/ms188332.aspx
493 | execute_statement
494 | : EXECUTE (return_status=LOCAL_ID '=')? func_proc_name (execute_statement_arg (',' execute_statement_arg)*)? ';'?
495 | | EXECUTE '(' execute_var_string ('+' execute_var_string)* ')' (AS? (LOGIN | USER) '=' STRING)? ';'?
496 | ;
497 |
498 | execute_statement_arg
499 | : (parameter=LOCAL_ID '=')? ((constant_LOCAL_ID | r_id) (OUTPUT | OUT)? | DEFAULT | NULL)
500 | ;
501 |
502 | execute_var_string
503 | : LOCAL_ID
504 | | STRING
505 | ;
506 |
507 | // https://msdn.microsoft.com/en-us/library/ff848791.aspx
508 | security_statement
509 | // https://msdn.microsoft.com/en-us/library/ms188354.aspx
510 | : execute_clause ';'?
511 | // https://msdn.microsoft.com/en-us/library/ms187965.aspx
512 | | GRANT (ALL PRIVILEGES? | grant_permission ('(' column_name_list ')')?) (ON on_id=table_name)? TO (to_principal=r_id) (WITH GRANT OPTION)? (AS as_principal=r_id)? ';'?
513 | // https://msdn.microsoft.com/en-us/library/ms178632.aspx
514 | | REVERT ('(' WITH COOKIE '=' LOCAL_ID ')')? ';'?
515 | ;
516 |
517 | grant_permission
518 | : EXECUTE
519 | | VIEW r_id // DEFINITION
520 | | TAKE r_id // OWNERSHIP
521 | | CONTROL r_id? // SERVER
522 | | CREATE (TABLE | VIEW)
523 | | SHOWPLAN
524 | | IMPERSONATE
525 | | SELECT
526 | | REFERENCES
527 | | INSERT
528 | | ALTER (ANY? (r_id | DATABASE))?
529 | ;
530 |
531 | // https://msdn.microsoft.com/en-us/library/ms190356.aspx
532 | // https://msdn.microsoft.com/en-us/library/ms189484.aspx
533 | set_statement
534 | : SET LOCAL_ID ('.' member_name=r_id)? '=' expression ';'?
535 | | SET LOCAL_ID assignment_operator expression ';'?
536 | | SET LOCAL_ID '='
537 | CURSOR declare_set_cursor_common (FOR (READ ONLY | UPDATE (OF column_name_list)?))? ';'?
538 | // https://msdn.microsoft.com/en-us/library/ms189837.aspx
539 | | set_special
540 | ;
541 |
542 | // https://msdn.microsoft.com/en-us/library/ms174377.aspx
543 | transaction_statement
544 | // https://msdn.microsoft.com/en-us/library/ms188386.aspx
545 | : BEGIN DISTRIBUTED (TRAN | TRANSACTION) (r_id | LOCAL_ID)? ';'?
546 | // https://msdn.microsoft.com/en-us/library/ms188929.aspx
547 | | BEGIN (TRAN | TRANSACTION) ((r_id | LOCAL_ID) (WITH MARK STRING)?)? ';'?
548 | // https://msdn.microsoft.com/en-us/library/ms190295.aspx
549 | | COMMIT (TRAN | TRANSACTION) ((r_id | LOCAL_ID) (WITH '(' DELAYED_DURABILITY EQUAL (OFF | ON) ')')?)? ';'?
550 | // https://msdn.microsoft.com/en-us/library/ms178628.aspx
551 | | COMMIT WORK? ';'?
552 | // https://msdn.microsoft.com/en-us/library/ms181299.aspx
553 | | ROLLBACK (TRAN | TRANSACTION) (r_id | LOCAL_ID)? ';'?
554 | // https://msdn.microsoft.com/en-us/library/ms174973.aspx
555 | | ROLLBACK WORK? ';'?
556 | // https://msdn.microsoft.com/en-us/library/ms188378.aspx
557 | | SAVE (TRAN | TRANSACTION) (r_id | LOCAL_ID)? ';'?
558 | ;
559 |
560 | // https://msdn.microsoft.com/en-us/library/ms188037.aspx
561 | go_statement
562 | : GO (count=DECIMAL)?
563 | ;
564 |
565 | // https://msdn.microsoft.com/en-us/library/ms188366.aspx
566 | use_statement
567 | : USE database=r_id ';'?
568 | ;
569 |
570 | execute_clause
571 | : EXECUTE AS clause=(CALLER | SELF | OWNER | STRING)
572 | ;
573 |
574 | declare_local
575 | : LOCAL_ID AS? data_type ('=' expression)?
576 | ;
577 |
578 | table_type_definition
579 | : TABLE '(' column_def_table_constraints ')'
580 | ;
581 |
582 | column_def_table_constraints
583 | : column_def_table_constraint (','? column_def_table_constraint)*
584 | ;
585 |
586 | column_def_table_constraint
587 | : column_definition
588 | | table_constraint
589 | ;
590 |
591 | // https://msdn.microsoft.com/en-us/library/ms187742.aspx
592 | column_definition
593 | : r_id (data_type | AS expression) (COLLATE r_id)? null_notnull?
594 | ((CONSTRAINT constraint=r_id)? DEFAULT constant_expression (WITH VALUES)?
595 | | IDENTITY ('(' seed=DECIMAL ',' increment=DECIMAL ')')? (NOT FOR REPLICATION)?)?
596 | ROWGUIDCOL?
597 | column_constraint*
598 | ;
599 |
600 | // https://msdn.microsoft.com/en-us/library/ms186712.aspx
601 | column_constraint
602 | :(CONSTRAINT r_id)? null_notnull?
603 | ((PRIMARY KEY | UNIQUE) clustered? index_options?
604 | | CHECK (NOT FOR REPLICATION)? '(' search_condition ')')
605 | ;
606 |
607 | // https://msdn.microsoft.com/en-us/library/ms188066.aspx
608 | table_constraint
609 | : (CONSTRAINT r_id)?
610 | ((PRIMARY KEY | UNIQUE) clustered? '(' column_name_list (ASC | DESC)? ')' index_options? (ON r_id)?
611 | | CHECK (NOT FOR REPLICATION)? '(' search_condition ')')
612 | ;
613 |
614 | index_options
615 | : WITH '(' index_option (',' index_option)* ')'
616 | ;
617 |
618 | // https://msdn.microsoft.com/en-us/library/ms186869.aspx
619 | // Id runtime checking. Id in (PAD_INDEX, FILLFACTOR, IGNORE_DUP_KEY, STATISTICS_NORECOMPUTE, ALLOW_ROW_LOCKS,
620 | // ALLOW_PAGE_LOCKS, SORT_IN_TEMPDB, ONLINE, MAXDOP, DATA_COMPRESSION, ONLINE).
621 | index_option
622 | : simple_id '=' (simple_id | on_off | DECIMAL)
623 | ;
624 |
625 | // https://msdn.microsoft.com/en-us/library/ms180169.aspx
626 | declare_cursor
627 | : DECLARE cursor_name
628 | (CURSOR (declare_set_cursor_common (FOR UPDATE (OF column_name_list)?)?)?
629 | | INSENSITIVE? SCROLL? CURSOR FOR select_statement (FOR (READ ONLY | UPDATE | (OF column_name_list)))?
630 | ) ';'?
631 | ;
632 |
633 | declare_set_cursor_common
634 | : (LOCAL | GLOBAL)?
635 | (FORWARD_ONLY | SCROLL)? (STATIC | KEYSET | DYNAMIC | FAST_FORWARD)?
636 | (READ_ONLY | SCROLL_LOCKS | OPTIMISTIC)? TYPE_WARNING?
637 | FOR select_statement
638 | ;
639 |
640 | fetch_cursor
641 | : FETCH ((NEXT | PRIOR | FIRST | LAST | (ABSOLUTE | RELATIVE) expression)? FROM)?
642 | GLOBAL? cursor_name (INTO LOCAL_ID (',' LOCAL_ID)*)? ';'?
643 | ;
644 |
645 | // https://msdn.microsoft.com/en-us/library/ms190356.aspx
646 | // Runtime check.
647 | set_special
648 | : SET key=r_id (value=r_id | constant_LOCAL_ID | on_off) ';'?
649 | // https://msdn.microsoft.com/en-us/library/ms173763.aspx
650 | | SET set_type=TRANSACTION ISOLATION LEVEL
651 | (READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE) ';'?
652 | // https://msdn.microsoft.com/en-us/library/ms188059.aspx
653 | | SET set_type=IDENTITY_INSERT table_name on_off ';'?
654 | | SET set_type=ANSI_NULLS on_off
655 | | SET set_type=QUOTED_IDENTIFIER on_off
656 | | SET set_type=ANSI_PADDING on_off
657 | | SET set_type=STATISTICS (TIME | IO) on_off
658 | ;
659 |
660 | constant_LOCAL_ID
661 | : constant
662 | | LOCAL_ID
663 | ;
664 |
665 | // Expression.
666 |
667 | // https://msdn.microsoft.com/en-us/library/ms190286.aspx
668 | // Operator precendence: https://msdn.microsoft.com/en-us/library/ms190276.aspx
669 | // MC-Note TODO: COLLATE r_id is repeated many times. Also, can move into function_call?
670 | expression
671 | : DEFAULT #primitive_expression
672 | | NULL #primitive_expression
673 | | LOCAL_ID #primitive_expression
674 | | constant #primitive_expression
675 | | function_call #function_call_expression
676 | | expression COLLATE r_id #function_call_expression
677 | // https://docs.microsoft.com/en-us/sql/t-sql/queries/at-time-zone-transact-sql?view=sql-server-2017
678 | | left=expression AT TIME ZONE right=expression #conversion_expression
679 | // https://msdn.microsoft.com/en-us/library/ms181765.aspx
680 | | CASE caseExpr=expression switch_section+ (ELSE elseExpr=expression)? END #case_expression
681 | | CASE switch_search_condition_section+ (ELSE elseExpr=expression)? END #case_expression
682 |
683 | | full_column_name #column_ref_expression
684 | | '(' expression ')' #bracket_expression
685 | | '(' subquery ')' #subquery_expression
686 | | op='~' expression #unary_operator_expression
687 |
688 | | left=expression op=(STAR | '/' | '%') right=expression #binary_operator_expression
689 | | op=('+' | '-') expression #unary_operator_expression
690 | | left=expression op=('+' | '-' | '&' | '^' | '|') right=expression #binary_operator_expression
691 | | left=expression comparison_operator right=expression #binary_operator_expression
692 |
693 | | over_clause #over_clause_expression
694 | | percentile_cont #percentile_cont_expression
695 | | string_agg #string_agg_expression
696 | ;
697 |
698 | constant_expression
699 | : NULL
700 | | constant
701 | // system functions: https://msdn.microsoft.com/en-us/library/ms187786.aspx
702 | | function_call
703 | | LOCAL_ID // TODO: remove.
704 | | '(' constant_expression ')'
705 | ;
706 |
707 | subquery
708 | : select_statement
709 | ;
710 |
711 | // https://msdn.microsoft.com/en-us/library/ms175972.aspx
712 | with_expression
713 | : WITH (XMLNAMESPACES ',')? common_table_expression (',' common_table_expression)*
714 | ;
715 |
716 | common_table_expression
717 | : expression_name=r_id ('(' column_name_list ')')? AS '(' select_statement ')'
718 | ;
719 |
720 | update_elem
721 | : (full_column_name | name=LOCAL_ID) ('=' | assignment_operator) expression
722 | | udt_column_name=r_id '.' method_name=r_id '(' expression_list ')'
723 | //| full_column_name '.' WRITE (expression, )
724 | ;
725 |
726 | // https://msdn.microsoft.com/en-us/library/ms173545.aspx
727 | search_condition_list
728 | : search_condition (',' search_condition)*
729 | ;
730 |
731 | search_condition
732 | : left=search_condition op=AND right=search_condition # search_cond_and
733 | | left=search_condition op=OR right=search_condition # search_cond_or
734 | | predicate # search_cond_pred
735 | ;
736 |
737 | // MC-NOTE this is mostly redundant to the expression rule
738 | predicate
739 | : op=NOT expr=predicate #unary_operator_expression3
740 | | op=EXISTS '(' expr=subquery ')' #unary_operator_expression2
741 | | left=expression op=comparison_operator right=expression #binary_operator_expression2
742 | | test_expr=expression op=comparison_operator pref=(ALL | SOME | ANY) '(' subquery ')' #sublink_expression
743 | | left=expression NOT? op=BETWEEN right+=expression AND right+=expression #binary_mod_expression
744 | | left=expression NOT? op=IN '(' (subquery | expression_list) ')' #binary_in_expression
745 | | left=expression NOT? op=LIKE right+=expression (ESCAPE right+=expression)? #binary_mod_expression
746 | | left=expression op=IS right=null_notnull #binary_operator_expression2
747 | | '(' search_condition ')' #bracket_search_expression
748 | | DECIMAL #decimal_expression
749 | ;
750 |
751 | query_expression
752 | : '(' query_expression ')' #bracket_query_expression
753 | | left=query_expression op=union_op right=query_expression #union_query_expression
754 | | query_specification #query_specification_expression
755 | ;
756 |
757 | union_op
758 | : (UNION ALL? | EXCEPT | INTERSECT)
759 | ;
760 |
761 | // https://msdn.microsoft.com/en-us/library/ms176104.aspx
762 | query_specification
763 | : SELECT pref=(ALL | DISTINCT)? top_clause?
764 | select_list
765 | // https://msdn.microsoft.com/en-us/library/ms188029.aspx
766 | (INTO table_name)?
767 | (FROM table_sources)?
768 | (WHERE where=search_condition)?
769 | // https://msdn.microsoft.com/en-us/library/ms177673.aspx
770 | (GROUP BY group_by_item (',' group_by_item)*)?
771 | (group_by_grouping_sets)?
772 | (WITH (CUBE | ROLLUP))?
773 | (HAVING having=search_condition)?
774 | ;
775 |
776 | group_by_grouping_sets
777 | : GROUP BY GROUPING SETS '('
778 | grouping_set (',' grouping_set)*
779 | ')'
780 | ;
781 |
782 | grouping_set
783 | : '('')'
784 | | group_by_item
785 | | '(' group_by_item (',' group_by_item)* ')'
786 | ;
787 |
788 | top_clause
789 | : TOP expression PERCENT? (WITH TIES)?
790 | ;
791 |
792 | top_clause_dm
793 | : TOP '(' expression ')' PERCENT?
794 | ;
795 |
796 | // https://msdn.microsoft.com/en-us/library/ms188385.aspx
797 | order_by_clause
798 | : ORDER BY order_by_expression (',' order_by_expression)*
799 | (OFFSET offset=expression (ROW | ROWS) fetch_expression?)?
800 | ;
801 |
802 | fetch_expression
803 | : FETCH (FIRST | NEXT) expression (ROW | ROWS) ONLY
804 | ;
805 |
806 |
807 | // https://msdn.microsoft.com/en-us/library/ms173812.aspx
808 | for_clause
809 | : FOR BROWSE
810 | | FOR XML AUTO xml_common_directives?
811 | | FOR XML PATH ('(' STRING ')')? xml_common_directives?
812 | ;
813 |
814 | xml_common_directives
815 | : ',' (BINARY BASE64 | TYPE | ROOT)
816 | ;
817 |
818 | order_by_expression
819 | : expression direction=(ASC | DESC)?
820 | ;
821 |
822 | group_by_item
823 | : expression
824 | /*| rollup_spec
825 | | cube_spec
826 | | grouping_sets_spec
827 | | grand_total*/
828 | ;
829 |
830 | option_clause
831 | // https://msdn.microsoft.com/en-us/library/ms181714.aspx
832 | : OPTION '(' option (',' option)* ')'
833 | ;
834 |
835 | option
836 | : FAST number_rows=DECIMAL
837 | | (HASH | ORDER) GROUP
838 | | (MERGE | HASH | CONCAT) UNION
839 | | (LOOP | MERGE | HASH) JOIN
840 | | EXPAND VIEWS
841 | | FORCE ORDER
842 | | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX
843 | | KEEP PLAN
844 | | KEEPFIXED PLAN
845 | | MAXDOP number_of_processors=DECIMAL
846 | | MAXRECURSION number_recursion=DECIMAL
847 | | OPTIMIZE FOR '(' optimize_for_arg (',' optimize_for_arg)* ')'
848 | | OPTIMIZE FOR UNKNOWN
849 | | PARAMETERIZATION (SIMPLE | FORCED)
850 | | RECOMPILE
851 | | ROBUST PLAN
852 | | USE PLAN STRING
853 | ;
854 |
855 | optimize_for_arg
856 | : LOCAL_ID (UNKNOWN | '=' constant)
857 | ;
858 |
859 | // https://msdn.microsoft.com/en-us/library/ms176104.aspx
860 | select_list
861 | : select_list_elem (',' select_list_elem)*
862 | ;
863 |
864 | select_list_elem
865 | : (table_name '.')? (a_star | '$' (IDENTITY | ROWGUID))
866 | | alias=column_alias '=' expression
867 | | expression (AS? alias=column_alias)?
868 | ;
869 |
870 | table_sources
871 | : table_source (',' table_source)*
872 | ;
873 |
874 | // https://msdn.microsoft.com/en-us/library/ms177634.aspx
875 | // https://msdn.microsoft.com/en-us/library/ms191472.aspx
876 | table_source
877 | : '(' table_source ')' #bracket_table_source
878 | // https://msdn.microsoft.com/en-us/library/ms173815(v=sql.120).aspx
879 | | left=table_source join_type JOIN right=table_source ON search_condition #standard_join
880 | | left=table_source op=CROSS JOIN right=table_source #cross_join
881 | | left=table_source op=(CROSS | OUTER) APPLY right=table_source #apply_join
882 | | table_source_item #table_source_item_join
883 | ;
884 |
885 | /*
886 | table_source_item_joined
887 | : table_source_item join_part*
888 | ;
889 | */
890 |
891 | table_source_item
892 | : table_name tablesample_clause? table_alias? with_table_hints? #table_source_item_name
893 | | rowset_function table_alias? #table_source_item_simple
894 | | derived_table (table_alias column_alias_list?)? #table_source_item_complex
895 | | change_table table_alias? #table_source_item_simple
896 | | function_call table_alias? #table_source_item_simple
897 | | LOCAL_ID table_alias? #table_source_item_simple
898 | | LOCAL_ID '.' function_call (table_alias column_alias_list?)? #table_source_item_complex
899 | ;
900 |
901 | // dc: tablesample_clause
902 | tablesample_clause
903 | : TABLESAMPLE SYSTEM? '(' sample_number ( PERCENT | ROWS )? ')'
904 | ( REPEATABLE ( repeat_seed ) )?;
905 |
906 | sample_number
907 | : DECIMAL;
908 |
909 | repeat_seed
910 | : DECIMAL;
911 |
912 | table_alias
913 | : AS? r_id
914 | ;
915 |
916 | change_table
917 | : CHANGETABLE '(' CHANGES table_name ',' (NULL | DECIMAL | LOCAL_ID) ')'
918 | ;
919 |
920 | join_type
921 | : (INNER? | (LEFT | RIGHT | FULL) OUTER?) (join_hint=(LOOP | HASH | MERGE | REMOTE))?
922 | ;
923 |
924 | // MC-NOTE: It's not clear if this rule is necessary in most places
925 | table_name_with_hint
926 | : table_name with_table_hints?
927 | ;
928 |
929 | // https://msdn.microsoft.com/en-us/library/ms190312.aspx
930 | rowset_function
931 | : (
932 | OPENROWSET LR_BRACKET provider_name = STRING COMMA connectionString = STRING COMMA sql = STRING RR_BRACKET
933 | )
934 | | ( OPENROWSET '(' BULK data_file=STRING ',' (bulk_option (',' bulk_option)* | r_id)')' )
935 | ;
936 |
937 | // runtime check.
938 | bulk_option
939 | : r_id '=' bulk_option_value=(DECIMAL | STRING)
940 | ;
941 |
942 | derived_table
943 | : subquery
944 | | '(' subquery ')'
945 | ;
946 |
947 | function_call
948 | : ranking_windowed_function #rank_call
949 | | aggregate_windowed_function #aggregate_call
950 | | scalar_function_name '(' expression_list? ')' #standard_call
951 | | next_value_for_function #nvf_call
952 | // https://msdn.microsoft.com/en-us/library/ms173784.aspx
953 | | BINARY_CHECKSUM '(' STAR ')' #standard_call
954 | // https://msdn.microsoft.com/en-us/library/hh231076.aspx
955 | // https://msdn.microsoft.com/en-us/library/ms187928.aspx
956 | // MC-NOTE: TODO AST shaping for CAST
957 | | CAST '(' expression AS alias=data_type ')' #cast_call
958 | | CONVERT '(' data_type ',' expression (',' style=expression)? ')' #standard_call
959 | // https://msdn.microsoft.com/en-us/library/ms189788.aspx
960 | | CHECKSUM '(' STAR ')' #simple_call
961 | // https://msdn.microsoft.com/en-us/library/ms190349.aspx
962 | | COALESCE '(' expression_list ')' #standard_call
963 | // https://msdn.microsoft.com/en-us/library/ms188751.aspx
964 | | CURRENT_TIMESTAMP #simple_call
965 | // https://msdn.microsoft.com/en-us/library/ms176050.aspx
966 | | CURRENT_USER #simple_call
967 | // https://msdn.microsoft.com/en-us/library/ms186819.aspx
968 | | DATEADD '(' ID ',' expression ',' expression ')' #standard_call
969 | // https://msdn.microsoft.com/en-us/library/ms189794.aspx
970 | | DATEDIFF '(' ID ',' expression ',' expression ')' #standard_call
971 | // https://msdn.microsoft.com/en-us/library/ms174395.aspx
972 | | DATENAME '(' ID ',' expression ')' #standard_call
973 | // https://msdn.microsoft.com/en-us/library/ms174420.aspx
974 | | DATEPART '(' ID ',' expression ')' #standard_call
975 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/datetimeoffsetfromparts-transact-sql?view=sql-server-2017
976 | | DATETIMEOFFSETFROMPARTS '(' expression ',' expression ',' expression ',' expression ',' expression ',' expression ',' expression ',' expression ',' expression ',' expression ')' #standard_call
977 | // https://msdn.microsoft.com/en-us/library/ms189838.aspx
978 | | IDENTITY '(' data_type (',' seed=DECIMAL)? (',' increment=DECIMAL)? ')' #standard_call
979 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/logical-functions-iif-transact-sql
980 | | IIF '(' search_condition ',' expression ',' expression ')' #standard_call
981 | // https://msdn.microsoft.com/en-us/library/bb839514.aspx
982 | | MIN_ACTIVE_ROWVERSION #simple_call
983 | // https://msdn.microsoft.com/en-us/library/ms177562.aspx
984 | | NULLIF '(' expression ',' expression ')' #standard_call
985 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/parse-transact-sql?view=sql-server-2017
986 | | PARSE '(' left=expression AS alias=data_type (USING right=expression)? ')' #expression_call
987 | // https://msdn.microsoft.com/en-us/library/ms177587.aspx
988 | | SESSION_USER #simple_call
989 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-2017
990 | | STRING_SPLIT '(' expression ',' expression ')' #standard_call
991 | // https://msdn.microsoft.com/en-us/library/ms179930.aspx
992 | | SYSTEM_USER #simple_call
993 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-2017
994 | | TRY_CONVERT '(' data_type ',' expression ')' #standard_call
995 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql?view=sql-server-2017
996 | | TRY_CAST '(' expression AS alias=data_type ')' #cast_call
997 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/try-parse-transact-sql?view=sql-server-2017
998 | | TRY_PARSE '(' left=expression AS alias=data_type (USING right=expression)? ')' #expression_call
999 | ;
1000 |
1001 | switch_section
1002 | : WHEN whenExpr=expression THEN thenExpr=expression
1003 | ;
1004 |
1005 | switch_search_condition_section
1006 | : WHEN whenExpr=search_condition THEN thenExpr=expression
1007 | ;
1008 |
1009 | // https://msdn.microsoft.com/en-us/library/ms187373.aspx
1010 | with_table_hints
1011 | : WITH? '(' table_hint (',' table_hint)* ')'
1012 | ;
1013 |
1014 | // https://msdn.microsoft.com/en-us/library/ms187373.aspx
1015 | insert_with_table_hints
1016 | : WITH '(' table_hint (',' table_hint)* ')'
1017 | ;
1018 |
1019 | // Id runtime check. Id can be (FORCESCAN, HOLDLOCK, NOLOCK, NOWAIT, PAGLOCK, READCOMMITTED,
1020 | // READCOMMITTEDLOCK, READPAST, READUNCOMMITTED, REPEATABLEREAD, ROWLOCK, TABLOCK, TABLOCKX
1021 | // UPDLOCK, XLOCK)
1022 | table_hint
1023 | : NOEXPAND? ( INDEX '(' index_value (',' index_value)* ')'
1024 | | INDEX '=' index_value
1025 | | FORCESEEK ('(' index_value '(' ID (',' ID)* ')' ')')?
1026 | | SERIALIZABLE
1027 | | SNAPSHOT
1028 | | SPATIAL_WINDOW_MAX_CELLS '=' DECIMAL
1029 | | ID)?
1030 | ;
1031 |
1032 | index_value
1033 | : r_id | DECIMAL
1034 | ;
1035 |
1036 | column_alias_list
1037 | : '(' column_alias (',' column_alias)* ')'
1038 | ;
1039 |
1040 | column_alias
1041 | : r_id
1042 | | STRING
1043 | ;
1044 |
1045 | a_star
1046 | : STAR
1047 | ;
1048 |
1049 | table_value_constructor
1050 | : VALUES value_list (',' value_list)*
1051 | ;
1052 |
1053 | expression_list
1054 | : expression (',' expression)*
1055 | ;
1056 |
1057 | value_list
1058 | : '(' expression_list ')'
1059 | ;
1060 |
1061 |
1062 | // https://docs.microsoft.com/en-us/sql/t-sql/functions/next-value-for-transact-sql
1063 | next_value_for
1064 | : NEXT VALUE FOR
1065 | ;
1066 |
1067 | next_value_for_function
1068 | : next_value_for args=func_proc_name over_clause
1069 | ;
1070 |
1071 | // https://msdn.microsoft.com/en-us/library/ms189798.aspx
1072 | ranking_windowed_function
1073 | : (RANK | DENSE_RANK | ROW_NUMBER) '(' ')' over_clause
1074 | | (NTILE | FIRST_VALUE | LAST_VALUE) '(' expression ')' over_clause
1075 | | (LEAD | LAG) '(' expression (',' expression)* ')' over_clause
1076 | ;
1077 |
1078 | // https://msdn.microsoft.com/en-us/library/ms173454.aspx
1079 | aggregate_windowed_function
1080 | : (AVG | MAX | MIN | SUM | STDEV | STDEVP | VAR | VARP)
1081 | '(' all_distinct? expression ')' over_clause?
1082 | | (COUNT | COUNT_BIG)
1083 | '(' (args=STAR | all_distinct? expression) ')' over_clause?
1084 | | CHECKSUM_AGG '(' all_distinct? expression ')'
1085 | | GROUPING '(' expression ')'
1086 | | GROUPING_ID '(' expression_list ')'
1087 | ;
1088 |
1089 | all_distinct
1090 | : (ALL | DISTINCT)
1091 | ;
1092 |
1093 | // https://msdn.microsoft.com/en-us/library/ms189461.aspx
1094 | over_clause
1095 | : OVER '(' (PARTITION BY expression_list)? order_by_clause? row_or_range_clause? ')'
1096 | ;
1097 |
1098 | row_or_range_clause
1099 | : (ROWS | RANGE) window_frame_extent
1100 | ;
1101 |
1102 | window_frame_extent
1103 | : window_frame_preceding
1104 | | BETWEEN window_frame_bound AND window_frame_bound
1105 | ;
1106 |
1107 | window_frame_bound
1108 | : window_frame_preceding
1109 | | window_frame_following
1110 | ;
1111 |
1112 | window_frame_preceding
1113 | : UNBOUNDED PRECEDING
1114 | | DECIMAL PRECEDING
1115 | | CURRENT ROW
1116 | ;
1117 |
1118 | window_frame_following
1119 | : UNBOUNDED FOLLOWING
1120 | | DECIMAL FOLLOWING
1121 | ;
1122 |
1123 | create_database_option:
1124 | FILESTREAM ( database_filestream_option (',' database_filestream_option)* )
1125 | | DEFAULT_LANGUAGE EQUAL ( r_id | STRING )
1126 | | DEFAULT_FULLTEXT_LANGUAGE EQUAL ( r_id | STRING )
1127 | | NESTED_TRIGGERS EQUAL ( OFF | ON )
1128 | | TRANSFORM_NOISE_WORDS EQUAL ( OFF | ON )
1129 | | TWO_DIGIT_YEAR_CUTOFF EQUAL DECIMAL
1130 | | DB_CHAINING ( OFF | ON )
1131 | | TRUSTWORTHY ( OFF | ON )
1132 | ;
1133 |
1134 | database_filestream_option:
1135 | LR_BRACKET
1136 | (
1137 | ( NON_TRANSACTED_ACCESS EQUAL ( OFF | READ_ONLY | FULL ) )
1138 | |
1139 | ( DIRECTORY_NAME EQUAL STRING )
1140 | )
1141 | RR_BRACKET
1142 | ;
1143 |
1144 | database_file_spec:
1145 | file_group | file_spec;
1146 |
1147 | file_group:
1148 | FILEGROUP r_id
1149 | ( CONTAINS FILESTREAM )?
1150 | ( DEFAULT )?
1151 | ( CONTAINS MEMORY_OPTIMIZED_DATA )?
1152 | file_spec ( ',' file_spec )*
1153 | ;
1154 | file_spec
1155 | : LR_BRACKET
1156 | NAME EQUAL ( r_id | STRING ) ','?
1157 | FILENAME EQUAL r_file = STRING ','?
1158 | ( SIZE EQUAL file_size ','? )?
1159 | ( MAXSIZE EQUAL (file_size | UNLIMITED )','? )?
1160 | ( FILEGROWTH EQUAL file_size ','? )?
1161 | RR_BRACKET
1162 | ;
1163 |
1164 | // Primitive.
1165 |
1166 | full_table_name
1167 | : (server=r_id '.' database=r_id '.' schema=r_id '.'
1168 | | database=r_id '.' (schema=r_id)? '.'
1169 | | schema=r_id '.')? table=r_id
1170 | ;
1171 |
1172 | table_name
1173 | : (database=r_id '.' (schema=r_id)? '.' | schema=r_id '.')? table=r_id
1174 | ;
1175 |
1176 | simple_name
1177 | : (schema=r_id '.')? name=r_id
1178 | ;
1179 |
1180 | func_proc_name
1181 | : (database=r_id '.' (schema=r_id)? '.' | (schema=r_id) '.')? procedure=r_id
1182 | ;
1183 |
1184 | ddl_object
1185 | : full_table_name
1186 | | LOCAL_ID
1187 | ;
1188 |
1189 | full_column_name
1190 | : (table=table_name '.')? name=r_id
1191 | ;
1192 |
1193 | column_name_list
1194 | : r_id (',' r_id)*
1195 | ;
1196 |
1197 | cursor_name
1198 | : r_id
1199 | | LOCAL_ID
1200 | ;
1201 |
1202 | on_off
1203 | : ON
1204 | | OFF
1205 | ;
1206 |
1207 | clustered
1208 | : CLUSTERED
1209 | | NONCLUSTERED
1210 | ;
1211 |
1212 | null_notnull
1213 | : NOT? NULL
1214 | ;
1215 |
1216 | scalar_function_name
1217 | : func_proc_name
1218 | | RIGHT
1219 | | LEFT
1220 | | BINARY_CHECKSUM
1221 | | CHECKSUM
1222 | ;
1223 |
1224 | default_value
1225 | : NULL
1226 | | constant
1227 | ;
1228 |
1229 | // https://msdn.microsoft.com/en-us/library/ms179899.aspx
1230 | constant
1231 | : STRING // string, datetime or uniqueidentifier
1232 | | BINARY
1233 | | sign? DECIMAL
1234 | | sign? (REAL | FLOAT) // float or decimal
1235 | | sign? dollar='$' (DECIMAL | FLOAT) // money
1236 | ;
1237 |
1238 | sign
1239 | : '+'
1240 | | '-'
1241 | ;
1242 |
1243 | // https://msdn.microsoft.com/en-us/library/ms175874.aspx
1244 | r_id
1245 | : simple_id
1246 | | DOUBLE_QUOTE_ID
1247 | | SQUARE_BRACKET_ID
1248 | ;
1249 |
1250 | simple_id
1251 | : ID
1252 | | IO
1253 | | ABSOLUTE
1254 | | APPLY
1255 | | AUTO
1256 | | AVG
1257 | | BASE64
1258 | | CALLER
1259 | | CAST
1260 | | CATCH
1261 | | CHECKSUM_AGG
1262 | | COMMITTED
1263 | | CONCAT
1264 | | CONTROL
1265 | | COOKIE
1266 | | COUNT
1267 | | COUNT_BIG
1268 | | DATE
1269 | | DELAY
1270 | | DELETED
1271 | | DENSE_RANK
1272 | | DISABLE
1273 | | DYNAMIC
1274 | | ENCRYPTION
1275 | | EXPAND
1276 | | FAST
1277 | | FAST_FORWARD
1278 | | FIRST
1279 | | FIRST_VALUE
1280 | | FOLLOWING
1281 | | FORCE
1282 | | FORCESEEK
1283 | | FORWARD_ONLY
1284 | | FULLSCAN
1285 | | GLOBAL
1286 | | GO
1287 | | GROUPING
1288 | | GROUPING_ID
1289 | | HASH
1290 | | IMPERSONATE
1291 | | INSENSITIVE
1292 | | INSERTED
1293 | | ISOLATION
1294 | | KEEP
1295 | | KEEPFIXED
1296 | | FORCED
1297 | | KEYSET
1298 | | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX
1299 | | LAG
1300 | | LAST
1301 | | LAST_VALUE
1302 | | LEAD
1303 | | LEVEL
1304 | | LOCAL
1305 | | LOCK_ESCALATION
1306 | | LOGIN
1307 | | LOOP
1308 | | MARK
1309 | | MAX
1310 | | MAXDOP
1311 | | MAXRECURSION
1312 | | MIN
1313 | | MODIFY
1314 | | NAME
1315 | | NEXT
1316 | | NOCOUNT
1317 | | NOEXPAND
1318 | | NORECOMPUTE
1319 | | NTILE
1320 | | NUMBER
1321 | | NUMERIC
1322 | | OFFSET
1323 | | ONLINE
1324 | | ONLY
1325 | | OPTIMISTIC
1326 | | OPTIMIZE
1327 | | OUT
1328 | | OUTPUT
1329 | | OWNER
1330 | | PARAMETERIZATION
1331 | | PARTITION
1332 | | PATH
1333 | | PRECEDING
1334 | | PRIOR
1335 | | PRIVILEGES
1336 | | RANGE
1337 | | RANK
1338 | | READONLY
1339 | | READ_ONLY
1340 | | RECOMPILE
1341 | | RELATIVE
1342 | | REMOTE
1343 | | REPEATABLE
1344 | | ROBUST
1345 | | ROOT
1346 | | ROW
1347 | | ROWGUID
1348 | | ROWS
1349 | | ROW_NUMBER
1350 | | SAMPLE
1351 | | SCHEMABINDING
1352 | | SCROLL
1353 | | SCROLL_LOCKS
1354 | | SELF
1355 | | SERIALIZABLE
1356 | | SIMPLE
1357 | | SIZE
1358 | | SNAPSHOT
1359 | | SPATIAL_WINDOW_MAX_CELLS
1360 | | STATIC
1361 | | STATS_STREAM
1362 | | STDEV
1363 | | STDEVP
1364 | | SUM
1365 | | TEXTIMAGE_ON
1366 | | THROW
1367 | | TIES
1368 | | TIME
1369 | | TRY
1370 | | TYPE
1371 | | TYPE_WARNING
1372 | | UNBOUNDED
1373 | | UNCOMMITTED
1374 | | UNKNOWN
1375 | | USING
1376 | | VAR
1377 | | VARP
1378 | | VALUE
1379 | | VIEW_METADATA
1380 | | VIEWS
1381 | | WORK
1382 | | XML
1383 | | XMLNAMESPACES
1384 | | ZONE
1385 | ;
1386 |
1387 | // https://msdn.microsoft.com/en-us/library/ms188074.aspx
1388 | // Spaces are allowed for comparison operators.
1389 | comparison_operator
1390 | : '=' | '>' | '<' | '<' '=' | '>' '=' | '<' '>' | '!' '=' | '!' '>' | '!' '<'
1391 | ;
1392 |
1393 | assignment_operator
1394 | : '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='
1395 | ;
1396 |
1397 | file_size:
1398 | DECIMAL( KB | MB | GB | TB | '%' )?
1399 | ;
1400 |
1401 | // New grammar
1402 |
1403 | // https://msdn.microsoft.com/en-us/library/ms187926(v=sql.120).aspx
1404 | create_or_alter_procedure
1405 | : ((CREATE (OR ALTER)?) | ALTER) proc=(PROC | PROCEDURE) func_proc_name (';' DECIMAL)?
1406 | ('('? procedure_param (',' procedure_param)* ')'?)?
1407 | (WITH procedure_option (',' procedure_option)*)?
1408 | (FOR REPLICATION)? AS sql_clauses
1409 | ;
1410 |
1411 | // New grammar
1412 |
1413 | create_or_alter_function
1414 | : ((CREATE (OR ALTER)?) | ALTER) FUNCTION func_proc_name
1415 | (('(' procedure_param (',' procedure_param)* ')') | '(' ')') //must have (), but can be empty
1416 | (func_body_returns_select | func_body_returns_table | func_body_returns_scalar) ';'?
1417 | ;
1418 |
1419 | func_body_returns_select
1420 | :RETURNS TABLE
1421 | (WITH function_option (',' function_option)*)?
1422 | AS?
1423 | RETURN ('(' select_statement ')' | select_statement)
1424 | ;
1425 |
1426 | func_body_returns_table
1427 | : RETURNS LOCAL_ID table_type_definition
1428 | (WITH function_option (',' function_option)*)?
1429 | AS?
1430 | BEGIN
1431 | sql_clause*
1432 | RETURN ';'?
1433 | END ';'?
1434 | ;
1435 |
1436 | func_body_returns_scalar
1437 | :RETURNS data_type
1438 | (WITH function_option (',' function_option)*)?
1439 | AS?
1440 | BEGIN
1441 | sql_clause*
1442 | RETURN ret=expression ';'?
1443 | END
1444 | ;
1445 |
1446 | procedure_param
1447 | : LOCAL_ID (r_id '.')? AS? data_type VARYING? ('=' default_val=default_value)? (OUT | OUTPUT | READONLY)?
1448 | ;
1449 |
1450 | procedure_option
1451 | : ENCRYPTION
1452 | | RECOMPILE
1453 | | execute_clause
1454 | ;
1455 |
1456 | function_option
1457 | : ENCRYPTION
1458 | | SCHEMABINDING
1459 | | RETURNS NULL ON NULL INPUT
1460 | | CALLED ON NULL INPUT
1461 | | execute_clause
1462 | ;
1463 |
1464 | percentile_cont
1465 | : PERCENTILE_CONT '(' expression ')'
1466 | WITHIN GROUP '(' order_by_clause ')'
1467 | over_clause
1468 | ;
1469 |
1470 | string_agg
1471 | : STRING_AGG '(' expression ',' expression ')'
1472 | WITHIN GROUP '(' order_by_clause ')'
1473 | ;
1474 |
1475 | // New grammar (+ dc: NUMERIC)
1476 |
1477 | // https://msdn.microsoft.com/en-us/library/ms187752.aspx
1478 | // TODO: implement runtime check or add new tokens.
1479 | data_type
1480 | /*: BIGINT
1481 | | BINARY '(' DECIMAL ')'
1482 | | BIT
1483 | | CHAR '(' DECIMAL ')'
1484 | | DATE
1485 | | DATETIME
1486 | | DATETIME2
1487 | | DATETIMEOFFSET '(' DECIMAL ')'
1488 | | DECIMAL '(' DECIMAL ',' DECIMAL ')'
1489 | | DOUBLE PRECISION?
1490 | | FLOAT
1491 | | GEOGRAPHY
1492 | | GEOMETRY
1493 | | HIERARCHYID
1494 | | IMAGE
1495 | | INT
1496 | | MONEY
1497 | | NCHAR '(' DECIMAL ')'
1498 | | NTEXT
1499 | | NUMERIC '(' DECIMAL ',' DECIMAL ')'
1500 | | NVARCHAR '(' DECIMAL | MAX ')'
1501 | | REAL
1502 | | SMALLDATETIME
1503 | | SMALLINT
1504 | | SMALLMONEY
1505 | | SQL_VARIANT
1506 | | TEXT
1507 | | TIME '(' DECIMAL ')'
1508 | | TIMESTAMP
1509 | | TINYINT
1510 | | UNIQUEIDENTIFIER
1511 | | VARBINARY '(' DECIMAL | MAX ')'
1512 | | VARCHAR '(' DECIMAL | MAX ')'
1513 | | XML*/
1514 | : r_id IDENTITY? ('(' (DECIMAL | MAX) (',' DECIMAL)? ')')?
1515 | | DATE
1516 | | DATETIME2 '(' DECIMAL ')'
1517 | | DOUBLE PRECISION?
1518 | | INT
1519 | | TINYINT
1520 | | SMALLINT
1521 | | BIGINT
1522 | ;
1523 |
1524 |
1525 | // Lexer
1526 |
1527 | // Basic keywords (from https://msdn.microsoft.com/en-us/library/ms189822.aspx)
1528 | ADD: A D D;
1529 | ALL: A L L;
1530 | ALTER: A L T E R;
1531 | AND: A N D;
1532 | ANY: A N Y;
1533 | AS: A S;
1534 | ASC: A S C;
1535 | AUTHORIZATION: A U T H O R I Z A T I O N;
1536 | BACKUP: B A C K U P;
1537 | BEGIN: B E G I N;
1538 | BETWEEN: B E T W E E N;
1539 | BREAK: B R E A K;
1540 | BROWSE: B R O W S E;
1541 | BULK: B U L K;
1542 | BY: B Y;
1543 | CALLED: C A L L E D;
1544 | CASCADE: C A S C A D E;
1545 | CASE: C A S E;
1546 | CHANGETABLE: C H A N G E T A B L E;
1547 | CHANGES: C H A N G E S;
1548 | CHECK: C H E C K;
1549 | CHECKPOINT: C H E C K P O I N T;
1550 | CLOSE: C L O S E;
1551 | CLUSTERED: C L U S T E R E D;
1552 | COALESCE: C O A L E S C E;
1553 | COLLATE: C O L L A T E;
1554 | COLUMN: C O L U M N;
1555 | COMMIT: C O M M I T;
1556 | COMPUTE: C O M P U T E;
1557 | CONSTRAINT: C O N S T R A I N T;
1558 | CONTAINMENT: C O N T A I N M E N T;
1559 | CONTAINS: C O N T A I N S;
1560 | CONTAINSTABLE: C O N T A I N S T A B L E;
1561 | CONTINUE: C O N T I N U E;
1562 | CONVERT: C O N V E R T;
1563 | CREATE: C R E A T E;
1564 | CROSS: C R O S S;
1565 | CURRENT: C U R R E N T;
1566 | CURRENT_DATE: C U R R E N T '_' D A T E;
1567 | CURRENT_TIME: C U R R E N T '_' T I M E;
1568 | CURRENT_TIMESTAMP: C U R R E N T '_' T I M E S T A M P;
1569 | CURRENT_USER: C U R R E N T '_' U S E R;
1570 | CURSOR: C U R S O R;
1571 | DATABASE: D A T A B A S E;
1572 | DBCC: D B C C;
1573 | DEALLOCATE: D E A L L O C A T E;
1574 | DECLARE: D E C L A R E;
1575 | DEFAULT: D E F A U L T;
1576 | DELETE: D E L E T E;
1577 | DENY: D E N Y;
1578 | DESC: D E S C;
1579 | DISK: D I S K;
1580 | DISTINCT: D I S T I N C T;
1581 | DISTRIBUTED: D I S T R I B U T E D;
1582 | DOUBLE: D O U B L E;
1583 | DROP: D R O P;
1584 | DUMP: D U M P;
1585 | ELSE: E L S E;
1586 | END: E N D;
1587 | ERRLVL: E R R L V L;
1588 | ESCAPE: E S C A P E;
1589 | EXCEPT: E X C E P T;
1590 | EXECUTE: E X E C (U T E)?;
1591 | EXISTS: E X I S T S;
1592 | EXIT: E X I T;
1593 | EXTERNAL: E X T E R N A L;
1594 | FETCH: F E T C H;
1595 | FILE: F I L E;
1596 | FILENAME: F I L E N A M E;
1597 | FILLFACTOR: F I L L F A C T O R;
1598 | FOR: F O R;
1599 | FORCESEEK: F O R C E S E E K;
1600 | FOREIGN: F O R E I G N;
1601 | FREETEXT: F R E E T E X T;
1602 | FREETEXTTABLE: F R E E T E X T T A B L E;
1603 | FROM: F R O M;
1604 | FULL: F U L L;
1605 | FUNCTION: F U N C T I O N;
1606 | GOTO: G O T O;
1607 | GRANT: G R A N T;
1608 | GROUP: G R O U P;
1609 | HAVING: H A V I N G;
1610 | IDENTITY: I D E N T I T Y;
1611 | IDENTITYCOL: I D E N T I T Y C O L;
1612 | IDENTITY_INSERT: I D E N T I T Y '_' I N S E R T;
1613 | IIF: I I F;
1614 | IF: I F;
1615 | IN: I N;
1616 | INDEX: I N D E X;
1617 | INNER: I N N E R;
1618 | INSERT: I N S E R T;
1619 | INTERSECT: I N T E R S E C T;
1620 | INTO: I N T O;
1621 | IS: I S;
1622 | JOIN: J O I N;
1623 | KEY: K E Y;
1624 | KILL: K I L L;
1625 | LEFT: L E F T;
1626 | LIKE: L I K E;
1627 | LINENO: L I N E N O;
1628 | LOAD: L O A D;
1629 | LOG: L O G;
1630 | MERGE: M E R G E;
1631 | NATIONAL: N A T I O N A L;
1632 | NEXT: N E X T;
1633 | NOCHECK: N O C H E C K;
1634 | NONCLUSTERED: N O N C L U S T E R E D;
1635 | NONE: N O N E;
1636 | NOT: N O T;
1637 | NULL: N U L L;
1638 | NULLIF: N U L L I F;
1639 | NUMERIC: N U M E R I C; // dc
1640 | OF: O F;
1641 | OFF: O F F;
1642 | OFFSETS: O F F S E T S;
1643 | ON: O N;
1644 | OPEN: O P E N;
1645 | OPENDATASOURCE: O P E N D A T A S O U R C E;
1646 | OPENQUERY: O P E N Q U E R Y;
1647 | OPENROWSET: O P E N R O W S E T;
1648 | OPENXML: O P E N X M L;
1649 | OPTION: O P T I O N;
1650 | OR: O R;
1651 | ORDER: O R D E R;
1652 | OUTER: O U T E R;
1653 | OVER: O V E R;
1654 | PARTIAL: P A R T I A L;
1655 | PERCENT: P E R C E N T;
1656 | PIVOT: P I V O T;
1657 | PLAN: P L A N;
1658 | PRECISION: P R E C I S I O N;
1659 | PRIMARY: P R I M A R Y;
1660 | PRINT: P R I N T;
1661 | PROC: P R O C;
1662 | PROCEDURE: P R O C E D U R E;
1663 | PUBLIC: P U B L I C;
1664 | RAISERROR: R A I S E R R O R;
1665 | READ: R E A D;
1666 | READTEXT: R E A D T E X T;
1667 | RECONFIGURE: R E C O N F I G U R E;
1668 | REFERENCES: R E F E R E N C E S;
1669 | REPLICATION: R E P L I C A T I O N;
1670 | RESTORE: R E S T O R E;
1671 | RESTRICT: R E S T R I C T;
1672 | RETURN: R E T U R N;
1673 | RETURNS: R E T U R N S;
1674 | REVERT: R E V E R T;
1675 | REVOKE: R E V O K E;
1676 | RIGHT: R I G H T;
1677 | ROLLBACK: R O L L B A C K;
1678 | ROWCOUNT: R O W C O U N T;
1679 | ROWGUIDCOL: R O W G U I D C O L;
1680 | RULE: R U L E;
1681 | SAVE: S A V E;
1682 | SCHEMA: S C H E M A;
1683 | SECURITYAUDIT: S E C U R I T Y A U D I T;
1684 | SELECT: S E L E C T;
1685 | SEMANTICKEYPHRASETABLE: S E M A N T I C K E Y P H R A S E T A B L E;
1686 | SEMANTICSIMILARITYDETAILSTABLE: S E M A N T I C S I M I L A R I T Y D E T A I L S T A B L E;
1687 | SEMANTICSIMILARITYTABLE: S E M A N T I C S I M I L A R I T Y T A B L E;
1688 | SESSION_USER: S E S S I O N '_' U S E R;
1689 | SET: S E T;
1690 | SETUSER: S E T U S E R;
1691 | SHUTDOWN: S H U T D O W N;
1692 | SOME: S O M E;
1693 | STATISTICS: S T A T I S T I C S;
1694 | SYSTEM: S Y S T E M;
1695 | SYSTEM_USER: S Y S T E M '_' U S E R;
1696 | TABLE: T A B L E;
1697 | TABLESAMPLE: T A B L E S A M P L E;
1698 | TEXTSIZE: T E X T S I Z E;
1699 | THEN: T H E N;
1700 | TO: T O;
1701 | TOP: T O P;
1702 | TRAN: T R A N;
1703 | TRANSACTION: T R A N S A C T I O N;
1704 | TRIGGER: T R I G G E R;
1705 | TRUNCATE: T R U N C A T E;
1706 | TRY_CAST: T R Y '_' C A S T;
1707 | TRY_CONVERT: T R Y '_' C O N V E R T;
1708 | TRY_PARSE: T R Y '_' P A R S E;
1709 | TSEQUAL: T S E Q U A L;
1710 | UNION: U N I O N;
1711 | UNIQUE: U N I Q U E;
1712 | UNPIVOT: U N P I V O T;
1713 | UPDATE: U P D A T E;
1714 | UPDATETEXT: U P D A T E T E X T;
1715 | USE: U S E;
1716 | USER: U S E R;
1717 | VALUES: V A L U E S;
1718 | VALUE: V A L U E;
1719 | VARYING: V A R Y I N G;
1720 | VIEW: V I E W;
1721 | WAITFOR: W A I T F O R;
1722 | WHEN: W H E N;
1723 | WHERE: W H E R E;
1724 | WHILE: W H I L E;
1725 | WITH: W I T H;
1726 | WITHIN: W I T H I N;
1727 | WRITETEXT: W R I T E T E X T;
1728 |
1729 | // Additional keywords (they can be id).
1730 | ABSOLUTE: A B S O L U T E;
1731 | AFTER: A F T E R;
1732 | ALLOWED: A L L O W E D;
1733 | ALLOW_SNAPSHOT_ISOLATION: A L L O W '_' S N A P S H O T '_' I S O L A T I O N;
1734 | ANSI_NULLS: A N S I '_' N U L L S;
1735 | ANSI_NULL_DEFAULT: A N S I '_' N U L L '_' D E F A U L T;
1736 | ANSI_PADDING: A N S I '_' P A D D I N G;
1737 | ANSI_WARNINGS: A N S I '_' W A R N I N G S;
1738 | APPLY: A P P L Y;
1739 | ARITHABORT: A R I T H A B O R T;
1740 | AT: A T;
1741 | AUTO: A U T O;
1742 | AUTO_CLEANUP: A U T O '_' C L E A N U P;
1743 | AUTO_CLOSE: A U T O '_' C L O S E;
1744 | AUTO_CREATE_STATISTICS: A U T O '_' C R E A T E '_' S T A T I S T I C S;
1745 | AUTO_SHRINK: A U T O '_' S H R I N K;
1746 | AUTO_UPDATE_STATISTICS: A U T O '_' U P D A T E '_' S T A T I S T I C S;
1747 | AUTO_UPDATE_STATISTICS_ASYNC: A U T O '_' U P D A T E '_' S T A T I S T I C S '_' A S Y N C;
1748 | AVG: A V G;
1749 | BASE64: B A S E '64';
1750 | BIGINT: B I G I N T;
1751 | BINARY_CHECKSUM: B I N A R Y '_' C H E C K S U M;
1752 | BULK_LOGGED: B U L K '_' L O G G E D;
1753 | CALLER: C A L L E R;
1754 | CAST: C A S T;
1755 | CATCH: C A T C H;
1756 | CHANGE_RETENTION: C H A N G E '_' R E T E N T I O N;
1757 | CHANGE_TRACKING: C H A N G E '_' T R A C K I N G;
1758 | CHECKSUM: C H E C K S U M;
1759 | CHECKSUM_AGG: C H E C K S U M '_' A G G;
1760 | COMMITTED: C O M M I T T E D;
1761 | COMPATIBILITY_LEVEL: C O M P A T I B I L I T Y '_' L E V E L;
1762 | CONCAT: C O N C A T;
1763 | CONCAT_NULL_YIELDS_NULL: C O N C A T '_' N U L L '_' Y I E L D S '_' N U L L;
1764 | CONTROL: C O N T R O L;
1765 | COOKIE: C O O K I E;
1766 | COUNT: C O U N T;
1767 | COUNT_BIG: C O U N T '_' B I G;
1768 | CUBE: C U B E;
1769 | CURSOR_CLOSE_ON_COMMIT: C U R S O R '_' C L O S E '_' O N '_' C O M M I T;
1770 | CURSOR_DEFAULT: C U R S O R '_' D E F A U L T;
1771 | DATE: D A T E;
1772 | DATEADD: D A T E A D D;
1773 | DATEDIFF: D A T E D I F F;
1774 | DATENAME: D A T E N A M E;
1775 | DATEPART: D A T E P A R T;
1776 | DATETIME2: D A T E T I M E '2';
1777 | DATETIMEOFFSETFROMPARTS: D A T E T I M E O F F S E T F R O M P A R T S;
1778 | DATE_CORRELATION_OPTIMIZATION: D A T E '_' C O R R E L A T I O N '_' O P T I M I Z A T I O N;
1779 | DAYS: D A Y S;
1780 | DB_CHAINING: D B '_' C H A I N I N G;
1781 | DEFAULT_FULLTEXT_LANGUAGE: D E F A U L T '_' F U L L T E X T '_' L A N G U A G E;
1782 | DEFAULT_LANGUAGE: D E F A U L T '_' L A N G U A G E;
1783 | DELAY: D E L A Y;
1784 | DELAYED_DURABILITY: D E L A Y E D '_' D U R A B I L I T Y;
1785 | DELETED: D E L E T E D;
1786 | DENSE_RANK: D E N S E '_' R A N K;
1787 | DIRECTORY_NAME: D I R E C T O R Y '_' N A M E;
1788 | DISABLE: D I S A B L E;
1789 | DISABLED: D I S A B L E D;
1790 | DISABLE_BROKER: D I S A B L E '_' B R O K E R;
1791 | DYNAMIC: D Y N A M I C;
1792 | EMERGENCY: E M E R G E N C Y;
1793 | ENABLE_BROKER: E N A B L E '_' B R O K E R;
1794 | ENCRYPTION: E N C R Y P T I O N;
1795 | ERROR_BROKER_CONVERSATIONS: E R R O R '_' B R O K E R '_' C O N V E R S A T I O N S;
1796 | EXPAND: E X P A N D;
1797 | FAST: F A S T;
1798 | FAST_FORWARD: F A S T '_' F O R W A R D;
1799 | FILEGROUP: F I L E G R O U P;
1800 | FILEGROWTH: F I L E G R O W T H;
1801 | FILESTREAM: F I L E S T R E A M;
1802 | FIRST: F I R S T;
1803 | FIRST_VALUE: F I R S T '_' V A L U E;
1804 | FOLLOWING: F O L L O W I N G;
1805 | FORCE: F O R C E;
1806 | FORCED: F O R C E D;
1807 | FORWARD_ONLY: F O R W A R D '_' O N L Y;
1808 | FULLSCAN: F U L L S C A N;
1809 | GB: G B;
1810 | GLOBAL: G L O B A L;
1811 | GO: G O;
1812 | GROUPING: G R O U P I N G;
1813 | GROUPING_ID: G R O U P I N G '_' I D;
1814 | HADR: H A D R;
1815 | HASH: H A S H;
1816 | HONOR_BROKER_PRIORITY: H O N O R '_' B R O K E R '_' P R I O R I T Y;
1817 | HOURS: H O U R S;
1818 | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX: I G N O R E '_' N O N C L U S T E R E D '_' C O L U M N S T O R E '_' I N D E X;
1819 | IMMEDIATE: I M M E D I A T E;
1820 | IMPERSONATE: I M P E R S O N A T E;
1821 | INCREMENTAL: I N C R E M E N T A L;
1822 | INPUT: I N P U T;
1823 | INT: I N T;
1824 | INSENSITIVE: I N S E N S I T I V E;
1825 | INSERTED: I N S E R T E D;
1826 | ISOLATION: I S O L A T I O N;
1827 | IO: I O;
1828 | KB: K B;
1829 | KEEP: K E E P;
1830 | KEEPFIXED: K E E P F I X E D;
1831 | KEYSET: K E Y S E T;
1832 | LAG: L A G;
1833 | LAST: L A S T;
1834 | LAST_VALUE: L A S T '_' V A L U E;
1835 | LEAD: L E A D;
1836 | LEVEL: L E V E L;
1837 | LOCAL: L O C A L;
1838 | LOCK_ESCALATION: L O C K '_' E S C A L A T I O N;
1839 | LOGIN: L O G I N;
1840 | LOOP: L O O P;
1841 | MARK: M A R K;
1842 | MAX: M A X;
1843 | MAXDOP: M A X D O P;
1844 | MAXRECURSION: M A X R E C U R S I O N;
1845 | MAXSIZE: M A X S I Z E;
1846 | MB: M B;
1847 | MEMORY_OPTIMIZED_DATA: M E M O R Y '_' O P T I M I Z E D '_' D A T A;
1848 | MIN: M I N;
1849 | MINUTES: M I N U T E S;
1850 | MIN_ACTIVE_ROWVERSION: M I N '_' A C T I V E '_' R O W V E R S I O N;
1851 | MIXED_PAGE_ALLOCATION: M I X E D '_' P A G E '_' A L L O C A T I O N;
1852 | MODIFY: M O D I F Y;
1853 | MULTI_USER: M U L T I '_' U S E R;
1854 | NAME: N A M E;
1855 | NESTED_TRIGGERS: N E S T E D '_' T R I G G E R S;
1856 | NEW_BROKER: N E W '_' B R O K E R;
1857 | NOCOUNT: N O C O U N T;
1858 | NOEXPAND: N O E X P A N D;
1859 | NON_TRANSACTED_ACCESS: N O N '_' T R A N S A C T E D '_' A C C E S S;
1860 | NORECOMPUTE: N O R E C O M P U T E;
1861 | NO_WAIT: N O '_' W A I T;
1862 | NTILE: N T I L E;
1863 | NUMBER: N U M B E R;
1864 | NUMERIC_ROUNDABORT: N U M E R I C '_' R O U N D A B O R T;
1865 | OFFLINE: O F F L I N E;
1866 | OFFSET: O F F S E T;
1867 | ONLINE: O N L I N E;
1868 | ONLY: O N L Y;
1869 | OPTIMISTIC: O P T I M I S T I C;
1870 | OPTIMIZE: O P T I M I Z E;
1871 | OUT: O U T;
1872 | OUTPUT: O U T P U T;
1873 | OWNER: O W N E R;
1874 | PAGE_VERIFY: P A G E '_' V E R I F Y;
1875 | PARAMETERIZATION: P A R A M E T E R I Z A T I O N;
1876 | PARSE: P A R S E;
1877 | PARTITION: P A R T I T I O N;
1878 | PATH: P A T H;
1879 | PERCENTILE_CONT: P E R C E N T I L E '_' C O N T;
1880 | PRECEDING: P R E C E D I N G;
1881 | PRIOR: P R I O R;
1882 | PRIVILEGES: P R I V I L E G E S;
1883 | QUOTED_IDENTIFIER: Q U O T E D '_' I D E N T I F I E R;
1884 | RANGE: R A N G E;
1885 | RANK: R A N K;
1886 | READONLY: R E A D O N L Y;
1887 | READ_COMMITTED_SNAPSHOT: R E A D '_' C O M M I T T E D '_' S N A P S H O T;
1888 | READ_ONLY: R E A D '_' O N L Y;
1889 | READ_WRITE: R E A D '_' W R I T E;
1890 | RECOMPILE: R E C O M P I L E;
1891 | RECOVERY: R E C O V E R Y;
1892 | RECURSIVE_TRIGGERS: R E C U R S I V E '_' T R I G G E R S;
1893 | RELATIVE: R E L A T I V E;
1894 | REMOTE: R E M O T E;
1895 | REPEATABLE: R E P E A T A B L E;
1896 | RESTRICTED_USER: R E S T R I C T E D '_' U S E R;
1897 | ROBUST: R O B U S T;
1898 | ROLLUP: R O L L U P;
1899 | ROOT: R O O T;
1900 | ROW: R O W;
1901 | ROWGUID: R O W G U I D;
1902 | ROWS: R O W S;
1903 | ROW_NUMBER: R O W '_' N U M B E R;
1904 | SAMPLE: S A M P L E;
1905 | SCHEMABINDING: S C H E M A B I N D I N G;
1906 | SCROLL: S C R O L L;
1907 | SCROLL_LOCKS: S C R O L L '_' L O C K S;
1908 | SECONDS: S E C O N D S;
1909 | SELF: S E L F;
1910 | SERIALIZABLE: S E R I A L I Z A B L E;
1911 | SETS: S E T S;
1912 | SHOWPLAN: S H O W P L A N;
1913 | SIMPLE: S I M P L E;
1914 | SINGLE_USER: S I N G L E '_' U S E R;
1915 | SIZE: S I Z E;
1916 | SMALLINT: S M A L L I N T;
1917 | SNAPSHOT: S N A P S H O T;
1918 | SPATIAL_WINDOW_MAX_CELLS: S P A T I A L '_' W I N D O W '_' M A X '_' C E L L S;
1919 | STATIC: S T A T I C;
1920 | STATS_STREAM: S T A T S '_' S T R E A M;
1921 | STDEV: S T D E V;
1922 | STDEVP: S T D E V P;
1923 | STRING_AGG: S T R I N G '_' A G G;
1924 | STRING_SPLIT: S T R I N G '_' S P L I T;
1925 | SUM: S U M;
1926 | TAKE: T A K E;
1927 | TARGET_RECOVERY_TIME: T A R G E T '_' R E C O V E R Y '_' T I M E;
1928 | TB: T B;
1929 | TEXTIMAGE_ON: T E X T I M A G E '_' O N;
1930 | THROW: T H R O W;
1931 | TIES: T I E S;
1932 | TIME: T I M E;
1933 | TINYINT: T I N Y I N T;
1934 | TORN_PAGE_DETECTION: T O R N '_' P A G E '_' D E T E C T I O N;
1935 | TRANSFORM_NOISE_WORDS: T R A N S F O R M '_' N O I S E '_' W O R D S;
1936 | TRUSTWORTHY: T R U S T W O R T H Y;
1937 | TRY: T R Y;
1938 | TWO_DIGIT_YEAR_CUTOFF: T W O '_' D I G I T '_' Y E A R '_' C U T O F F;
1939 | TYPE: T Y P E;
1940 | TYPE_WARNING: T Y P E '_' W A R N I N G;
1941 | UNBOUNDED: U N B O U N D E D;
1942 | UNCOMMITTED: U N C O M M I T T E D;
1943 | UNKNOWN: U N K N O W N;
1944 | UNLIMITED: U N L I M I T E D;
1945 | USING: U S I N G;
1946 | VAR: V A R;
1947 | VARP: V A R P;
1948 | VIEWS: V I E W S;
1949 | VIEW_METADATA: V I E W '_' M E T A D A T A;
1950 | WORK: W O R K;
1951 | XML: X M L;
1952 | XMLNAMESPACES: X M L N A M E S P A C E S;
1953 | ZONE: Z O N E;
1954 |
1955 | DOLLAR_ACTION: '$' A C T I O N;
1956 |
1957 | SPACE: [ \t\r\n]+ -> skip;
1958 | COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
1959 | LINE_COMMENT: '--' ~[\r\n]* -> channel(HIDDEN);
1960 |
1961 | // TODO: ID can be not only Latin.
1962 | DOUBLE_QUOTE_ID: '"' ~'"'+ '"';
1963 | SQUARE_BRACKET_ID: '[' ~']'+ ']';
1964 | LOCAL_ID: '@' ([a-zA-Z_$@#0-9] | FullWidthLetter)+;
1965 | DECIMAL: DEC_DIGIT+;
1966 | ID: ( [a-zA-Z_#] | FullWidthLetter) ( [a-zA-Z_#$@0-9] | FullWidthLetter )*;
1967 | STRING: N? '\'' (~'\'' | '\'\'')* '\'';
1968 | BINARY: '0' X HEX_DIGIT*;
1969 | FLOAT: DEC_DOT_DEC;
1970 | REAL: DEC_DOT_DEC (E [+-]? DEC_DIGIT+)?;
1971 |
1972 | EQUAL: '=';
1973 |
1974 | GREATER: '>';
1975 | LESS: '<';
1976 | EXCLAMATION: '!';
1977 |
1978 | PLUS_ASSIGN: '+=';
1979 | MINUS_ASSIGN: '-=';
1980 | MULT_ASSIGN: '*=';
1981 | DIV_ASSIGN: '/=';
1982 | MOD_ASSIGN: '%=';
1983 | AND_ASSIGN: '&=';
1984 | XOR_ASSIGN: '^=';
1985 | OR_ASSIGN: '|=';
1986 |
1987 | DOT: '.';
1988 | UNDERLINE: '_';
1989 | AT_SIGN: '@';
1990 | SHARP: '#';
1991 | DOLLAR: '$';
1992 | LR_BRACKET: '(';
1993 | RR_BRACKET: ')';
1994 | COMMA: ',';
1995 | SEMI: ';';
1996 | COLON: ':';
1997 | STAR: '*';
1998 | DIVIDE: '/';
1999 | MODULE: '%';
2000 | PLUS: '+';
2001 | MINUS: '-';
2002 | BIT_NOT: '~';
2003 | BIT_OR: '|';
2004 | BIT_AND: '&';
2005 | BIT_XOR: '^';
2006 |
2007 | fragment LETTER: [a-zA-Z_];
2008 | fragment DEC_DOT_DEC: (DEC_DIGIT+ '.' DEC_DIGIT+ | DEC_DIGIT+ '.' | '.' DEC_DIGIT+);
2009 | fragment HEX_DIGIT: [0-9A-Fa-f];
2010 | fragment DEC_DIGIT: [0-9];
2011 |
2012 | fragment A: [aA];
2013 | fragment B: [bB];
2014 | fragment C: [cC];
2015 | fragment D: [dD];
2016 | fragment E: [eE];
2017 | fragment F: [fF];
2018 | fragment G: [gG];
2019 | fragment H: [hH];
2020 | fragment I: [iI];
2021 | fragment J: [jJ];
2022 | fragment K: [kK];
2023 | fragment L: [lL];
2024 | fragment M: [mM];
2025 | fragment N: [nN];
2026 | fragment O: [oO];
2027 | fragment P: [pP];
2028 | fragment Q: [qQ];
2029 | fragment R: [rR];
2030 | fragment S: [sS];
2031 | fragment T: [tT];
2032 | fragment U: [uU];
2033 | fragment V: [vV];
2034 | fragment W: [wW];
2035 | fragment X: [xX];
2036 | fragment Y: [yY];
2037 | fragment Z: [zZ];
2038 | fragment FullWidthLetter
2039 | : '\u00c0'..'\u00d6'
2040 | | '\u00d8'..'\u00f6'
2041 | | '\u00f8'..'\u00ff'
2042 | | '\u0100'..'\u1fff'
2043 | | '\u2c00'..'\u2fff'
2044 | | '\u3040'..'\u318f'
2045 | | '\u3300'..'\u337f'
2046 | | '\u3400'..'\u3fff'
2047 | | '\u4e00'..'\u9fff'
2048 | | '\ua000'..'\ud7ff'
2049 | | '\uf900'..'\ufaff'
2050 | | '\uff00'..'\ufff0'
2051 | // | '\u10000'..'\u1F9FF' //not support four bytes chars
2052 | // | '\u20000'..'\u2FA1F'
2053 | ;
2054 |
--------------------------------------------------------------------------------