# encoding: utf-8 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # Contact: Kyle Lahnakoski (kyle@lahnakoski.com) # Bill Sun 2022 - 2023 # KNOWN TYPES from mo_parsing import Forward, Group, Optional, MatchFirst, Literal, ZeroOrMore, export from mo_parsing.infix import delimited_list, RIGHT_ASSOC, LEFT_ASSOC from aquery_parser.keywords import ( RB, LB, NEG, NOT, BINARY_NOT, NULL, EQ, KNOWN_OPS, LT, GT, ) from aquery_parser.utils import ( keyword, to_json_call, int_num, ansi_string, ansi_ident, assign, flag, ) _size = Optional(LB + int_num("params") + RB) _sizes = Optional(LB + delimited_list(int_num("params")) + RB) simple_types = Forward() BIGINT = Group(keyword("bigint")("op") + Optional(_size)+Optional(flag("unsigned"))) / to_json_call BOOL = Group(keyword("bool")("op")) / to_json_call BOOLEAN = Group(keyword("boolean")("op")) / to_json_call DOUBLE = Group(keyword("double")("op")) / to_json_call FLOAT64 = Group(keyword("float64")("op")) / to_json_call FLOAT = Group(keyword("float")("op")) / to_json_call GEOMETRY = Group(keyword("geometry")("op")) / to_json_call INTEGER = Group(keyword("integer")("op")) / to_json_call INT = (keyword("int")("op") + _size) / to_json_call INT32 = Group(keyword("int32")("op")) / to_json_call INT64 = Group(keyword("int64")("op")) / to_json_call REAL = Group(keyword("real")("op")) / to_json_call TEXT = Group(keyword("text")("op")) / to_json_call SMALLINT = Group(keyword("smallint")("op")) / to_json_call STRING = Group(keyword("string")("op")) / to_json_call BLOB = (keyword("blob")("op") + _size) / to_json_call BYTES = (keyword("bytes")("op") + _size) / to_json_call CHAR = (keyword("char")("op") + _size) / to_json_call NCHAR = (keyword("nchar")("op") + _size) / to_json_call VARCHAR = (keyword("varchar")("op") + _size) / to_json_call VARCHAR2 = (keyword("varchar2")("op") + _size) / to_json_call VARBINARY = (keyword("varbinary")("op") + _size) / to_json_call TINYINT = (keyword("tinyint")("op") + _size) / to_json_call UUID = Group(keyword("uuid")("op")) / to_json_call DECIMAL = (keyword("decimal")("op") + _sizes) / to_json_call DOUBLE_PRECISION = ( Group((keyword("double precision") / (lambda: "double_precision"))("op")) / to_json_call ) NUMERIC = (keyword("numeric")("op") + _sizes) / to_json_call NUMBER = (keyword("number")("op") + _sizes) / to_json_call MAP_TYPE = ( keyword("map")("op") + LB + delimited_list(simple_types("params")) + RB ) / to_json_call ARRAY_TYPE = (keyword("array")("op") + LB + simple_types("params") + RB) / to_json_call DATE = keyword("date") DATETIME = keyword("datetime") DATETIME_W_TIMEZONE = keyword("datetime with time zone") TIME = keyword("time") TIMESTAMP = keyword("timestamp") TIMESTAMP_W_TIMEZONE = keyword("timestamp with time zone") TIMESTAMPTZ = keyword("timestamptz") TIMETZ = keyword("timetz") time_functions = DATE | DATETIME | TIME | TIMESTAMP | TIMESTAMPTZ | TIMETZ # KNOWNN TIME TYPES _format = Optional((ansi_string | ansi_ident)("params")) DATE_TYPE = (DATE("op") + _format) / to_json_call DATETIME_TYPE = (DATETIME("op") + _format) / to_json_call DATETIME_W_TIMEZONE_TYPE = (DATETIME_W_TIMEZONE("op") + _format) / to_json_call TIME_TYPE = (TIME("op") + _format) / to_json_call TIMESTAMP_TYPE = (TIMESTAMP("op") + _format) / to_json_call TIMESTAMP_W_TIMEZONE_TYPE = (TIMESTAMP_W_TIMEZONE("op") + _format) / to_json_call TIMESTAMPTZ_TYPE = (TIMESTAMPTZ("op") + _format) / to_json_call TIMETZ_TYPE = (TIMETZ("op") + _format) / to_json_call simple_types << MatchFirst([ ARRAY_TYPE, BIGINT, BOOL, BOOLEAN, BLOB, BYTES, CHAR, DATE_TYPE, DATETIME_W_TIMEZONE_TYPE, DATETIME_TYPE, DECIMAL, DOUBLE_PRECISION, DOUBLE, FLOAT64, FLOAT, GEOMETRY, MAP_TYPE, INTEGER, INT, INT32, INT64, NCHAR, NUMBER, NUMERIC, REAL, TEXT, SMALLINT, STRING, TIME_TYPE, TIMESTAMP_W_TIMEZONE_TYPE, TIMESTAMP_TYPE, TIMESTAMPTZ_TYPE, TIMETZ_TYPE, TINYINT, UUID, VARCHAR, VARCHAR2, VARBINARY, ]) CASTING = (Literal("::").suppress() + simple_types("params")).set_parser_name("cast") KNOWN_OPS.insert(0, CASTING) unary_ops = { NEG: RIGHT_ASSOC, NOT: RIGHT_ASSOC, BINARY_NOT: RIGHT_ASSOC, CASTING: LEFT_ASSOC, } def get_column_type(expr, var_name, literal_string): column_definition = Forward() column_type = Forward().set_parser_name("column type") struct_type = ( keyword("struct")("op") + LT.suppress() + Group(delimited_list(column_definition))("params") + GT.suppress() ) / to_json_call row_type = ( keyword("row")("op") + LB + Group(delimited_list(column_definition))("params") + RB ) / to_json_call array_type = ( keyword("array")("op") + ( ( LT.suppress() + Group(delimited_list(column_type))("params") + GT.suppress() ) | (LB + Group(delimited_list(column_type))("params") + RB) ) ) / to_json_call column_type << (struct_type | row_type | array_type | simple_types) column_def_identity = ( assign( "generated", (keyword("always") | keyword("by default") / (lambda: "by_default")), ) + keyword("as identity").suppress() + Optional(assign("start with", int_num)) + Optional(assign("increment by", int_num)) ) column_def_references = assign( "references", var_name("table") + LB + delimited_list(var_name)("columns") + RB, ) column_options = ZeroOrMore( ((NOT + NULL) / (lambda: False))("nullable") | (NULL / (lambda t: True))("nullable") | flag("unique") | flag("auto_increment") | assign("comment", literal_string) | assign("collate", Optional(EQ) + var_name) | flag("primary key") | column_def_identity("identity") | column_def_references | assign("check", LB + expr + RB) | assign("default", expr) ).set_parser_name("column_options") column_definition << Group( var_name("name") + (column_type | var_name)("type") + column_options ).set_parser_name("column_definition") return column_type, column_definition, column_def_references export("aquery_parser.utils", unary_ops)