bug fix on select into

dev
Bill 2 years ago
parent 48beab441d
commit 34a9fe105c

@ -232,9 +232,9 @@ def ext (fx):
# operator call behavior
def binary_op_behavior(op:OperatorBase, c_code, x, y):
def binary_op_behavior(op:OperatorBase, c_code, *xs):
name = op.cname if c_code else op.sqlname
return f'({x} {name} {y})'
return f'({f" {name} ".join(xs)})'
def unary_op_behavior(op:OperatorBase, c_code, x):
name = op.cname if c_code else op.sqlname
@ -248,10 +248,16 @@ def count_behavior(op:OperatorBase, c_code, x, distinct = False):
if not c_code:
return f'{op.sqlname}({"distinct " if distinct else ""}{x})'
elif distinct:
return '({x}).distinct_size()'
return f'({x}).distinct_size()'
else:
return '{count()}'
def distinct_behavior(op:OperatorBase, c_code, x):
if not c_code:
return f'{op.sqlname}({x})'
else:
return f'({x}).distinct()'
def windowed_fn_behavor(op: OperatorBase, c_code, *x):
if not c_code:
return f'{op.sqlname}({", ".join([f"{xx}" for xx in x])})'
@ -277,6 +283,7 @@ oplte = OperatorBase('lte', 2, logical, cname = '<=', sqlname = '<=', call = bin
opneq = OperatorBase('neq', 2, logical, cname = '!=', sqlname = '!=', call = binary_op_behavior)
opeq = OperatorBase('eq', 2, logical, cname = '==', sqlname = '=', call = binary_op_behavior)
opnot = OperatorBase('not', 1, logical, cname = '!', sqlname = 'NOT', call = unary_op_behavior)
opdistinct = OperatorBase('distinct', 1, as_is, cname = '.distinct()', sqlname = 'distinct', call = distinct_behavior)
# functional
fnmax = OperatorBase('max', 1, as_is, cname = 'max', sqlname = 'MAX', call = fn_behavior)
fnmin = OperatorBase('min', 1, as_is, cname = 'min', sqlname = 'MIN', call = fn_behavior)
@ -315,7 +322,7 @@ builtin_binary_arith = _op_make_dict(opadd, opdiv, opmul, opsub, opmod)
builtin_binary_logical = _op_make_dict(opand, opor, opxor, opgt, oplt, opge, oplte, opneq, opeq)
builtin_unary_logical = _op_make_dict(opnot)
builtin_unary_arith = _op_make_dict(opneg)
builtin_unary_special = _op_make_dict(spnull)
builtin_unary_special = _op_make_dict(spnull, opdistinct)
builtin_cstdlib = _op_make_dict(fnsqrt, fnlog, fnsin, fncos, fntan, fnpow)
builtin_func = _op_make_dict(fnmax, fnmin, fnsum, fnavg, fnmaxs, fnmins, fndeltas, fnlast, fnsums, fnavgs, fncnt)
user_module_func = {}

@ -1,3 +1,5 @@
from collections import OrderedDict
from collections.abc import MutableMapping, Mapping
import uuid
lower_alp = 'abcdefghijklmnopqrstuvwxyz'
@ -7,6 +9,50 @@ base62alp = nums + lower_alp + upper_alp
reserved_monet = ['month']
class CaseInsensitiveDict(MutableMapping):
def __init__(self, data=None, **kwargs):
self._store = OrderedDict()
if data is None:
data = {}
self.update(data, **kwargs)
def __setitem__(self, key, value):
# Use the lowercased key for lookups, but store the actual
# key alongside the value.
self._store[key.lower()] = (key, value)
def __getitem__(self, key):
return self._store[key.lower()][1]
def __delitem__(self, key):
del self._store[key.lower()]
def __iter__(self):
return (casedkey for casedkey, mappedvalue in self._store.values())
def __len__(self):
return len(self._store)
def lower_items(self):
"""Like iteritems(), but with all lowercase keys."""
return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items())
def __eq__(self, other):
if isinstance(other, Mapping):
other = CaseInsensitiveDict(other)
else:
return NotImplemented
# Compare insensitively
return dict(self.lower_items()) == dict(other.lower_items())
# Copy is required
def copy(self):
return CaseInsensitiveDict(self._store.values())
def __repr__(self):
return str(dict(self.items()))
def base62uuid(crop=8):
_id = uuid.uuid4().int
ret = ''
@ -60,7 +106,7 @@ def defval(val, default):
return default if val is None else val
# escape must be readonly
from typing import Set
from typing import Mapping, Set
def remove_last(pattern : str, string : str, escape : Set[str] = set()) -> str:
idx = string.rfind(pattern)
if idx == -1:

@ -61,9 +61,16 @@ class projection(ast_node):
pass
def produce(self, node):
self.add('SELECT')
self.has_postproc = False
if 'select' in node:
p = node['select']
self.distinct = False
elif 'select_distinct' in node:
p = node['select_distinct']
self.distinct = True
self.projections = p if type(p) is list else [p]
self.add('SELECT')
if self.parent is None:
self.context.sql_begin()
self.postproc_fname = 'dll_' + base62uuid(6)
@ -75,8 +82,8 @@ class projection(ast_node):
if 'from' in node:
from_clause = node['from']['table_source']
self.datasource = join(self, from_clause)
if 'assumptions' in from_clause:
self.assumptions = enlist(from_clause['assumptions'])
if 'assumptions' in node['from']:
self.assumptions = enlist(node['from']['assumptions'])
if self.datasource is not None:
self.datasource_changed = True
@ -109,15 +116,21 @@ class projection(ast_node):
proj_map : Dict[int, List[Union[Types, int, str, expr]]]= dict()
self.var_table = dict()
# self.sp_refs = set()
for i, proj in enumerate(self.projections):
i = 0
for proj in self.projections:
compound = False
self.datasource.rec = set()
name = ''
this_type = AnyT
if type(proj) is dict:
if type(proj) is dict or proj == '*':
if 'value' in proj:
e = proj['value']
elif proj == '*':
e = '*'
else:
print('unknown projection', proj)
proj_expr = expr(self, e)
sql_expr = expr(self, e, c_code=False)
this_type = proj_expr.type
name = proj_expr.sql
compound = True # compound column
@ -127,43 +140,58 @@ class projection(ast_node):
alias = proj['name']
if not proj_expr.is_special:
if proj_expr.node == '*':
name = [c.get_full_name() for c in self.datasource.rec]
else:
y = lambda x:x
name = eval('f\'' + name + '\'')
count = lambda : 'count(*)'
name = enlist(sql_expr.eval(False, y, count=count))
for n in name:
offset = len(col_exprs)
if name not in self.var_table:
self.var_table[name] = offset
if n not in self.var_table:
self.var_table[n] = offset
if proj_expr.is_ColExpr and type(proj_expr.raw_col) is ColRef:
for n in (proj_expr.raw_col.table.alias):
self.var_table[f'{n}.'+name] = offset
for _alias in (proj_expr.raw_col.table.alias):
self.var_table[f'{_alias}.'+n] = offset
proj_map[i] = [this_type, offset, proj_expr]
col_expr = name + ' AS ' + alias if alias else name
col_expr = n + ' AS ' + alias if alias else n
if alias:
self.var_table[alias] = offset
col_exprs.append((col_expr, proj_expr.type))
i += 1
else:
self.context.headers.add('"./server/aggregations.h"')
self.has_postproc = True
if self.datasource.rec is not None:
self.col_ext = self.col_ext.union(self.datasource.rec)
proj_map[i] = [this_type, proj_expr.sql, proj_expr]
disp_name = get_legal_name(alias if alias else name)
i += 1
name = enlist(name)
disp_name = [get_legal_name(alias if alias else n) for n in name]
elif type(proj) is str:
col = self.datasource.get_col(proj)
this_type = col.type
disp_name = proj
print('Unknown behavior:', proj, 'is str')
# name = col.name
self.datasource.rec = None
# TODO: Type deduction in Python
cols.append(ColRef(this_type, self.out_table, None, disp_name, i, compound=compound))
for n in disp_name:
cols.append(ColRef(this_type, self.out_table, None, n, len(cols), compound=compound))
self.out_table.add_cols(cols, new = False)
if 'groupby' in node:
self.group_node = groupby(self, node['groupby'])
if self.group_node.use_sp_gb:
self.has_postproc = True
else:
self.group_node = None
if not self.has_postproc and self.distinct:
self.add('DISTINCT')
self.col_ext = [c for c in self.col_ext if c.name not in self.var_table] # remove duplicates in self.var_table
col_ext_names = [c.name for c in self.col_ext]
self.add(', '.join([c[0] for c in col_exprs] + col_ext_names))
@ -249,7 +277,7 @@ class projection(ast_node):
self.group_node and
(self.group_node.use_sp_gb and
val[2].cols_mentioned.intersection(
self.datasource.all_cols.difference(self.group_node.refs))
self.datasource.all_cols().difference(self.group_node.refs))
) and val[2].is_compound # compound val not in key
# or
# (not self.group_node and val[2].is_compound)
@ -282,6 +310,7 @@ class projection(ast_node):
# for funcs evaluate f_i(x, ...)
self.context.emitc(f'{self.out_table.contextname_cpp}->get_col<{key}>() = {val[1]};')
# print out col_is
if 'into' not in node:
self.context.emitc(f'print(*{self.out_table.contextname_cpp});')
if self.outfile:
@ -289,18 +318,29 @@ class projection(ast_node):
if 'into' in node:
self.context.emitc(select_into(self, node['into']).ccode)
if not self.distinct:
self.finalize()
def finalize(self):
self.context.emitc(f'puts("done.");')
if self.parent is None:
self.context.sql_end()
self.context.postproc_end(self.postproc_fname)
class select_distinct(projection):
first_order = 'select_distinct'
def consume(self, node):
super().consume(node)
if self.has_postproc:
self.context.emitc(
f'{self.out_table.table_name}->distinct();'
)
self.finalize()
class select_into(ast_node):
def init(self, node):
if type(self.parent) is projection:
if isinstance(self.parent, projection):
if self.context.has_dll:
# has postproc put back to monetdb
self.produce = self.produce_cpp
@ -308,8 +348,8 @@ class select_into(ast_node):
self.produce = self.produce_sql
else:
raise ValueError('parent must be projection')
def produce_cpp(self, node):
assert(type(self.parent) is projection)
if not hasattr(self.parent, 'out_table'):
raise Exception('No out_table found.')
else:
@ -508,7 +548,7 @@ class groupby(ast_node):
return False
def produce(self, node):
if type(self.parent) is not projection:
if not isinstance(self.parent, projection):
raise ValueError('groupby can only be used in projection')
node = enlist(node)
@ -554,7 +594,7 @@ class join(ast_node):
self.tables : List[TableInfo] = []
self.tables_dir = dict()
self.rec = None
self.top_level = self.parent and type(self.parent) is projection
self.top_level = self.parent and isinstance(self.parent, projection)
self.have_sep = False
# self.tmp_name = 'join_' + base62uuid(4)
# self.datasource = TableInfo(self.tmp_name, [], self.context)
@ -636,9 +676,16 @@ class join(ast_node):
datasource.rec = None
return ret
@property
# @property
def all_cols(self):
return set([c for t in self.tables for c in t.columns])
ret = set()
for table in self.tables:
rec = table.rec
table.rec = self.rec
ret.update(table.all_cols())
table.rec = rec
return ret
def consume(self, node):
self.sql = ''
for j in self.joins:
@ -787,7 +834,7 @@ class outfile(ast_node):
self.sql = sql if sql else ''
def init(self, _):
assert(type(self.parent) is projection)
assert(isinstance(self.parent, projection))
if not self.parent.use_postproc:
if self.context.dialect == 'MonetDB':
self.produce = self.produce_monetdb

@ -1,4 +1,4 @@
from typing import Optional
from typing import Optional, Set
from reconstruct.ast import ast_node
from reconstruct.storage import ColRef, Context
from engine.types import *
@ -199,11 +199,8 @@ class expr(ast_node):
self.udf_decltypecall = ex_vname.sql
else:
print(f'Undefined expr: {key}{val}')
if 'distinct' in val and key != count:
if self.c_code:
self.sql = 'distinct ' + self.sql
elif self.is_compound:
self.sql = '(' + self.sql + ').distinct()'
if type(node) is str:
if self.is_udfexpr:
curr_udf : udf = self.root.udf
@ -235,6 +232,11 @@ class expr(ast_node):
# get the column from the datasource in SQL context
else:
if self.datasource is not None:
if (node == '*' and
not (type(self.parent) is expr
and 'count' in self.parent.node)):
self.datasource.all_cols()
else:
self.raw_col = self.datasource.parse_col_names(node)
self.raw_col = self.raw_col if type(self.raw_col) is ColRef else None
if self.raw_col is not None:
@ -259,10 +261,16 @@ class expr(ast_node):
self.is_compound = True
self.opname = self.raw_col
else:
self.sql = '\'' + node + '\''
self.sql = '\'' + node + '\'' if node != '*' else '*'
self.type = StrT
self.opname = self.sql
if self.c_code and self.datasource is not None:
if (type(self.parent) is expr and
'distinct' in self.parent.node and
not self.is_special):
# this node is executed by monetdb
# gb condition, not special
self.sql = f'distinct({self.sql})'
self.sql = f'{{y(\"{self.sql}\")}}'
elif type(node) is bool:
self.type = BoolT

@ -1,5 +1,5 @@
from engine.types import *
from engine.utils import base62uuid, enlist
from engine.utils import CaseInsensitiveDict, base62uuid, enlist
from typing import List, Dict, Set
class ColRef:
@ -20,6 +20,18 @@ class ColRef:
# e.g. order by, group by, filter by expressions
self.__arr__ = (_ty, cobj, table, name, id)
def get_full_name(self):
table_name = self.table.table_name
it_alias = iter(self.table.alias)
alias = next(it_alias, table_name)
try:
while alias == table_name:
alias = next(it_alias)
except StopIteration:
alias = table_name
return f'{alias}.{self.name}'
def __getitem__(self, key):
if type(key) is str:
return getattr(self, key)
@ -35,7 +47,7 @@ class TableInfo:
self.table_name : str = table_name
self.contextname_cpp : str = ''
self.alias : Set[str] = set([table_name])
self.columns_byname : Dict[str, ColRef] = dict() # column_name, type
self.columns_byname : Dict[str, ColRef] = CaseInsensitiveDict() # column_name, type
self.columns : List[ColRef] = []
self.cxt = cxt
# keep track of temp vars
@ -86,6 +98,10 @@ class TableInfo:
else:
return datasource.parse_col_names(parsedColExpr[1])
def all_cols(self):
if type(self.rec) is set:
self.rec.update(self.columns)
return set(self.columns)
class Context:
def new(self):

@ -1,4 +1,4 @@
example:
g++-9 -shared -fPIC example.cpp aquery_mem.cpp -fno-semantic-interposition -Ofast -march=native -flto --std=c++1z -o ../test.so
$(CXX) -shared -fPIC example.cpp aquery_mem.cpp -fno-semantic-interposition -Ofast -march=native -flto --std=c++1z -o ../test.so
all: example

@ -75,7 +75,7 @@ extern void register_memory(void* ptr, deallocator_t deallocator);
__AQEXPORT__(void) init_session(Context* cxt);
#define __AQ_NO_SESSION__ __AQEXPORT__(void) init_session(Context*) {}
void* memcpy(void*, void*, unsigned long long);
void* memcpy(void*, const void*, unsigned long long);
struct ColRef_storage {
void* container;
unsigned int capacity, size;

@ -117,9 +117,9 @@ decayed_t<VT, types::GetLongType<T>> sums(const VT<T>& arr) {
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<T>> avgs(const VT<T>& arr) {
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgs(const VT<T>& arr) {
const uint32_t& len = arr.size;
typedef types::GetFPType<T> FPType;
typedef types::GetFPType<types::GetLongType<T>> FPType;
decayed_t<VT, FPType> ret(len);
uint32_t i = 0;
types::GetLongType<T> s;

@ -26,6 +26,21 @@ namespace types {
struct Coercion;
}
#endif
template <template <class...> class VT, class T>
std::ostream& operator<<(std::ostream& os, const VT<T>& v)
{
v.out();
return os;
}
#ifdef __AQ__HAS__INT128__
std::ostream& operator<<(std::ostream& os, __int128 & v);
std::ostream& operator<<(std::ostream& os, __uint128_t & v);
#endif
std::ostream& operator<<(std::ostream& os, types::date_t & v);
std::ostream& operator<<(std::ostream& os, types::time_t & v);
std::ostream& operator<<(std::ostream& os, types::timestamp_t & v);
template<typename _Ty>
class ColView;
template<typename _Ty>
@ -200,19 +215,7 @@ public:
}
inline ColRef<_Ty> subvec(uint32_t start = 0) { return subvec_deep(start, size); }
};
template <template <class...> class VT, class T>
std::ostream& operator<<(std::ostream& os, const VT<T>& v)
{
v.out();
return os;
}
std::ostream& operator<<(std::ostream& os, types::date_t & v);
std::ostream& operator<<(std::ostream& os, types::time_t & v);
std::ostream& operator<<(std::ostream& os, types::timestamp_t & v);
#ifdef __AQ__HAS__INT128__
std::ostream& operator<<(std::ostream& os, __int128 & v);
std::ostream& operator<<(std::ostream& os, __uint128_t & v);
#endif
template <class Type>
struct decayed_impl<ColView, Type> { typedef ColRef<Type> type; };
@ -433,7 +436,10 @@ struct TableInfo {
template <size_t ...Is>
void inline
reserve(std::index_sequence<Is...>, uint32_t size) {
const auto& assign_sz = [&size](auto& col){ col.size = size;};
const auto& assign_sz = [&size](auto& col){
col.size = size;
col.grow();
};
(assign_sz(get_col<Is>()), ...);
}
template <size_t ...Is>
@ -481,6 +487,53 @@ struct TableView {
template <size_t j = 0>
typename std::enable_if < j < sizeof...(Types) - 1, void>::type print_impl(const uint32_t& i, const char* __restrict sep = " ") const;
template <size_t ...Is>
decltype(auto) inline
get_record(std::index_sequence<Is...>, uint32_t i) {
return std::forward_as_tuple(info.template get_col<Is>()[idxs[i]] ...);
}
TableInfo<Types ...>* get_tableinfo(const char* name = nullptr, const char** names = nullptr) {
if (name == nullptr)
name = info.name;
const char* info_names[sizeof...(Types)];
if (name == nullptr) {
for(uint32_t i = 0; i < sizeof...(Types); ++i)
info_names[i] = info.colrefs[i].name;
names = info_names;
}
return new TableInfo<Types ...>(name, names);
}
TableInfo<Types ...>* materialize(const char* name = nullptr, const char** names = nullptr) {
std::make_index_sequence<sizeof...(Types)> seq;
auto table = get_tableinfo(name, names);
table->reserve(seq, idxs->size);
for (uint32_t i = 0; i < idxs->size; ++i) {
table->set_record(get_record(i));
}
return table;
}
TableInfo<Types ...>* distinct(const char* name = nullptr, const char** names = nullptr) {
std::unordered_set<tuple_type> d_records;
std::make_index_sequence<sizeof...(Types)> seq;
for (uint32_t j = 0; j < idxs->size; ++j) {
d_records.insert(get_record(seq, j));
}
TableInfo<Types ...>* ret = get_tableinfo(name, names);
ret->reserve(seq, d_records.size());
uint32_t i = 0;
for (const auto& dr : d_records) {
ret->set_record(seq, dr, i++);
}
return ret;
}
~TableView() {
delete idxs;
}

@ -9,7 +9,7 @@
#include "monetdbe.h"
inline constexpr monetdbe_types AQType_2_monetdbe[] = {
monetdbe_int32_t, monetdbe_float, monetdbe_str, monetdbe_double, monetdbe_int64_t,
monetdbe_int32_t, monetdbe_float, monetdbe_str, monetdbe_double, monetdbe_double, monetdbe_int64_t,
#ifdef HAVE_HGE
monetdbe_int128_t,
#else
@ -22,7 +22,8 @@ inline constexpr monetdbe_types AQType_2_monetdbe[] = {
#else
monetdbe_int64_t,
#endif
monetdbe_int16_t, monetdbe_int8_t, monetdbe_bool, monetdbe_int64_t, monetdbe_int64_t, monetdbe_int64_t
monetdbe_int16_t, monetdbe_int8_t, monetdbe_bool, monetdbe_int64_t,
monetdbe_timestamp, monetdbe_int64_t, monetdbe_int64_t
};
template<class ...Ts>
@ -34,23 +35,33 @@ void TableInfo<Ts ...>::monetdb_append_table(void* srv, const char* alt_name) {
monetdbe_column** monetdbe_cols = new monetdbe_column * [sizeof...(Ts)];
uint32_t i = 0;
const auto get_col = [&monetdbe_cols, &i](auto v) {
puts("getcols...");
const auto get_col = [&monetdbe_cols, &i, *this](auto v) {
printf("%d %d\n", i, (ColRef<void>*)v - colrefs);
monetdbe_cols[i++] = (monetdbe_column*)v->monetdb_get_col();
};
(get_col((ColRef<Ts>*)(colrefs + i)), ...);
puts("getcols done");
for(int i = 0; i < sizeof...(Ts); ++i)
{
printf("no:%d name: %s count:%d data: %p \n",
i, monetdbe_cols[i]->name, monetdbe_cols[i]->count, monetdbe_cols[i]->data);
}
std::string create_table_str = "CREATE TABLE ";
create_table_str += alt_name;
create_table_str += " (";
i = 0;
const auto get_name_type = [&i, *this]() {
return std::string(colrefs[i++].name) + ' ';
const auto get_name_type = [&i, *this, &create_table_str](auto v) {
create_table_str+= std::string(colrefs[i++].name) + ' ' +
std::string(types::SQL_Type[types::Types<std::remove_pointer_t<decltype(v)>>::getType()]) + ", ";
};
create_table_str += ((get_name_type() + types::SQL_Type[types::Types<Ts>::getType()] + ", ") + ... + std::string(""));
(get_name_type((Ts*)(0)), ...);
auto last_comma = create_table_str.find_last_of(',');
if (last_comma != static_cast<decltype(last_comma)>(-1)) {
create_table_str[last_comma] = ')';
Server* server = (Server*)srv;
puts("create table...");
puts(create_table_str.c_str());
server->exec(create_table_str.c_str());
if (!server->last_error) {
auto err = monetdbe_append(*((monetdbe_database*)server->server), "sys", alt_name, monetdbe_cols, sizeof...(Ts));

@ -28,7 +28,7 @@ namespace types {
};
static constexpr const char* printf_str[] = { "%d", "%f", "%s", "%lf", "%Lf", "%ld", "%d", "%hi", "%s", "%s", "%c",
"%u", "%lu", "%s", "%hu", "%hhu", "%s", "%s", "Vector<%s>", "%s", "NULL", "ERROR" };
static constexpr const char* SQL_Type[] = { "INT", "REAL", "TEXT", "DOUBLE", "DOUBLE", "BIGINT", "HUGEINT", "SMALLINT", "DATE", "TIME", "TINYINT",
static constexpr const char* SQL_Type[] = { "INT", "REAL", "VARCHAR(15)", "DOUBLE", "DOUBLE", "BIGINT", "HUGEINT", "SMALLINT", "DATE", "TIME", "TINYINT",
"INT", "BIGINT", "HUGEINT", "SMALLINT", "TINYINT", "BIGINT", "BOOL", "BIGINT", "TIMESTAMP", "NULL", "ERROR"};

@ -1,27 +1,27 @@
-- please run datagen.get_stock_data() to generate data/stock.csv first
-- create table ticks(ID varchar(10), timestamp int, tradeDate date, price int);
create table ticks(ID varchar(10), timestamp int, tradeDate date, price int);
-- LOAD DATA INFILE "data/stock.csv"
-- INTO TABLE ticks
-- FIELDS TERMINATED BY ","
LOAD DATA INFILE "data/stock.csv"
INTO TABLE ticks
FIELDS TERMINATED BY ","
-- SELECT max(price-mins(price))
-- FROM ticks ASSUMING ASC timestamp
-- WHERE ID="S"
-- AND tradeDate='2003-01-10'
SELECT max(price-mins(price))
FROM ticks ASSUMING ASC timestamp
WHERE ID="S"
AND tradeDate='2003-01-10'
-- create table base(ID varchar(10), name varchar(10));
create table base(ID varchar(10), name varchar(10));
-- LOAD DATA INFILE "data/base.csv"
-- INTO TABLE base
-- FIELDS TERMINATED BY ","
LOAD DATA INFILE "data/base.csv"
INTO TABLE base
FIELDS TERMINATED BY ","
-- SELECT last(price)
-- FROM ticks t, base b
-- ASSUMING ASC name, ASC timestamp
-- WHERE t.ID=b.ID
-- AND name="x"
SELECT last(price)
FROM ticks t, base b
ASSUMING ASC name, ASC timestamp
WHERE t.ID=b.ID
AND name="x"
create table TradedStocks(ID varchar(15), SeqNo int, TradeDate date, TimeStamp time, Type varchar(5));
create table HistoricQuotes(ID varchar(15), TradeDate date, HighPrice real, LowPrice real, ClosePrice real, OpenPrice real, volume bigint);
@ -33,9 +33,15 @@ LOAD DATA INFILE "data/hist-price-file.csv"
INTO TABLE HistoricQuotes
FIELDS TERMINATED BY "|"
SELECT ts.ID, avgs(10, hq.ClosePrice)
FROM TradedStocks AS ts NATURAL JOIN
HistoricQuotes AS hq
ASSUMING ASC hq.TradeDate
GROUP BY ts.ID
select distinct ID, TradeDate
into td
from TradedStocks
-- -- Monetdb wont recognize right table when
-- -- doing a natural join
SELECT ID, avgs(10, ClosePrice)
FROM td NATURAL JOIN
HistoricQuotes
ASSUMING ASC TradeDate
GROUP BY ID
ORDER BY ID
Loading…
Cancel
Save