306 lines
8.5 KiB
JavaScript
306 lines
8.5 KiB
JavaScript
// 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;
|