feat: add sqlite support to starmelon interpreter
This commit is contained in:
parent
e90a0b62a6
commit
3cf23637d5
7 changed files with 566 additions and 24 deletions
306
src/fixture/query.js
Normal file
306
src/fixture/query.js
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
// CORE QUERIES
|
||||
|
||||
function __Debug_print(object) {
|
||||
//Deno.core.print(JSON.stringify(object));
|
||||
//Deno.core.print("\n");
|
||||
}
|
||||
|
||||
function _Query_succeed(value)
|
||||
{
|
||||
return {
|
||||
$: 0,
|
||||
a: value
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var _Query_fetchOptional = F3(function(sql, args, decoder)
|
||||
{
|
||||
return {
|
||||
$: 1,
|
||||
b: sql,
|
||||
c: args,
|
||||
d: { $: 0, a: decoder }
|
||||
};
|
||||
});
|
||||
|
||||
var _Query_fetchOne = F3(function(sql, args, decoder)
|
||||
{
|
||||
return {
|
||||
$: 2,
|
||||
b: sql,
|
||||
c: args,
|
||||
d: { $: 1, a: decoder }
|
||||
};
|
||||
});
|
||||
|
||||
var _Query_fetchAll = F3(function(sql, args, decoder)
|
||||
{
|
||||
return {
|
||||
$: 3,
|
||||
b: sql,
|
||||
c: args,
|
||||
d: { $: 2, a: decoder }
|
||||
};
|
||||
});
|
||||
|
||||
function _Query_mapMany(f, queries)
|
||||
{
|
||||
return {
|
||||
$: 4,
|
||||
f: f,
|
||||
g: queries
|
||||
};
|
||||
}
|
||||
|
||||
var _Query_andThen = F2(function(callback, query)
|
||||
{
|
||||
return {
|
||||
$: 5,
|
||||
e: query,
|
||||
h: callback
|
||||
};
|
||||
});
|
||||
|
||||
var _Query_map1 = F2(function(f, q1)
|
||||
{
|
||||
return _Query_mapMany(f, [q1]);
|
||||
});
|
||||
|
||||
var _Query_map2 = F3(function(f, q1, q2)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2]);
|
||||
});
|
||||
|
||||
var _Query_map3 = F4(function(f, q1, q2, q3)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3]);
|
||||
});
|
||||
|
||||
var _Query_map4 = F5(function(f, q1, q2, q3, q4)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3, q4]);
|
||||
});
|
||||
|
||||
var _Query_map5 = F6(function(f, q1, q2, q3, q4, q5)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3, q4, q5]);
|
||||
});
|
||||
|
||||
var _Query_map6 = F7(function(f, q1, q2, q3, q4, q5, q6)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3, q4, q5, q6]);
|
||||
});
|
||||
|
||||
var _Query_map7 = F8(function(f, q1, q2, q3, q4, q5, q6, q7)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3, q4, q5, q6, q7]);
|
||||
});
|
||||
|
||||
var _Query_map8 = F9(function(f, q1, q2, q3, q4, q5, q6, q7, q8)
|
||||
{
|
||||
return _Query_mapMany(f, [q1, q2, q3, q4, q5, q6, q7, q8]);
|
||||
});
|
||||
|
||||
// RUN
|
||||
|
||||
function _Query_runDecoder(decoder, sql, xs)
|
||||
{
|
||||
switch (decoder.$) {
|
||||
case 0:
|
||||
if (xs.length === 0) {
|
||||
return $elm$core$Result$Ok($elm$core$Maybe$Nothing);
|
||||
}
|
||||
var result = _Json_runOnString.f(decoder.a, xs[0]);
|
||||
|
||||
if (!$elm$core$Result$isOk(result))
|
||||
{
|
||||
return $elm$core$Result$Err(
|
||||
A3(
|
||||
$author$project$Astrid$Query$Decode,
|
||||
sql,
|
||||
0,
|
||||
result.a
|
||||
)
|
||||
);
|
||||
}
|
||||
return $elm$core$Result$Ok($elm$core$Maybe$Just(result.a));
|
||||
|
||||
case 1:
|
||||
if (xs.length === 0) {
|
||||
return $elm$core$Result$Err($author$project$Astrid$Query$NotFound(sql));
|
||||
}
|
||||
var result = _Json_runOnString.f(decoder.a, xs[0]);
|
||||
|
||||
if (!$elm$core$Result$isOk(result))
|
||||
{
|
||||
return $elm$core$Result$Err(
|
||||
A3(
|
||||
$author$project$Astrid$Query$Decode,
|
||||
sql,
|
||||
0,
|
||||
result.a
|
||||
)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
|
||||
case 2:
|
||||
var len = xs.length;
|
||||
var array = new Array(len);
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var string = xs[i];
|
||||
try
|
||||
{
|
||||
var value = JSON.parse(string);
|
||||
__Debug_print("parsed the json");
|
||||
__Debug_print(value);
|
||||
__Debug_print(decoder);
|
||||
var result = _Json_runHelp(decoder.a, value);
|
||||
__Debug_print("result of parsing the json");
|
||||
__Debug_print(result);
|
||||
if (!$elm$core$Result$isOk(result))
|
||||
{
|
||||
return $elm$core$Result$Err(
|
||||
A3(
|
||||
$author$project$Astrid$Query$Decode,
|
||||
sql,
|
||||
i,
|
||||
result.a
|
||||
)
|
||||
);
|
||||
}
|
||||
array[i] = result.a;
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
return $elm$core$Result$Err(
|
||||
A3(
|
||||
$author$project$Astrid$Query$Decode,
|
||||
sql,
|
||||
i,
|
||||
A2(
|
||||
$elm$json$Json$Decode$Failure,
|
||||
'This is not valid JSON! ' + e.message, _Json_wrap(string)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $elm$core$Result$Ok(_Json_toElmArray(array));
|
||||
}
|
||||
}
|
||||
|
||||
var _Query_execute = function(query)
|
||||
{
|
||||
var queries = new Array;
|
||||
var statements = new Array;
|
||||
var decoders = new Array;
|
||||
var values = new Array;
|
||||
var callbacks = new Array;
|
||||
|
||||
queries.push(query);
|
||||
|
||||
while (true) {
|
||||
var q;
|
||||
while(q = queries.pop()) {
|
||||
switch (q.$) {
|
||||
case 0:
|
||||
values.push(q.a);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
var moreThanOneRow = (q.$ === 3)
|
||||
var sql = q.b;
|
||||
var bindParameters = _List_toArray(q.c);
|
||||
var decoder = q.d;
|
||||
statements.push([moreThanOneRow, sql, bindParameters]);
|
||||
decoders.push(decoder);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
callbacks.push({ $:'Map', a: q.f })
|
||||
// We know that the list of queries is limited to length 8,
|
||||
// which is much less then browser's stack overflow limits that
|
||||
// start around 100,000 elements.
|
||||
Array.prototype.push.apply(queries, q.g);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
callbacks.push({ $:'AndThen', a: q.h })
|
||||
queries.push(q.e)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (statements.length > 0) {
|
||||
__Debug_print("statements = ");
|
||||
__Debug_print(statements);
|
||||
var queryResult = Deno.core.opSync(
|
||||
'op_starmelon_batch_queries',
|
||||
statements,
|
||||
);
|
||||
__Debug_print(queryResult);
|
||||
// I am assuming here that the Rust code is serializing the same
|
||||
// structure that the Elm compiler thinks we have.
|
||||
if (!$elm$core$Result$isOk(queryResult)) {
|
||||
return queryResult
|
||||
}
|
||||
var results = queryResult.a;
|
||||
|
||||
var len = results.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var result = _Query_runDecoder(decoders[i], statements[i][1], results[i])
|
||||
if (!$elm$core$Result$isOk(result))
|
||||
{
|
||||
return result
|
||||
}
|
||||
values.push(result.a);
|
||||
}
|
||||
statements.length = 0;
|
||||
decoders.length = 0;
|
||||
}
|
||||
|
||||
__Debug_print("processing callbacks stack");
|
||||
|
||||
reduce:
|
||||
while(callbacks.length > 0) {
|
||||
var last = callbacks[callbacks.length - 1];
|
||||
switch (last.$) {
|
||||
case 'Map':
|
||||
var arity = last.a.a;
|
||||
if (values.length < arity) {
|
||||
// This implies that queries.length > 0 because we must
|
||||
// have a way to generate the missing value(s) to call
|
||||
// this function.
|
||||
break reduce;
|
||||
}
|
||||
callbacks.pop();
|
||||
// Directly call the wrapped Elm function since we know all
|
||||
// the arguments
|
||||
var fun = last.a.f;
|
||||
var args = values.slice(-arity);
|
||||
values.length = values.length - args.length;
|
||||
values.push(Function.prototype.apply(fun, args));
|
||||
break;
|
||||
|
||||
case 'AndThen':
|
||||
callbacks.pop();
|
||||
var fun = last.a.f;
|
||||
// I think that if we have an AndThen then we will always have at least one value
|
||||
queries.push(fun(values.pop()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (queries.length == 0 && callbacks.length == 0) {
|
||||
// values must have one element in it.
|
||||
return $elm$core$Result$Ok(values.pop())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var $author$project$Astrid$Query$execute = _Query_execute;
|
||||
Loading…
Add table
Add a link
Reference in a new issue