├── 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 | [![Build Status](https://travis-ci.org/datacamp/antlr-tsql.svg?branch=master)](https://travis-ci.org/datacamp/antlr-tsql) 4 | [![PyPI version](https://badge.fury.io/py/antlr-tsql.svg)](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 | --------------------------------------------------------------------------------