rado 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/define/CTE.d.ts +2 -0
- package/dist/define/CTE.js +51 -0
- package/dist/define/Cursor.d.ts +65 -42
- package/dist/define/Cursor.js +170 -88
- package/dist/define/Expr.d.ts +2 -2
- package/dist/define/Expr.js +4 -1
- package/dist/define/Ops.d.ts +1 -6
- package/dist/define/Ops.js +10 -7
- package/dist/define/Query.d.ts +117 -2
- package/dist/define/Query.js +472 -17
- package/dist/define/Selection.d.ts +1 -1
- package/dist/define/Table.d.ts +6 -3
- package/dist/define/Table.js +6 -1
- package/dist/define/VirtualTable.d.ts +1 -1
- package/dist/define/query/Delete.d.ts +0 -2
- package/dist/define/query/Delete.js +0 -3
- package/dist/define/query/Select.d.ts +0 -2
- package/dist/define/query/Select.js +1 -14
- package/dist/deno/driver/better-sqlite3.js +57 -0
- package/dist/deno/driver/bun-sqlite.js +69 -0
- package/dist/deno/driver/sql.js.js +72 -0
- package/dist/deno/driver/sqlite3.js +123 -0
- package/dist/deno/index.js +14 -0
- package/dist/deno/lib/Driver.js +330 -0
- package/dist/deno/lib/Formatter.js +715 -0
- package/dist/deno/lib/SqlError.js +11 -0
- package/dist/deno/lib/Statement.js +108 -0
- package/dist/deno/sqlite/SqliteFormatter.js +70 -0
- package/dist/deno/sqlite/SqliteFunctions.js +150 -0
- package/dist/deno/sqlite/SqliteSchema.js +47 -0
- package/dist/deno/sqlite.js +3 -0
- package/dist/deno/util/Callable.js +15 -0
- package/dist/driver/bun-sqlite.js +1 -2
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -8
- package/dist/lib/Driver.d.ts +1 -2
- package/dist/lib/Formatter.js +17 -3
- package/dist/sqlite/index.d.ts +2 -0
- package/dist/sqlite/index.js +3 -0
- package/dist/src/driver/better-sqlite3.js +49 -0
- package/dist/src/driver/sql.js.js +66 -0
- package/dist/src/driver/sqlite3.js +87 -0
- package/dist/src/index.js +24 -0
- package/dist/{lib → src/lib}/Column.js +1 -6
- package/dist/{lib → src/lib}/Cursor.js +25 -50
- package/dist/src/lib/Driver.js +316 -0
- package/dist/{lib → src/lib}/Expr.js +4 -4
- package/dist/src/lib/Formatter.js +625 -0
- package/dist/{lib → src/lib}/Ops.js +14 -5
- package/dist/src/lib/Sanitizer.js +0 -0
- package/dist/src/lib/Statement.js +103 -0
- package/dist/{lib → src/lib}/Table.js +1 -1
- package/dist/{lib → src/lib}/Target.js +4 -9
- package/dist/src/lib/Update.js +0 -0
- package/dist/src/sqlite/SqliteFormatter.js +67 -0
- package/dist/src/sqlite/SqliteFunctions.js +146 -0
- package/dist/src/sqlite/SqliteSchema.js +47 -0
- package/dist/src/sqlite.js +3 -0
- package/dist/test/DbSuite.js +28 -0
- package/dist/test/TSTestTypes.js +6 -0
- package/dist/test/TestBasic.js +172 -0
- package/dist/test/TestExtend.js +68 -0
- package/dist/test/TestFts5.js +34 -0
- package/dist/test/TestFunctions.js +28 -0
- package/dist/test/TestJoins.js +34 -0
- package/dist/test/TestJson.js +33 -0
- package/dist/test/TestPrepare.js +27 -0
- package/dist/test/TestRawSql.js +31 -0
- package/dist/test/TestSchema.js +69 -0
- package/dist/test/TestSubQueries.js +79 -0
- package/dist/test/TestTransaction.js +54 -0
- package/dist/test/TestUpdate.js +95 -0
- package/dist/test/index.js +14 -0
- package/package.json +1 -1
- package/dist/lib/Column.d.ts +0 -57
- package/dist/lib/Cursor.d.ts +0 -85
- package/dist/lib/Expr.d.ts +0 -154
- package/dist/lib/Fields.d.ts +0 -13
- package/dist/lib/Functions.d.ts +0 -5
- package/dist/lib/Id.d.ts +0 -3
- package/dist/lib/Index.d.ts +0 -17
- package/dist/lib/Ops.d.ts +0 -7
- package/dist/lib/OrderBy.d.ts +0 -9
- package/dist/lib/Param.d.ts +0 -20
- package/dist/lib/Query.d.ts +0 -109
- package/dist/lib/Schema.d.ts +0 -18
- package/dist/lib/Selection.d.ts +0 -20
- package/dist/lib/Table.d.ts +0 -62
- package/dist/lib/Target.d.ts +0 -38
- package/dist/lib/Update.d.ts +0 -4
- /package/dist/{lib/Fields.js → deno/lib/Sanitizer.js} +0 -0
- /package/dist/{lib/Id.js → src/lib/Fields.js} +0 -0
- /package/dist/{lib → src/lib}/Functions.js +0 -0
- /package/dist/{lib/Update.js → src/lib/Id.js} +0 -0
- /package/dist/{lib → src/lib}/Index.js +0 -0
- /package/dist/{lib → src/lib}/OrderBy.js +0 -0
- /package/dist/{lib → src/lib}/Param.js +0 -0
- /package/dist/{lib → src/lib}/Query.js +0 -0
- /package/dist/{lib → src/lib}/Schema.js +0 -0
- /package/dist/{lib → src/lib}/Selection.js +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/lib/Statement.ts
|
|
2
|
+
import { ParamData, ParamType } from "./Param.js";
|
|
3
|
+
var SEPARATE = ", ";
|
|
4
|
+
var WHITESPACE = " ";
|
|
5
|
+
var NEWLINE = "\n";
|
|
6
|
+
var INSERT_PARAM = "?";
|
|
7
|
+
var Statement = class {
|
|
8
|
+
constructor(sanitizer, sql = "", paramData = []) {
|
|
9
|
+
this.sanitizer = sanitizer;
|
|
10
|
+
this.sql = sql;
|
|
11
|
+
this.paramData = paramData;
|
|
12
|
+
}
|
|
13
|
+
currentIndent = "";
|
|
14
|
+
space() {
|
|
15
|
+
if (this.sql === "")
|
|
16
|
+
return this;
|
|
17
|
+
return this.raw(WHITESPACE);
|
|
18
|
+
}
|
|
19
|
+
add(addition) {
|
|
20
|
+
if (!addition)
|
|
21
|
+
return this;
|
|
22
|
+
return this.space().raw(addition);
|
|
23
|
+
}
|
|
24
|
+
addLine(addition) {
|
|
25
|
+
if (!addition)
|
|
26
|
+
return this;
|
|
27
|
+
return this.newline().add(addition);
|
|
28
|
+
}
|
|
29
|
+
indent() {
|
|
30
|
+
this.currentIndent = this.currentIndent + " ";
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
dedent() {
|
|
34
|
+
this.currentIndent = this.currentIndent.slice(0, -2);
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
newline() {
|
|
38
|
+
return this.raw(NEWLINE + this.currentIndent);
|
|
39
|
+
}
|
|
40
|
+
identifier(name) {
|
|
41
|
+
return this.raw(this.sanitizer.escapeIdentifier(name));
|
|
42
|
+
}
|
|
43
|
+
addIdentifier(name) {
|
|
44
|
+
return this.space().identifier(name);
|
|
45
|
+
}
|
|
46
|
+
value(value) {
|
|
47
|
+
this.paramData.push(ParamData.Value(value));
|
|
48
|
+
return this.raw(INSERT_PARAM);
|
|
49
|
+
}
|
|
50
|
+
addValue(value) {
|
|
51
|
+
return this.space().value(value);
|
|
52
|
+
}
|
|
53
|
+
param(name) {
|
|
54
|
+
this.paramData.push(ParamData.Named(name));
|
|
55
|
+
return this.raw(INSERT_PARAM);
|
|
56
|
+
}
|
|
57
|
+
addParam(name) {
|
|
58
|
+
return this.space().param(name);
|
|
59
|
+
}
|
|
60
|
+
raw(query) {
|
|
61
|
+
if (!query)
|
|
62
|
+
return this;
|
|
63
|
+
this.sql += query;
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
openParenthesis() {
|
|
67
|
+
return this.raw("(").indent().newline();
|
|
68
|
+
}
|
|
69
|
+
closeParenthesis() {
|
|
70
|
+
return this.dedent().newline().raw(")");
|
|
71
|
+
}
|
|
72
|
+
*call(parts, separator = SEPARATE) {
|
|
73
|
+
this.openParenthesis();
|
|
74
|
+
yield* this.separate(parts, separator);
|
|
75
|
+
this.closeParenthesis();
|
|
76
|
+
}
|
|
77
|
+
*separate(parts, separator = SEPARATE) {
|
|
78
|
+
for (let i = 0; i < parts.length; i++) {
|
|
79
|
+
if (i > 0)
|
|
80
|
+
this.raw(separator).newline();
|
|
81
|
+
yield parts[i];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
isEmpty() {
|
|
85
|
+
return this.sql === "";
|
|
86
|
+
}
|
|
87
|
+
params(input) {
|
|
88
|
+
return this.paramData.map((param) => {
|
|
89
|
+
if (param.type === ParamType.Named) {
|
|
90
|
+
if (input && param.name in input)
|
|
91
|
+
return this.sanitizer.formatParamValue(input[param.name]);
|
|
92
|
+
throw new TypeError(`Missing parameter ${param.name}`);
|
|
93
|
+
}
|
|
94
|
+
return this.sanitizer.formatParamValue(param.value);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
toString() {
|
|
98
|
+
return this.sql;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
export {
|
|
102
|
+
Statement
|
|
103
|
+
};
|
|
@@ -59,7 +59,7 @@ var Table = class extends Cursor.SelectMultiple {
|
|
|
59
59
|
return new Cursor.Delete(Query.Delete({ table: this.schema() }));
|
|
60
60
|
}
|
|
61
61
|
createTable() {
|
|
62
|
-
return new Cursor.
|
|
62
|
+
return new Cursor.Create(this.schema());
|
|
63
63
|
}
|
|
64
64
|
as(alias) {
|
|
65
65
|
return new Table({ ...this.schema(), alias });
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
// src/lib/Target.ts
|
|
2
2
|
var TargetType = /* @__PURE__ */ ((TargetType2) => {
|
|
3
|
-
TargetType2["
|
|
4
|
-
TargetType2["Query"] = "Query";
|
|
3
|
+
TargetType2["Each"] = "Each";
|
|
5
4
|
TargetType2["Table"] = "Table";
|
|
6
5
|
TargetType2["Join"] = "Join";
|
|
7
6
|
return TargetType2;
|
|
8
7
|
})(TargetType || {});
|
|
9
8
|
var Target;
|
|
10
9
|
((Target2) => {
|
|
11
|
-
function
|
|
12
|
-
return { type: "
|
|
10
|
+
function Each(expr, alias) {
|
|
11
|
+
return { type: "Each" /* Each */, expr, alias };
|
|
13
12
|
}
|
|
14
|
-
Target2.
|
|
15
|
-
function Query(query, alias) {
|
|
16
|
-
return { type: "Query" /* Query */, query, alias };
|
|
17
|
-
}
|
|
18
|
-
Target2.Query = Query;
|
|
13
|
+
Target2.Each = Each;
|
|
19
14
|
function Table(table) {
|
|
20
15
|
return { type: "Table" /* Table */, table };
|
|
21
16
|
}
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/sqlite/SqliteFormatter.ts
|
|
2
|
+
import { ExprType } from "../lib/Expr.js";
|
|
3
|
+
import { Formatter } from "../lib/Formatter.js";
|
|
4
|
+
import { TargetType } from "../lib/Target.js";
|
|
5
|
+
var BACKTICK = "`";
|
|
6
|
+
var ESCAPE_BACKTICK = "``";
|
|
7
|
+
var SINGLE_QUOTE = "'";
|
|
8
|
+
var ESCAPE_SINGLE_QUOTE = "''";
|
|
9
|
+
var MATCH_BACKTICK = /`/g;
|
|
10
|
+
var MATCH_SINGLE_QUOTE = /'/g;
|
|
11
|
+
var SqliteFormatter = class extends Formatter {
|
|
12
|
+
formatParamValue(paramValue) {
|
|
13
|
+
if (paramValue === null || paramValue === void 0)
|
|
14
|
+
return null;
|
|
15
|
+
if (typeof paramValue === "boolean")
|
|
16
|
+
return paramValue ? 1 : 0;
|
|
17
|
+
if (typeof paramValue === "number")
|
|
18
|
+
return paramValue;
|
|
19
|
+
if (typeof paramValue === "string")
|
|
20
|
+
return paramValue;
|
|
21
|
+
return JSON.stringify(paramValue);
|
|
22
|
+
}
|
|
23
|
+
escapeValue(value) {
|
|
24
|
+
if (value === null || value === void 0)
|
|
25
|
+
return "NULL";
|
|
26
|
+
if (typeof value === "boolean")
|
|
27
|
+
return value ? "1" : "0";
|
|
28
|
+
if (typeof value === "number")
|
|
29
|
+
return String(value);
|
|
30
|
+
if (typeof value === "string")
|
|
31
|
+
return this.escapeString(value);
|
|
32
|
+
return "json(" + this.escapeString(JSON.stringify(value)) + ")";
|
|
33
|
+
}
|
|
34
|
+
escapeIdentifier(input) {
|
|
35
|
+
return BACKTICK + input.replace(MATCH_BACKTICK, ESCAPE_BACKTICK) + BACKTICK;
|
|
36
|
+
}
|
|
37
|
+
escapeString(input) {
|
|
38
|
+
return SINGLE_QUOTE + input.replace(MATCH_SINGLE_QUOTE, ESCAPE_SINGLE_QUOTE) + SINGLE_QUOTE;
|
|
39
|
+
}
|
|
40
|
+
formatAccess(ctx, mkSubject, field) {
|
|
41
|
+
const { stmt, formatAsJson } = ctx;
|
|
42
|
+
mkSubject();
|
|
43
|
+
stmt.raw(formatAsJson ? "->" : "->>");
|
|
44
|
+
return this.formatString(ctx, `$.${field}`);
|
|
45
|
+
}
|
|
46
|
+
formatExpr(ctx, expr) {
|
|
47
|
+
const { stmt } = ctx;
|
|
48
|
+
switch (expr.type) {
|
|
49
|
+
case ExprType.Call:
|
|
50
|
+
if (expr.method === "match") {
|
|
51
|
+
const [from, query] = expr.params;
|
|
52
|
+
if (from.type !== ExprType.Row)
|
|
53
|
+
throw new Error("not implemented");
|
|
54
|
+
if (from.target.type !== TargetType.Table)
|
|
55
|
+
throw new Error("not implemented");
|
|
56
|
+
stmt.identifier(from.target.table.alias || from.target.table.name).raw(" MATCH ");
|
|
57
|
+
this.formatExprValue(ctx, query);
|
|
58
|
+
return stmt;
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
return super.formatExpr(ctx, expr);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
export {
|
|
66
|
+
SqliteFormatter
|
|
67
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// src/sqlite/SqliteFunctions.ts
|
|
2
|
+
import { Functions } from "../lib/Functions.js";
|
|
3
|
+
var SqliteFunctions = Functions;
|
|
4
|
+
var {
|
|
5
|
+
count,
|
|
6
|
+
iif,
|
|
7
|
+
exists,
|
|
8
|
+
match,
|
|
9
|
+
cast,
|
|
10
|
+
abs,
|
|
11
|
+
changes,
|
|
12
|
+
char,
|
|
13
|
+
coalesce,
|
|
14
|
+
ifnull,
|
|
15
|
+
instr,
|
|
16
|
+
last_insert_rowid,
|
|
17
|
+
length,
|
|
18
|
+
likelihood,
|
|
19
|
+
likely,
|
|
20
|
+
lower,
|
|
21
|
+
ltrim,
|
|
22
|
+
max,
|
|
23
|
+
min,
|
|
24
|
+
nullif,
|
|
25
|
+
prnumberf,
|
|
26
|
+
quote,
|
|
27
|
+
random,
|
|
28
|
+
replace,
|
|
29
|
+
round,
|
|
30
|
+
rtrim,
|
|
31
|
+
sign,
|
|
32
|
+
soundex,
|
|
33
|
+
sqlite_version,
|
|
34
|
+
substr,
|
|
35
|
+
total_changes,
|
|
36
|
+
trim,
|
|
37
|
+
unicode,
|
|
38
|
+
unlikely,
|
|
39
|
+
upper,
|
|
40
|
+
avg,
|
|
41
|
+
group_concat,
|
|
42
|
+
sum,
|
|
43
|
+
acos,
|
|
44
|
+
acosh,
|
|
45
|
+
asin,
|
|
46
|
+
asinh,
|
|
47
|
+
atan,
|
|
48
|
+
atan2,
|
|
49
|
+
atanh,
|
|
50
|
+
ceil,
|
|
51
|
+
cos,
|
|
52
|
+
cosh,
|
|
53
|
+
degrees,
|
|
54
|
+
exp,
|
|
55
|
+
floor,
|
|
56
|
+
ln,
|
|
57
|
+
log,
|
|
58
|
+
log2,
|
|
59
|
+
mod,
|
|
60
|
+
pi,
|
|
61
|
+
pow,
|
|
62
|
+
radians,
|
|
63
|
+
sin,
|
|
64
|
+
sinh,
|
|
65
|
+
sqrt,
|
|
66
|
+
tan,
|
|
67
|
+
tanh,
|
|
68
|
+
trunc,
|
|
69
|
+
date,
|
|
70
|
+
time,
|
|
71
|
+
datetime,
|
|
72
|
+
julianday,
|
|
73
|
+
strftime
|
|
74
|
+
} = SqliteFunctions;
|
|
75
|
+
export {
|
|
76
|
+
SqliteFunctions,
|
|
77
|
+
abs,
|
|
78
|
+
acos,
|
|
79
|
+
acosh,
|
|
80
|
+
asin,
|
|
81
|
+
asinh,
|
|
82
|
+
atan,
|
|
83
|
+
atan2,
|
|
84
|
+
atanh,
|
|
85
|
+
avg,
|
|
86
|
+
cast,
|
|
87
|
+
ceil,
|
|
88
|
+
changes,
|
|
89
|
+
char,
|
|
90
|
+
coalesce,
|
|
91
|
+
cos,
|
|
92
|
+
cosh,
|
|
93
|
+
count,
|
|
94
|
+
date,
|
|
95
|
+
datetime,
|
|
96
|
+
degrees,
|
|
97
|
+
exists,
|
|
98
|
+
exp,
|
|
99
|
+
floor,
|
|
100
|
+
group_concat,
|
|
101
|
+
ifnull,
|
|
102
|
+
iif,
|
|
103
|
+
instr,
|
|
104
|
+
julianday,
|
|
105
|
+
last_insert_rowid,
|
|
106
|
+
length,
|
|
107
|
+
likelihood,
|
|
108
|
+
likely,
|
|
109
|
+
ln,
|
|
110
|
+
log,
|
|
111
|
+
log2,
|
|
112
|
+
lower,
|
|
113
|
+
ltrim,
|
|
114
|
+
match,
|
|
115
|
+
max,
|
|
116
|
+
min,
|
|
117
|
+
mod,
|
|
118
|
+
nullif,
|
|
119
|
+
pi,
|
|
120
|
+
pow,
|
|
121
|
+
prnumberf,
|
|
122
|
+
quote,
|
|
123
|
+
radians,
|
|
124
|
+
random,
|
|
125
|
+
replace,
|
|
126
|
+
round,
|
|
127
|
+
rtrim,
|
|
128
|
+
sign,
|
|
129
|
+
sin,
|
|
130
|
+
sinh,
|
|
131
|
+
soundex,
|
|
132
|
+
sqlite_version,
|
|
133
|
+
sqrt,
|
|
134
|
+
strftime,
|
|
135
|
+
substr,
|
|
136
|
+
sum,
|
|
137
|
+
tan,
|
|
138
|
+
tanh,
|
|
139
|
+
time,
|
|
140
|
+
total_changes,
|
|
141
|
+
trim,
|
|
142
|
+
trunc,
|
|
143
|
+
unicode,
|
|
144
|
+
unlikely,
|
|
145
|
+
upper
|
|
146
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/sqlite/SqliteSchema.ts
|
|
2
|
+
import { Cursor } from "../lib/Cursor.js";
|
|
3
|
+
import { Statement } from "../lib/Statement.js";
|
|
4
|
+
import { SqliteFormatter } from "./SqliteFormatter.js";
|
|
5
|
+
var SqliteSchema;
|
|
6
|
+
((SqliteSchema2) => {
|
|
7
|
+
const formatter = new SqliteFormatter();
|
|
8
|
+
function tableData(tableName) {
|
|
9
|
+
return Cursor.all`select * from pragma_table_info(${tableName}) order by cid`;
|
|
10
|
+
}
|
|
11
|
+
SqliteSchema2.tableData = tableData;
|
|
12
|
+
function indexData(tableName) {
|
|
13
|
+
return Cursor.all`select * from sqlite_master where type='index' and tbl_name=${tableName}`;
|
|
14
|
+
}
|
|
15
|
+
SqliteSchema2.indexData = indexData;
|
|
16
|
+
function createInstructions(columnData, indexData2) {
|
|
17
|
+
if (columnData.length === 0 && indexData2.length === 0)
|
|
18
|
+
return void 0;
|
|
19
|
+
const columns = columnData.map(columnInstruction);
|
|
20
|
+
const indexes = indexData2.map(indexInstruction).filter((row) => row[1]);
|
|
21
|
+
return {
|
|
22
|
+
columns: Object.fromEntries(columns),
|
|
23
|
+
indexes: Object.fromEntries(indexes)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
SqliteSchema2.createInstructions = createInstructions;
|
|
27
|
+
function columnInstruction(column) {
|
|
28
|
+
const stmt = new Statement(formatter);
|
|
29
|
+
stmt.identifier(column.name).add(column.type);
|
|
30
|
+
if (column.pk === 1)
|
|
31
|
+
stmt.add("PRIMARY KEY");
|
|
32
|
+
if (column.notnull === 1)
|
|
33
|
+
stmt.add("NOT NULL");
|
|
34
|
+
if (column.dflt_value !== null) {
|
|
35
|
+
stmt.add("DEFAULT").space().openParenthesis().raw(column.dflt_value).closeParenthesis();
|
|
36
|
+
}
|
|
37
|
+
return [column.name, stmt.sql];
|
|
38
|
+
}
|
|
39
|
+
SqliteSchema2.columnInstruction = columnInstruction;
|
|
40
|
+
function indexInstruction(index) {
|
|
41
|
+
return [index.name, index.sql];
|
|
42
|
+
}
|
|
43
|
+
SqliteSchema2.indexInstruction = indexInstruction;
|
|
44
|
+
})(SqliteSchema || (SqliteSchema = {}));
|
|
45
|
+
export {
|
|
46
|
+
SqliteSchema
|
|
47
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// test/DbSuite.ts
|
|
2
|
+
async function connect() {
|
|
3
|
+
switch (process.env.TEST_DRIVER) {
|
|
4
|
+
case "better-sqlite3": {
|
|
5
|
+
const { default: BetterSqlite3Database } = await import("better-sqlite3");
|
|
6
|
+
const { connect: createConnection } = await import("../src/driver/better-sqlite3.js");
|
|
7
|
+
return createConnection(new BetterSqlite3Database(":memory:")).toAsync();
|
|
8
|
+
}
|
|
9
|
+
case "sql.js": {
|
|
10
|
+
const { default: init } = await import("sql.js");
|
|
11
|
+
const { Database } = await init();
|
|
12
|
+
const { connect: createConnection } = await import("../src/driver/sql.js.js");
|
|
13
|
+
return createConnection(new Database()).toAsync();
|
|
14
|
+
}
|
|
15
|
+
case "sqlite3": {
|
|
16
|
+
const {
|
|
17
|
+
default: { Database }
|
|
18
|
+
} = await import("sqlite3");
|
|
19
|
+
const { connect: createConnection } = await import("../src/driver/sqlite3.js");
|
|
20
|
+
return createConnection(new Database(":memory:"));
|
|
21
|
+
}
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`Unknown driver ${process.env.TEST_DRIVER}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
connect
|
|
28
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// test/TestBasic.ts
|
|
2
|
+
import { test } from "uvu";
|
|
3
|
+
import * as assert from "uvu/assert";
|
|
4
|
+
import {
|
|
5
|
+
Expr,
|
|
6
|
+
column,
|
|
7
|
+
create,
|
|
8
|
+
insertInto,
|
|
9
|
+
selectFirst,
|
|
10
|
+
table
|
|
11
|
+
} from "../src/index.js";
|
|
12
|
+
import { connect } from "./DbSuite.js";
|
|
13
|
+
test("basic", async () => {
|
|
14
|
+
const query = await connect();
|
|
15
|
+
const Node = table({
|
|
16
|
+
name: "node",
|
|
17
|
+
columns: {
|
|
18
|
+
id: column.integer().primaryKey(),
|
|
19
|
+
index: column.number()
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
await query(create(Node));
|
|
23
|
+
const amount = 10;
|
|
24
|
+
const objects = Array.from({ length: amount }).map((_, index) => ({ index }));
|
|
25
|
+
assert.equal(objects.length, amount);
|
|
26
|
+
await query(Node.insertAll(objects));
|
|
27
|
+
assert.equal((await query(Node)).length, amount);
|
|
28
|
+
const stored = await query(Node);
|
|
29
|
+
const id = stored[amount - 1].id;
|
|
30
|
+
assert.equal(
|
|
31
|
+
(await query(
|
|
32
|
+
Node.sure().where(
|
|
33
|
+
Node.index.greaterOrEqual(amount - 1),
|
|
34
|
+
Node.index.less(amount)
|
|
35
|
+
)
|
|
36
|
+
)).id,
|
|
37
|
+
id
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
test("filters", async () => {
|
|
41
|
+
const query = await connect();
|
|
42
|
+
const Test = table({
|
|
43
|
+
name: "test",
|
|
44
|
+
columns: {
|
|
45
|
+
id: column.integer().primaryKey(),
|
|
46
|
+
prop: column.number()
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
await query(create(Test));
|
|
50
|
+
const a = { prop: 10 };
|
|
51
|
+
const b = { prop: 20 };
|
|
52
|
+
await query(Test.insertAll([a, b]));
|
|
53
|
+
const gt10 = await query.get(Test.where(Test.prop.greater(10)));
|
|
54
|
+
assert.equal(gt10.prop, 20);
|
|
55
|
+
});
|
|
56
|
+
test("select", async () => {
|
|
57
|
+
const query = await connect();
|
|
58
|
+
const Test = table({
|
|
59
|
+
name: "test",
|
|
60
|
+
columns: {
|
|
61
|
+
id: column.integer().primaryKey(),
|
|
62
|
+
propA: column.number(),
|
|
63
|
+
propB: column.number()
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
await query(create(Test));
|
|
67
|
+
const a = { propA: 10, propB: 5 };
|
|
68
|
+
const b = { propA: 20, propB: 5 };
|
|
69
|
+
await query(Test.insertAll([a, b]));
|
|
70
|
+
const res = await query(Test.select({ a: Test.propA, b: Test.propB }));
|
|
71
|
+
assert.equal(res, [
|
|
72
|
+
{ a: 10, b: 5 },
|
|
73
|
+
{ a: 20, b: 5 }
|
|
74
|
+
]);
|
|
75
|
+
const res2 = await query(
|
|
76
|
+
Test.select({
|
|
77
|
+
...Test,
|
|
78
|
+
testProp: Expr.value(123)
|
|
79
|
+
}).sure()
|
|
80
|
+
);
|
|
81
|
+
assert.is(res2.testProp, 123);
|
|
82
|
+
const res3 = await query(Test.sure().select(Expr.value("test")));
|
|
83
|
+
assert.is(res3, "test");
|
|
84
|
+
const res4 = await query(Test.sure().select(Expr.value(true)));
|
|
85
|
+
assert.is(res4, true);
|
|
86
|
+
});
|
|
87
|
+
test("update", async () => {
|
|
88
|
+
const query = await connect();
|
|
89
|
+
const Test = table({
|
|
90
|
+
name: "test",
|
|
91
|
+
columns: {
|
|
92
|
+
id: column.integer().primaryKey(),
|
|
93
|
+
propA: column.number(),
|
|
94
|
+
propB: column.number()
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
Test.id;
|
|
98
|
+
await query(Test.createTable());
|
|
99
|
+
const a = { propA: 10, propB: 5 };
|
|
100
|
+
const b = { propA: 20, propB: 5 };
|
|
101
|
+
await query(Test.insertAll([a, b]));
|
|
102
|
+
await query(Test.set({ propA: 15 }).where(Test.propA.is(10)));
|
|
103
|
+
assert.ok(await query(Test.sure().where(Test.propA.is(15))));
|
|
104
|
+
});
|
|
105
|
+
test("json", async () => {
|
|
106
|
+
const query = await connect();
|
|
107
|
+
const Test = table({
|
|
108
|
+
name: "test",
|
|
109
|
+
columns: {
|
|
110
|
+
id: column.integer().primaryKey(),
|
|
111
|
+
prop: column.number(),
|
|
112
|
+
propB: column.number()
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
await query(create(Test));
|
|
116
|
+
const a = { prop: 10, propB: 5 };
|
|
117
|
+
const b = { prop: 20, propB: 5 };
|
|
118
|
+
await query(insertInto(Test).values(a, b));
|
|
119
|
+
const q = Test.sure().select({
|
|
120
|
+
fieldA: Expr.value(12),
|
|
121
|
+
fieldB: Test.propB
|
|
122
|
+
}).where(Test.prop.is(10));
|
|
123
|
+
const res1 = await query(q);
|
|
124
|
+
assert.is(res1.fieldA, 12);
|
|
125
|
+
assert.is(res1.fieldB, 5);
|
|
126
|
+
});
|
|
127
|
+
test("each", async () => {
|
|
128
|
+
const query = await connect();
|
|
129
|
+
const a = {
|
|
130
|
+
refs: [
|
|
131
|
+
{ id: 1, type: "entry" },
|
|
132
|
+
{ id: 0, type: "nonsense" },
|
|
133
|
+
{ id: 2, type: "entry" }
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
const Test = table({
|
|
137
|
+
name: "test",
|
|
138
|
+
columns: {
|
|
139
|
+
id: column.integer().primaryKey(),
|
|
140
|
+
refs: column.array()
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
const Entry = table({
|
|
144
|
+
name: "Entry",
|
|
145
|
+
columns: {
|
|
146
|
+
id: column.integer().primaryKey(),
|
|
147
|
+
title: column.string()
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
await query(create(Test, Entry));
|
|
151
|
+
await query(insertInto(Test).values(a));
|
|
152
|
+
const res = await query(selectFirst(Test).select({ refs: Test.refs }));
|
|
153
|
+
assert.equal(res, a);
|
|
154
|
+
const b = { title: "Entry B" };
|
|
155
|
+
const c = { title: "Entry C" };
|
|
156
|
+
await query(create(Entry));
|
|
157
|
+
await query(Entry.insertAll([b, c]));
|
|
158
|
+
const Link = Entry.as("Link");
|
|
159
|
+
const tests = Test.select({
|
|
160
|
+
links: Test.refs.filter((ref) => {
|
|
161
|
+
return ref.type.is("entry");
|
|
162
|
+
}).map((ref) => {
|
|
163
|
+
return Link.fetch(ref.id).select({ id: Link.id, title: Link.title });
|
|
164
|
+
})
|
|
165
|
+
}).sure();
|
|
166
|
+
const res2 = await query(tests);
|
|
167
|
+
assert.equal(res2.links, [
|
|
168
|
+
{ id: 1, title: "Entry B" },
|
|
169
|
+
{ id: 2, title: "Entry C" }
|
|
170
|
+
]);
|
|
171
|
+
});
|
|
172
|
+
test.run();
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// test/TestExtend.ts
|
|
2
|
+
import { test } from "uvu";
|
|
3
|
+
import * as assert from "uvu/assert";
|
|
4
|
+
import { column, create, table } from "../src/index.js";
|
|
5
|
+
import { connect } from "./DbSuite.js";
|
|
6
|
+
var UserTable = table({
|
|
7
|
+
name: "user",
|
|
8
|
+
columns: {
|
|
9
|
+
id: column.integer().primaryKey(),
|
|
10
|
+
firstName: column.string(),
|
|
11
|
+
lastName: column.string()
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
var User = table.extend(UserTable, {
|
|
15
|
+
name() {
|
|
16
|
+
return this.firstName.concat(" ").concat(this.lastName);
|
|
17
|
+
},
|
|
18
|
+
roles() {
|
|
19
|
+
return Role.innerJoin(UserRoles, Role.id.is(UserRoles.roleId)).innerJoin(
|
|
20
|
+
this,
|
|
21
|
+
UserRoles.userId.is(this.id)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
var Role = table({
|
|
26
|
+
name: "role",
|
|
27
|
+
columns: {
|
|
28
|
+
id: column.integer().primaryKey(),
|
|
29
|
+
name: column.string()
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
var UserRoles = table({
|
|
33
|
+
name: "user_roles",
|
|
34
|
+
columns: {
|
|
35
|
+
userId: column.integer().references(UserTable.id),
|
|
36
|
+
roleId: column.integer().references(Role.id)
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
test("Extend", async () => {
|
|
40
|
+
const query = await connect();
|
|
41
|
+
await query(create(Role, User, UserRoles));
|
|
42
|
+
const user1 = await query(
|
|
43
|
+
User.insertOne({
|
|
44
|
+
firstName: "a",
|
|
45
|
+
lastName: "b"
|
|
46
|
+
})
|
|
47
|
+
);
|
|
48
|
+
const role1 = await query(Role.insertOne({ name: "role1" }));
|
|
49
|
+
const role2 = await query(Role.insertOne({ name: "role2" }));
|
|
50
|
+
await query(
|
|
51
|
+
UserRoles.insertAll([
|
|
52
|
+
{ userId: user1.id, roleId: role1.id },
|
|
53
|
+
{ userId: user1.id, roleId: role2.id }
|
|
54
|
+
])
|
|
55
|
+
);
|
|
56
|
+
const { Aliased } = User.alias();
|
|
57
|
+
const user = await query(
|
|
58
|
+
Aliased.first().select({
|
|
59
|
+
name: Aliased.name(),
|
|
60
|
+
roles: Aliased.roles()
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
assert.equal(user, {
|
|
64
|
+
name: "a b",
|
|
65
|
+
roles: [role1, role2]
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
test.run();
|