Single Table query part 1
This commit is contained in:
+29
-17
@@ -1,10 +1,11 @@
|
||||
from operator import index
|
||||
from engine.utils import base62uuid
|
||||
|
||||
from copy import copy
|
||||
# replace column info with this later.
|
||||
class ColRef:
|
||||
def __init__(self, cname, _ty, cobj, cnt, table:'TableInfo', name, id, compound = False):
|
||||
self.cname = cname
|
||||
self.cxt_name = None
|
||||
self.cname = cname # column object location
|
||||
self.cxt_name = None # column object in context
|
||||
self.type = _ty
|
||||
self.cobj = cobj
|
||||
self.cnt = cnt
|
||||
@@ -28,6 +29,7 @@ class ColRef:
|
||||
base_name = f'{base_name}_{counter}'
|
||||
self.cxt_name = base_name
|
||||
cxt.columns_in_context[self] = base_name
|
||||
# TODO: change this to cname;
|
||||
cxt.emit(f'auto& {base_name} = *(ColRef<{self.type}> *)(&{self.table.cxt_name}->colrefs[{self.id}]);')
|
||||
elif self.cxt_name is None:
|
||||
self.cxt_name = cxt.columns_in_context[self]
|
||||
@@ -44,7 +46,9 @@ class ColRef:
|
||||
self.__arr__[key] = value
|
||||
|
||||
def __str__(self):
|
||||
return self.cname
|
||||
return self.reference()
|
||||
def __repr__(self):
|
||||
return self.reference()
|
||||
|
||||
class TableInfo:
|
||||
|
||||
@@ -87,6 +91,7 @@ class TableInfo:
|
||||
|
||||
self.cxt.emit(f'auto& {base_name} = *(TableInfo{type_tags} *)(cxt->tables[{self.table_name}]);')
|
||||
def refer_all(self):
|
||||
self.reference()
|
||||
for c in self.columns:
|
||||
c.reference()
|
||||
def add_cols(self, cols, new = True):
|
||||
@@ -95,12 +100,13 @@ class TableInfo:
|
||||
def add_col(self, c, new = True, i = 0):
|
||||
_ty = c['type']
|
||||
if new:
|
||||
cname =f'{self.table_name}->colrefs[{i}].scast<int>()'
|
||||
cname =f'get<{i}>({self.table_name})'
|
||||
_ty = _ty if type(c) is ColRef else list(_ty.keys())[0]
|
||||
col_object = ColRef(cname, _ty, c, 1, self,c['name'], len(self.columns))
|
||||
else:
|
||||
col_object = c
|
||||
cname = c.cname
|
||||
c.table = self
|
||||
self.cxt.ccols_byname[cname] = col_object
|
||||
self.columns_byname[c['name']] = col_object
|
||||
self.columns.append(col_object)
|
||||
@@ -156,7 +162,7 @@ class TableInfo:
|
||||
self.cxt.tables_byname[alias] = self
|
||||
self.alias.add(alias)
|
||||
|
||||
def parse_tablenames(self, colExpr, materialize = True):
|
||||
def parse_tablenames(self, colExpr, materialize = True, raw = False):
|
||||
self.get_col = self.get_col if materialize else self.get_col_d
|
||||
|
||||
parsedColExpr = colExpr.split('.')
|
||||
@@ -168,13 +174,12 @@ class TableInfo:
|
||||
if datasource is None:
|
||||
raise ValueError(f'Table name/alias not defined{parsedColExpr[0]}')
|
||||
else:
|
||||
ret = datasource.get_col(parsedColExpr[1])
|
||||
if self.groupinfo is not None and ret:
|
||||
ret = f"{ret.reference()}[{'start' if ret in self.groupinfo.referenced else 'range'}]"
|
||||
else:
|
||||
ret = ret.reference()
|
||||
return ret
|
||||
|
||||
ret = datasource.parse_tablenames(parsedColExpr[1], raw)
|
||||
from engine.expr import index_expr
|
||||
string = ret.reference() + index_expr
|
||||
if self.groupinfo is not None and ret and ret in self.groupinfo.raw_groups:
|
||||
string = f'get<{self.groupinfo.raw_groups.index(ret)}>({{y}})'
|
||||
return string, ret if raw else string
|
||||
class View:
|
||||
def __init__(self, context, table = None, tmp = True):
|
||||
self.table: TableInfo = table
|
||||
@@ -187,7 +192,11 @@ class View:
|
||||
self.context.emit(f'{self.name}:()')
|
||||
|
||||
class Context:
|
||||
function_head = 'extern \"C\" int dllmain(Context* cxt){ \n'
|
||||
function_head = '''
|
||||
extern "C" int __DLLEXPORT__ dllmain(Context* cxt) {
|
||||
using namespace std;
|
||||
using namespace types;
|
||||
'''
|
||||
def __init__(self):
|
||||
self.tables:List[TableInfo] = []
|
||||
self.tables_byname = dict()
|
||||
@@ -208,7 +217,8 @@ class Context:
|
||||
# and will be deactivated when the `from' is out of scope
|
||||
self.datasource = None
|
||||
self.ds_stack = []
|
||||
|
||||
self.scans = []
|
||||
self.removing_scan = False
|
||||
def add_table(self, table_name, cols):
|
||||
tbl = TableInfo(table_name, cols, self)
|
||||
self.tables.append(tbl)
|
||||
@@ -257,6 +267,10 @@ class Context:
|
||||
return ds
|
||||
else:
|
||||
return None
|
||||
def remove_scan(self, scan, str_scan):
|
||||
self.emit(str_scan)
|
||||
self.scans.remove(scan)
|
||||
|
||||
def finalize(self):
|
||||
if not self.finalized:
|
||||
headers = ''
|
||||
@@ -282,8 +296,6 @@ class ast_node:
|
||||
self.context = parent.context if context is None else context
|
||||
self.parent = parent
|
||||
self.datasource = None
|
||||
for h in self.header:
|
||||
self.context.headers.add(h)
|
||||
self.init(node)
|
||||
self.produce(node)
|
||||
self.spawn(node)
|
||||
|
||||
+38
-17
@@ -1,21 +1,35 @@
|
||||
# code-gen for data decl languages
|
||||
|
||||
from engine.ast import ColRef, TableInfo, ast_node, include
|
||||
from engine.ast import ColRef, TableInfo, ast_node, Context, include
|
||||
from engine.utils import base62uuid
|
||||
|
||||
class create_table(ast_node):
|
||||
name = 'create_table'
|
||||
def __init__(self, parent: "ast_node", node, context: Context = None, cexpr = None):
|
||||
self.cexpr = cexpr
|
||||
super().__init__(parent, node, context)
|
||||
def produce(self, node):
|
||||
ct = node[self.name]
|
||||
tbl = self.context.add_table(ct['name'], ct['columns'])
|
||||
if type(node) is not TableInfo:
|
||||
ct = node[self.name]
|
||||
tbl = self.context.add_table(ct['name'], ct['columns'])
|
||||
else:
|
||||
tbl = node
|
||||
|
||||
col_type_str = ','.join([c.type for c in tbl.columns])
|
||||
# create tables in c
|
||||
self.emit(f"auto {tbl.table_name} = new TableInfo(\"{tbl.table_name}\", {tbl.n_cols});")
|
||||
self.emit(f"auto {tbl.table_name} = new TableInfo<{col_type_str}>(\"{tbl.table_name}\", {tbl.n_cols});")
|
||||
self.emit("cxt->tables.insert({\"" + tbl.table_name + f"\", {tbl.table_name}"+"});")
|
||||
self.context.tables_in_context[tbl] = tbl.table_name
|
||||
tbl.cxt_name = tbl.table_name
|
||||
for i, c in enumerate(ct['columns']):
|
||||
# TODO: more self awareness
|
||||
self.emit(f"{tbl.table_name}->colrefs[{i}].ty = types::AINT;")
|
||||
|
||||
tbl.refer_all()
|
||||
if self.cexpr is None:
|
||||
for c in tbl.columns:
|
||||
self.emit(f"{c.cxt_name}.init();")
|
||||
else:
|
||||
for i, c in enumerate(tbl.columns):
|
||||
self.emit(f"{c.cxt_name}.init();")
|
||||
self.emit(f"{c.cxt_name} = {self.cexpr[i]()};")
|
||||
|
||||
class insert(ast_node):
|
||||
name = 'insert'
|
||||
def produce(self, node):
|
||||
@@ -42,18 +56,25 @@ class c(ast_node):
|
||||
class load(ast_node):
|
||||
name="load"
|
||||
def produce(self, node):
|
||||
self.context.headers.add('"csv.h"')
|
||||
node = node[self.name]
|
||||
table:TableInfo = self.context.tables_byname[node['table']]
|
||||
n_keys = len(table.columns)
|
||||
keys = ''
|
||||
for _ in range(n_keys):
|
||||
keys+='`tk'+base62uuid(6)
|
||||
tablename = 'l'+base62uuid(7)
|
||||
|
||||
self.emit(f"{tablename}:({keys}!(+(`csv ? 1:\"{node['file']['literal']}\")))[{keys}]")
|
||||
|
||||
table.refer_all()
|
||||
csv_reader_name = 'csv_reader_' + base62uuid(6)
|
||||
col_types = [c.type for c in table.columns]
|
||||
col_tmp_names = ['tmp_'+base62uuid(8) for _ in range(len(table.columns))]
|
||||
# col_type_str = ",".join(col_types)
|
||||
col_names = ','.join([f'"{c.name}"' for c in table.columns])
|
||||
|
||||
self.emit(f'io::CSVReader<{len(col_types)}> {csv_reader_name}("{node["file"]["literal"]}");')
|
||||
self.emit(f'{csv_reader_name}.read_header(io::ignore_extra_column, {col_names});')
|
||||
for t, n in zip(col_types, col_tmp_names):
|
||||
self.emit(f'{t} {n};')
|
||||
self.emit(f'while({csv_reader_name}.read_row({",".join(col_tmp_names)})) {{ \n')
|
||||
for i, c in enumerate(table.columns):
|
||||
self.emit(f'{c.cname}:{tablename}[{i}]')
|
||||
self.emit(f'{c.cxt_name}.emplace_back({col_tmp_names[i]});')
|
||||
self.emit('}')
|
||||
|
||||
|
||||
class outfile(ast_node):
|
||||
name="_outfile"
|
||||
|
||||
+39
-24
@@ -1,5 +1,7 @@
|
||||
from engine.ast import ast_node
|
||||
|
||||
from engine.ast import ast_node, ColRef
|
||||
start_expr = 'f"'
|
||||
index_expr = '{\'\' if x is None and y is None else f\'[{x}]\'}'
|
||||
end_expr = '"'
|
||||
|
||||
class expr(ast_node):
|
||||
name='expr'
|
||||
@@ -8,7 +10,7 @@ class expr(ast_node):
|
||||
'min': 'min',
|
||||
'avg': 'avg',
|
||||
'sum': 'sum',
|
||||
'mod':'mod',
|
||||
'count' : 'count',
|
||||
'mins': ['mins', 'minsw'],
|
||||
'maxs': ['maxs', 'maxsw'],
|
||||
'avgs': ['avgs', 'avgsw'],
|
||||
@@ -19,29 +21,32 @@ class expr(ast_node):
|
||||
'sub':'-',
|
||||
'add':'+',
|
||||
'mul':'*',
|
||||
'div':'%',
|
||||
'div':'/',
|
||||
'mod':'%',
|
||||
'and':'&',
|
||||
'or':'|',
|
||||
'xor' : '^',
|
||||
'gt':'>',
|
||||
'lt':'<',
|
||||
'le':'<=',
|
||||
'gt':'>='
|
||||
}
|
||||
|
||||
compound_ops = {
|
||||
'ge' : [2, lambda x: f'~({x[0]}<{x[1]})'],
|
||||
'le' : [2, lambda x: f'~({x[0]}>{x[1]})'],
|
||||
'count' : [1, lambda x: f'#({x[0]})']
|
||||
}
|
||||
|
||||
unary_ops = {
|
||||
'neg' : '-',
|
||||
'not' : '~'
|
||||
'not' : '!'
|
||||
}
|
||||
|
||||
coumpound_generating_ops = ['mod', 'mins', 'maxs', 'sums'] + \
|
||||
list( binary_ops.keys()) + list(compound_ops.keys()) + list(unary_ops.keys() )
|
||||
|
||||
def __init__(self, parent, node, materialize_cols = True):
|
||||
def __init__(self, parent, node, materialize_cols = True, abs_col = False):
|
||||
self.materialize_cols = materialize_cols
|
||||
self.raw_col = None
|
||||
self.__abs = abs_col
|
||||
ast_node.__init__(self, parent, node, None)
|
||||
|
||||
def init(self, _):
|
||||
@@ -54,7 +59,8 @@ class expr(ast_node):
|
||||
else:
|
||||
self.datasource = self.context.datasource
|
||||
self.udf_map = parent.context.udf_map
|
||||
self.cexpr = ''
|
||||
self._expr = ''
|
||||
self.cexpr = None
|
||||
self.func_maps = {**self.udf_map, **self.builtin_func_maps}
|
||||
|
||||
def produce(self, node):
|
||||
@@ -62,30 +68,31 @@ class expr(ast_node):
|
||||
for key, val in node.items():
|
||||
if key in self.func_maps:
|
||||
# if type(val) in [dict, str]:
|
||||
self.context.headers.add('"./server/aggregations.h"')
|
||||
if type(val) is list and len(val) > 1:
|
||||
cfunc = self.func_maps[key]
|
||||
cfunc = cfunc[len(val) - 1] if type(cfunc) is list else cfunc
|
||||
self.cexpr += f"{cfunc}("
|
||||
self._expr += f"{cfunc}("
|
||||
for i, p in enumerate(val):
|
||||
self.cexpr += expr(self, p).cexpr + (';'if i<len(val)-1 else '')
|
||||
self._expr += expr(self, p)._expr + (','if i<len(val)-1 else '')
|
||||
else:
|
||||
funcname = self.func_maps[key]
|
||||
funcname = funcname[0] if type(funcname) is list else funcname
|
||||
self.cexpr += f"{funcname}("
|
||||
self.cexpr += expr(self, val).cexpr
|
||||
self.cexpr += ')'
|
||||
self._expr += f"{funcname}("
|
||||
self._expr += expr(self, val)._expr
|
||||
self._expr += ')'
|
||||
elif key in self.binary_ops:
|
||||
l = expr(self, val[0]).cexpr
|
||||
r = expr(self, val[1]).cexpr
|
||||
self.cexpr += f'({l}{self.binary_ops[key]}{r})'
|
||||
l = expr(self, val[0])._expr
|
||||
r = expr(self, val[1])._expr
|
||||
self._expr += f'({l}{self.binary_ops[key]}{r})'
|
||||
elif key in self.compound_ops:
|
||||
x = []
|
||||
if type(val) is list:
|
||||
for v in val:
|
||||
x.append(expr(self, v).cexpr)
|
||||
self.cexpr = self.compound_ops[key][1](x)
|
||||
x.append(expr(self, v)._expr)
|
||||
self._expr = self.compound_ops[key][1](x)
|
||||
elif key in self.unary_ops:
|
||||
self.cexpr += f'({expr(self, val).cexpr}{self.unary_ops[key]})'
|
||||
self._expr += f'({expr(self, val)._expr}{self.unary_ops[key]})'
|
||||
else:
|
||||
print(f'Undefined expr: {key}{val}')
|
||||
|
||||
@@ -101,10 +108,18 @@ class expr(ast_node):
|
||||
while type(p) is expr and not p.isvector:
|
||||
p.isvector = True
|
||||
p = p.parent
|
||||
self.cexpr = self.datasource.parse_tablenames(node, self.materialize_cols)
|
||||
|
||||
self._expr, self.raw_col = self.datasource.parse_tablenames(node, self.materialize_cols, True)
|
||||
self.raw_col = self.raw_col if type(self.raw_col) is ColRef else None
|
||||
if self.__abs and self.raw_col:
|
||||
self._expr = self.raw_col.reference() + index_expr
|
||||
elif type(node) is bool:
|
||||
self.cexpr = '1' if node else '0'
|
||||
self._expr = '1' if node else '0'
|
||||
else:
|
||||
self.cexpr = f'{node}'
|
||||
self._expr = f'{node}'
|
||||
def toCExpr(_expr):
|
||||
return lambda x = None, y = None : eval(start_expr + _expr + end_expr)
|
||||
def consume(self, _):
|
||||
self.cexpr = expr.toCExpr(self._expr)
|
||||
def __str__(self):
|
||||
return self.cexpr
|
||||
+35
-30
@@ -1,56 +1,61 @@
|
||||
from engine.ast import ast_node
|
||||
from engine.ast import TableInfo, ast_node
|
||||
from engine.scan import scan
|
||||
from engine.utils import base62uuid
|
||||
from engine.expr import expr
|
||||
|
||||
import engine.types
|
||||
class groupby(ast_node):
|
||||
name = '_groupby'
|
||||
def init(self, _):
|
||||
self.context.headers.add('"./server/hasher.h"')
|
||||
self.context.headers.add('unordered_map')
|
||||
self.group = 'g' + base62uuid(7)
|
||||
self.group_type = 'record_type' + base62uuid(7)
|
||||
self.datasource = self.parent.datasource
|
||||
self.scanner = None
|
||||
self.datasource.rec = []
|
||||
self.raw_groups = []
|
||||
def produce(self, node):
|
||||
|
||||
if type(node) is not list:
|
||||
node = [node]
|
||||
g_contents = '('
|
||||
g_contents = ''
|
||||
g_contents_list = []
|
||||
first_col = ''
|
||||
for i, g in enumerate(node):
|
||||
v = g['value']
|
||||
e = expr(self, v).cexpr
|
||||
e = expr(self, v)
|
||||
self.raw_groups.append(e.raw_col)
|
||||
e = e._expr
|
||||
# if v is compound expr, create tmp cols
|
||||
if type(v) is not str:
|
||||
tmpcol = 't' + base62uuid(7)
|
||||
self.emit(f'{tmpcol}:{e}')
|
||||
self.emit(f'auto {tmpcol} = {e};')
|
||||
e = tmpcol
|
||||
if i == 0:
|
||||
first_col = e
|
||||
g_contents += e + (';'if i < len(node)-1 else '')
|
||||
|
||||
self.emit(f'{self.group}:'+g_contents+')')
|
||||
g_contents_list.append(e)
|
||||
g_contents_decltype = [f'decltype({c})' for c in g_contents_list]
|
||||
g_contents = expr.toCExpr(','.join(g_contents_list))
|
||||
self.emit(f'typedef record<{expr.toCExpr(",".join(g_contents_decltype))(0)}> {self.group_type};')
|
||||
self.emit(f'unordered_map<{self.group_type}, vector_type<uint32_t>, '
|
||||
f'transTypes<{self.group_type}, hasher>> {self.group};')
|
||||
self.n_grps = len(node)
|
||||
if self.n_grps <= 1:
|
||||
self.emit(f'{self.group}:={self.group}')
|
||||
else:
|
||||
self.emit(f'{self.group}:groupby[({self.group},(,!(#({first_col}))))]')
|
||||
self.scanner = scan(self, None, expr.toCExpr(first_col)()+'.size')
|
||||
self.scanner.add(f'{self.group}[forward_as_tuple({g_contents(self.scanner.it_ver)})].emplace_back({self.scanner.it_ver});')
|
||||
|
||||
|
||||
def consume(self, _):
|
||||
self.referenced = self.datasource.rec
|
||||
self.datasource.rec = None
|
||||
return super().consume(_)
|
||||
self.scanner.finalize()
|
||||
|
||||
def finalize(self, ret, out):
|
||||
self.groupby_function = 'fgrp'+base62uuid(4)
|
||||
grp = self.group
|
||||
if self.n_grps <= 1:
|
||||
cfn = "{[range] start:*range;"+ ret + "}"
|
||||
self.emit(f'{out}:(({cfn}\'{grp})[!{grp}])')
|
||||
self.parent.inv = False
|
||||
else:
|
||||
cfn = "{[ids;grps;ll;dim;x] " + \
|
||||
"start:grps[x][dim];" + \
|
||||
"end:$[x=0;ll;grps[x-1][dim]];" + \
|
||||
"range:(end-start)#((start-ll)#ids);" + \
|
||||
"start:ids[start];" + \
|
||||
ret + '}'
|
||||
self.emit(f'{self.groupby_function}:{cfn}')
|
||||
self.emit(f'{out}:+({self.groupby_function}' + \
|
||||
f'[{grp}[1];{grp}[0];(#{grp}[0])+1;(#({grp}[0][0]))-1]\'!(#({grp}[0])))')
|
||||
def finalize(self, cexprs, out:TableInfo):
|
||||
gscanner = scan(self, self.group)
|
||||
key_var = 'key_'+base62uuid(7)
|
||||
val_var = 'val_'+base62uuid(7)
|
||||
|
||||
gscanner.add(f'auto &{key_var} = {gscanner.it_ver}.first;')
|
||||
gscanner.add(f'auto &{val_var} = {gscanner.it_ver}.second;')
|
||||
gscanner.add(';\n'.join([f'{out.columns[i].reference()}.emplace_back({ce(x=val_var, y=key_var)})' for i, ce in enumerate(cexprs)])+';')
|
||||
|
||||
gscanner.finalize()
|
||||
+14
-22
@@ -5,7 +5,7 @@ from engine.expr import expr
|
||||
from engine.orderby import orderby
|
||||
from engine.scan import filter
|
||||
from engine.utils import base62uuid, enlist, base62alp
|
||||
from engine.ddl import outfile
|
||||
from engine.ddl import create_table, outfile
|
||||
import copy
|
||||
|
||||
class projection(ast_node):
|
||||
@@ -75,7 +75,7 @@ class projection(ast_node):
|
||||
if self.group_node is not None:
|
||||
# There is group by;
|
||||
has_groupby = True
|
||||
cexpr = f'('
|
||||
cexprs = []
|
||||
flatten = False
|
||||
cols = []
|
||||
self.out_table = TableInfo('out_'+base62uuid(4), [], self.context)
|
||||
@@ -89,27 +89,23 @@ class projection(ast_node):
|
||||
if type(proj) is dict:
|
||||
if 'value' in proj:
|
||||
e = proj['value']
|
||||
if type(e) is str:
|
||||
cname = e # TODO: deal w/ alias
|
||||
cexpr += (f"{self.datasource.parse_tablenames(proj['value'])}")
|
||||
elif type(e) is dict:
|
||||
p_expr = expr(self, e)
|
||||
cname = p_expr.cexpr
|
||||
compound = True
|
||||
cexpr += f"{cname}"
|
||||
cname = ''.join([a if a in base62alp else '' for a in cname])
|
||||
cexpr += ';'if i < len(self.projections)-1 else ''
|
||||
sname = expr(self, e)._expr
|
||||
fname = expr.toCExpr(sname)
|
||||
absname = expr(self, e, abs_col=True)._expr
|
||||
compound = True
|
||||
cexprs.append(fname)
|
||||
cname = ''.join([a if a in base62alp else '' for a in fname()])
|
||||
|
||||
compound = compound and has_groupby and self.datasource.rec not in self.group_node.referenced
|
||||
|
||||
cols.append(ColRef(f'{disp_varname}[{i}]', 'generic', self.out_table, 0, None, cname, i, compound=compound))
|
||||
cols.append(ColRef(cname, expr.toCExpr(f'decays<decltype({absname})>')(0), self.out_table, 0, None, cname, i, compound=compound))
|
||||
self.out_table.add_cols(cols, False)
|
||||
|
||||
cexpr += ')'
|
||||
if has_groupby:
|
||||
self.group_node.finalize(cexpr, disp_varname)
|
||||
create_table(self, self.out_table)
|
||||
self.group_node.finalize(cexprs, self.out_table)
|
||||
else:
|
||||
self.emit(f'auto {disp_varname} = {cexpr};')
|
||||
create_table(self, self.out_table, cexpr = cexprs)
|
||||
self.datasource.group_node = None
|
||||
|
||||
has_orderby = 'orderby' in node
|
||||
@@ -122,12 +118,8 @@ class projection(ast_node):
|
||||
self.emit_no_ln(f"{f'{disp_varname}:+' if flatten else ''}(")
|
||||
|
||||
if self.disp or has_orderby:
|
||||
if len(self.projections) > 1:
|
||||
self.emit_no_ln(f"{'+' if self.inv else ''}{disp_varname}")
|
||||
else:
|
||||
self.emit_no_ln(f'print({disp_varname});')
|
||||
if flatten:
|
||||
self.emit_no_ln(f'{disp_varname}')
|
||||
self.emit(f'print(*{self.out_table.cxt_name});')
|
||||
|
||||
if has_orderby:
|
||||
self.emit(f')[{orderby_node.view}]')
|
||||
else:
|
||||
|
||||
+32
-2
@@ -1,11 +1,41 @@
|
||||
from xmlrpc.client import Boolean
|
||||
from engine.ast import ColRef, TableInfo, View, ast_node
|
||||
from engine.ast import ColRef, TableInfo, View, ast_node, Context
|
||||
from engine.utils import base62uuid
|
||||
from engine.expr import expr
|
||||
|
||||
class scan(ast_node):
|
||||
name = 'scan'
|
||||
|
||||
def __init__(self, parent: "ast_node", node, size = None, context: Context = None):
|
||||
self.type = type
|
||||
self.size = size
|
||||
super().__init__(parent, node, context)
|
||||
def init(self, _):
|
||||
self.datasource = self.context.datasource
|
||||
self.start = ''
|
||||
self.body = ''
|
||||
self.end = '}'
|
||||
self.filter = None
|
||||
scan_vars = set(s.it_var for s in self.context.scans)
|
||||
self.it_ver = 'i' + base62uuid(2)
|
||||
while(self.it_ver in scan_vars):
|
||||
self.it_ver = 'i' + base62uuid(6)
|
||||
self.parent.context.scans.append(self)
|
||||
def produce(self, node):
|
||||
if type(node) is ColRef:
|
||||
if self.size is None:
|
||||
self.start += f'for (auto& {self.it_ver} : {node.reference()}) {{\n'
|
||||
else:
|
||||
self.start += f"for (uint32_t {self.it_ver} = 0; {self.it_ver} < {node.reference()}.size; ++{self.it_ver}){{\\n"
|
||||
elif type(node) is str:
|
||||
self.start+= f'for(auto& {self.it_ver} : {node}) {{\n'
|
||||
else:
|
||||
self.start += f"for (uint32_t {self.it_ver} = 0; {self.it_ver} < {self.size}; ++{self.it_ver}){{\n"
|
||||
|
||||
def add(self, stmt):
|
||||
self.body+=stmt + '\n'
|
||||
def finalize(self):
|
||||
self.context.remove_scan(self, self.start + self.body + self.end)
|
||||
|
||||
class filter(ast_node):
|
||||
name = 'filter'
|
||||
def __init__(self, parent: "ast_node", node, materialize = False, context = None):
|
||||
|
||||
Reference in New Issue
Block a user