initial support for udf, inline k9 block, assumptions
This commit is contained in:
@@ -33,6 +33,7 @@ EXCEPT = keyword("except")
|
|||||||
FETCH = keyword("fetch").suppress()
|
FETCH = keyword("fetch").suppress()
|
||||||
FROM = keyword("from").suppress()
|
FROM = keyword("from").suppress()
|
||||||
FULL = keyword("full")
|
FULL = keyword("full")
|
||||||
|
FUNCTION = keyword("function").suppress()
|
||||||
GROUP = keyword("group").suppress()
|
GROUP = keyword("group").suppress()
|
||||||
HAVING = keyword("having").suppress()
|
HAVING = keyword("having").suppress()
|
||||||
INNER = keyword("inner")
|
INNER = keyword("inner")
|
||||||
@@ -109,6 +110,7 @@ INDF = (
|
|||||||
# https://prestodb.io/docs/current/functions/comparison.html#is-distinct-from-and-is-not-distinct-from
|
# https://prestodb.io/docs/current/functions/comparison.html#is-distinct-from-and-is-not-distinct-from
|
||||||
keyword("is not distinct from").set_parser_name("ne!")
|
keyword("is not distinct from").set_parser_name("ne!")
|
||||||
)
|
)
|
||||||
|
FASSIGN = Literal(":=").set_parser_name("fassign") # Assignment in UDFs
|
||||||
NEQ = (Literal("!=") | Literal("<>")).set_parser_name("neq")
|
NEQ = (Literal("!=") | Literal("<>")).set_parser_name("neq")
|
||||||
LAMBDA = Literal("->").set_parser_name("lambda")
|
LAMBDA = Literal("->").set_parser_name("lambda")
|
||||||
|
|
||||||
@@ -181,6 +183,7 @@ RESERVED = MatchFirst([
|
|||||||
FOREIGN,
|
FOREIGN,
|
||||||
FROM,
|
FROM,
|
||||||
FULL,
|
FULL,
|
||||||
|
FUNCTION,
|
||||||
GROUP_BY,
|
GROUP_BY,
|
||||||
GROUP,
|
GROUP,
|
||||||
HAVING,
|
HAVING,
|
||||||
@@ -224,7 +227,10 @@ RESERVED = MatchFirst([
|
|||||||
WITH,
|
WITH,
|
||||||
WITHIN,
|
WITHIN,
|
||||||
])
|
])
|
||||||
|
L_INLINE = Literal("<k>").suppress()
|
||||||
|
R_INLINE = Literal("</k>").suppress()
|
||||||
|
LBRACE = Literal("{").suppress()
|
||||||
|
RBRACE = Literal("}").suppress()
|
||||||
LB = Literal("(").suppress()
|
LB = Literal("(").suppress()
|
||||||
RB = Literal(")").suppress()
|
RB = Literal(")").suppress()
|
||||||
EQ = Char("=").suppress()
|
EQ = Char("=").suppress()
|
||||||
@@ -282,6 +288,7 @@ precedence = {
|
|||||||
"lambda": 12,
|
"lambda": 12,
|
||||||
"join": 18,
|
"join": 18,
|
||||||
"list": 18,
|
"list": 18,
|
||||||
|
"function": 30,
|
||||||
"select": 30,
|
"select": 30,
|
||||||
"from": 30,
|
"from": 30,
|
||||||
"window": 35,
|
"window": 35,
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
# Contact: Kyle Lahnakoski (kyle@lahnakoski.com)
|
# Contact: Kyle Lahnakoski (kyle@lahnakoski.com)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from operator import add
|
||||||
|
from textwrap import indent
|
||||||
|
from mo_parsing import whitespaces
|
||||||
from mo_parsing.helpers import restOfLine
|
from mo_parsing.helpers import restOfLine
|
||||||
from mo_parsing.infix import delimited_list
|
from mo_parsing.infix import delimited_list
|
||||||
from mo_parsing.whitespaces import NO_WHITESPACE, Whitespace
|
from mo_parsing.whitespaces import NO_WHITESPACE, Whitespace
|
||||||
@@ -77,6 +79,7 @@ def parser(literal_string, ident, sqlserver=False):
|
|||||||
|
|
||||||
var_name = ~RESERVED + ident
|
var_name = ~RESERVED + ident
|
||||||
|
|
||||||
|
inline_kblock = (L_INLINE + SkipTo(R_INLINE, include=True))("k9")
|
||||||
# EXPRESSIONS
|
# EXPRESSIONS
|
||||||
expr = Forward()
|
expr = Forward()
|
||||||
column_type, column_definition, column_def_references = get_column_type(
|
column_type, column_definition, column_def_references = get_column_type(
|
||||||
@@ -342,6 +345,22 @@ def parser(literal_string, ident, sqlserver=False):
|
|||||||
)
|
)
|
||||||
) / to_join_call
|
) / to_join_call
|
||||||
|
|
||||||
|
fassign = Group(var_name("var") + Suppress(FASSIGN) + expr("expr") + Suppress(";"))("assignment")
|
||||||
|
fassigns = fassign + ZeroOrMore(fassign, Whitespace(white=" \t"))
|
||||||
|
|
||||||
|
fbody = (Optional(fassigns) + expr("ret"))
|
||||||
|
|
||||||
|
udf = (
|
||||||
|
FUNCTION
|
||||||
|
+ var_name("fname")
|
||||||
|
+ LB
|
||||||
|
+ Optional(delimited_list(var_name)("params"))
|
||||||
|
+ RB
|
||||||
|
+ LBRACE
|
||||||
|
+ fbody
|
||||||
|
+ RBRACE
|
||||||
|
)
|
||||||
|
|
||||||
selection = (
|
selection = (
|
||||||
(SELECT + DISTINCT + ON + LB)
|
(SELECT + DISTINCT + ON + LB)
|
||||||
+ delimited_list(select_column)("distinct_on")
|
+ delimited_list(select_column)("distinct_on")
|
||||||
@@ -407,11 +426,13 @@ def parser(literal_string, ident, sqlserver=False):
|
|||||||
)
|
)
|
||||||
+ RB,
|
+ RB,
|
||||||
)
|
)
|
||||||
assumption = (ASSUMING + (ASC|DESC)("assumption"))
|
|
||||||
|
assumption = Group((ASC|DESC) ("ord") + var_name("attrib"))
|
||||||
|
assumptions = (ASSUMING + Group(delimited_list(assumption))("assumptions"))
|
||||||
|
|
||||||
table_source << Group(
|
table_source << Group(
|
||||||
((LB + query + RB) | stack | call_function | var_name)("value")
|
((LB + query + RB) | stack | call_function | var_name)("value")
|
||||||
+ Optional(assumption)
|
+ Optional(assumptions)
|
||||||
+ Optional(flag("with ordinality"))
|
+ Optional(flag("with ordinality"))
|
||||||
+ Optional(tablesample)
|
+ Optional(tablesample)
|
||||||
+ alias
|
+ alias
|
||||||
@@ -600,7 +621,9 @@ def parser(literal_string, ident, sqlserver=False):
|
|||||||
) / to_json_call
|
) / to_json_call
|
||||||
|
|
||||||
return (
|
return (
|
||||||
query
|
inline_kblock
|
||||||
|
| udf
|
||||||
|
| query
|
||||||
| (insert | update | delete)
|
| (insert | update | delete)
|
||||||
| (create_table | create_view | create_cache | create_index)
|
| (create_table | create_view | create_cache | create_index)
|
||||||
| (drop_table | drop_view | drop_index)
|
| (drop_table | drop_view | drop_index)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
FUNCTION
|
||||||
|
execStrategy ( alloc , mavgday , mavgmonth , px ) {
|
||||||
|
buySignal := mavgday > mavgmonth ;
|
||||||
|
f := a + b ;
|
||||||
|
alloc * prd (
|
||||||
|
CASE maxs ( buySignal )
|
||||||
|
WHEN TRUE THEN
|
||||||
|
CASE buySignal
|
||||||
|
WHEN TRUE THEN 1 / px
|
||||||
|
ELSE px
|
||||||
|
END
|
||||||
|
ELSE 1
|
||||||
|
END )
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
WITH
|
||||||
|
Target (Id , TradeDate , ClosePrice ) AS
|
||||||
|
( SELECT
|
||||||
|
Id , TradeDate , ClosePrice
|
||||||
|
FROM price
|
||||||
|
WHERE Id IN stock10 AND
|
||||||
|
TradeDate >= startYear10 AND
|
||||||
|
TradeDate <= startYear10 + 365 * 10),
|
||||||
|
weekly (Id , bucket , name , low , high , mean ) AS
|
||||||
|
( SELECT
|
||||||
|
Id ,
|
||||||
|
timeBucket ,
|
||||||
|
" weekly " ,
|
||||||
|
min ( ClosePrice ) ,
|
||||||
|
max ( ClosePrice ) ,
|
||||||
|
avg ( ClosePrice )
|
||||||
|
FROM Target
|
||||||
|
GROUP BY Id , getWeek ( TradeDate ) as
|
||||||
|
timeBucket ),
|
||||||
|
monthly ( Id , bucket , name , low , high , mean ) AS
|
||||||
|
( SELECT
|
||||||
|
Id ,
|
||||||
|
timeBucket ,
|
||||||
|
" monthly " ,
|
||||||
|
min ( ClosePrice ) ,
|
||||||
|
max ( ClosePrice ) ,
|
||||||
|
avg ( ClosePrice )
|
||||||
|
FROM Target
|
||||||
|
GROUP BY Id , getMonth ( TradeDate ) as
|
||||||
|
timeBucket ),
|
||||||
|
yearly (Id , bucket , name , low , high , mean ) AS
|
||||||
|
( SELECT
|
||||||
|
Id ,
|
||||||
|
timeBucket ,
|
||||||
|
" yearly " ,
|
||||||
|
min ( ClosePrice ) ,
|
||||||
|
max ( ClosePrice ) ,
|
||||||
|
avg ( ClosePrice )
|
||||||
|
FROM Target
|
||||||
|
GROUP BY Id , getYear ( TradeDate ) as
|
||||||
|
timeBucket )
|
||||||
|
SELECT
|
||||||
|
Id , bucket , name , low , high , mean
|
||||||
|
FROM
|
||||||
|
CONCATENATE ( weekly , monthly , yearly )
|
||||||
|
ASSUMING ASC Id , ASC name , ASC bucket
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
|
import re
|
||||||
import mo_sql_parsing as parser
|
import mo_sql_parsing as parser
|
||||||
|
|
||||||
|
ws = re.compile(r'\s+')
|
||||||
|
|
||||||
q = 'SELECT p.Name, v.Name FROM Production.Product p JOIN Purchasing.ProductVendor pv ON p.ProductID = pv.ProductID JOIN Purchasing.Vendor v ON pv.BusinessEntityID = v.BusinessEntityID WHERE ProductSubcategoryID = 15 ORDER BY v.Name;'
|
q = 'SELECT p.Name, v.Name FROM Production.Product p JOIN Purchasing.ProductVendor pv ON p.ProductID = pv.ProductID JOIN Purchasing.Vendor v ON pv.BusinessEntityID = v.BusinessEntityID WHERE ProductSubcategoryID = 15 ORDER BY v.Name;'
|
||||||
|
|
||||||
res = parser.parse(q)
|
res = parser.parse(q)
|
||||||
@@ -8,8 +12,16 @@ print(res)
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
q = input()
|
q = input()
|
||||||
|
trimed = ws.sub(' ', q.lower()).split(' ')
|
||||||
|
if trimed[0] == 'file':
|
||||||
|
fn = 'q.sql' if len(trimed) <= 1 or len(trimed[1]) == 0 \
|
||||||
|
else trimed[1]
|
||||||
|
|
||||||
|
with open(fn, 'r') as file:
|
||||||
|
contents = file.read()
|
||||||
|
stmts = parser.parse(contents)
|
||||||
|
continue
|
||||||
stmts = parser.parse(q)
|
stmts = parser.parse(q)
|
||||||
for s in stmts:
|
print(stmts)
|
||||||
print(s)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(type(e), e)
|
||||||
|
|||||||
Reference in New Issue
Block a user