@sqg/sqg 0.9.0 → 0.10.0
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/dist/sqg.mjs +88 -50
- package/dist/templates/java-jdbc.hbs +38 -2
- package/dist/templates/turso.hbs +14 -18
- package/dist/templates/typescript-duckdb.hbs +26 -3
- package/package.json +1 -1
package/dist/sqg.mjs
CHANGED
|
@@ -680,7 +680,7 @@ var EnumType = class {
|
|
|
680
680
|
var SQLQuery = class {
|
|
681
681
|
columns;
|
|
682
682
|
allColumns;
|
|
683
|
-
/** Database-reported parameter types (variable name → SQL type
|
|
683
|
+
/** Database-reported parameter types (variable name → SQL type), set by database adapters */
|
|
684
684
|
parameterTypes;
|
|
685
685
|
constructor(filename, id, rawQuery, queryAnonymous, queryNamed, queryPositional, type, isOne, isPluck, variables, config) {
|
|
686
686
|
this.filename = filename;
|
|
@@ -966,6 +966,25 @@ async function initializeDatabase(queries, execQueries) {
|
|
|
966
966
|
|
|
967
967
|
//#endregion
|
|
968
968
|
//#region src/db/duckdb.ts
|
|
969
|
+
function convertType(type) {
|
|
970
|
+
if (type instanceof DuckDBListType) return new ListType(convertType(type.valueType));
|
|
971
|
+
if (type instanceof DuckDBStructType) return new StructType(type.entryTypes.map((t, index) => ({
|
|
972
|
+
name: type.entryNames[index],
|
|
973
|
+
type: convertType(t),
|
|
974
|
+
nullable: true
|
|
975
|
+
})));
|
|
976
|
+
if (type instanceof DuckDBMapType) return new MapType({
|
|
977
|
+
name: "key",
|
|
978
|
+
type: convertType(type.keyType),
|
|
979
|
+
nullable: true
|
|
980
|
+
}, {
|
|
981
|
+
name: "value",
|
|
982
|
+
type: convertType(type.valueType),
|
|
983
|
+
nullable: true
|
|
984
|
+
});
|
|
985
|
+
if (type instanceof DuckDBEnumType) return new EnumType(type.values);
|
|
986
|
+
return type.toString();
|
|
987
|
+
}
|
|
969
988
|
const duckdb = new class {
|
|
970
989
|
db;
|
|
971
990
|
connection;
|
|
@@ -1005,6 +1024,15 @@ const duckdb = new class {
|
|
|
1005
1024
|
return ` ${part.value} `;
|
|
1006
1025
|
}).join("");
|
|
1007
1026
|
const stmt = await connection.prepare(sql);
|
|
1027
|
+
if (stmt.parameterCount > 0) {
|
|
1028
|
+
const paramTypes = /* @__PURE__ */ new Map();
|
|
1029
|
+
for (let i = 0; i < stmt.parameterCount; i++) {
|
|
1030
|
+
const paramType = stmt.parameterType(i + 1);
|
|
1031
|
+
paramTypes.set(statement.parameters[i].name, convertType(paramType));
|
|
1032
|
+
}
|
|
1033
|
+
query.parameterTypes = paramTypes;
|
|
1034
|
+
consola.debug("Parameter types:", Object.fromEntries(paramTypes));
|
|
1035
|
+
}
|
|
1008
1036
|
for (let i = 0; i < stmt.parameterCount; i++) stmt.bindValue(i + 1, statement.parameters[i].value);
|
|
1009
1037
|
if (query.isQuery) {
|
|
1010
1038
|
const result = await stmt.stream();
|
|
@@ -1012,25 +1040,6 @@ const duckdb = new class {
|
|
|
1012
1040
|
const columnTypes = result.columnTypes();
|
|
1013
1041
|
consola.debug("Columns:", columnNames);
|
|
1014
1042
|
consola.debug("Types:", columnTypes.map((t) => `${t.toString()} / ${t.constructor.name}`));
|
|
1015
|
-
function convertType(type) {
|
|
1016
|
-
if (type instanceof DuckDBListType) return new ListType(convertType(type.valueType));
|
|
1017
|
-
if (type instanceof DuckDBStructType) return new StructType(type.entryTypes.map((t, index) => ({
|
|
1018
|
-
name: type.entryNames[index],
|
|
1019
|
-
type: convertType(t),
|
|
1020
|
-
nullable: true
|
|
1021
|
-
})));
|
|
1022
|
-
if (type instanceof DuckDBMapType) return new MapType({
|
|
1023
|
-
name: "key",
|
|
1024
|
-
type: convertType(type.keyType),
|
|
1025
|
-
nullable: true
|
|
1026
|
-
}, {
|
|
1027
|
-
name: "value",
|
|
1028
|
-
type: convertType(type.valueType),
|
|
1029
|
-
nullable: true
|
|
1030
|
-
});
|
|
1031
|
-
if (type instanceof DuckDBEnumType) return new EnumType(type.values);
|
|
1032
|
-
return type.toString();
|
|
1033
|
-
}
|
|
1034
1043
|
query.columns = columnNames.map((name, index) => ({
|
|
1035
1044
|
name,
|
|
1036
1045
|
type: convertType(columnTypes[index]),
|
|
@@ -1053,33 +1062,17 @@ const duckdb = new class {
|
|
|
1053
1062
|
for (const table of tables) {
|
|
1054
1063
|
consola.info(`Introspecting table schema: ${table.tableName}`);
|
|
1055
1064
|
try {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
nullable: true
|
|
1068
|
-
}, {
|
|
1069
|
-
name: "value",
|
|
1070
|
-
type: convertType(type.valueType),
|
|
1071
|
-
nullable: true
|
|
1072
|
-
});
|
|
1073
|
-
if (type instanceof DuckDBEnumType) return new EnumType(type.values);
|
|
1074
|
-
return type.toString();
|
|
1075
|
-
}
|
|
1076
|
-
table.columns = rows.map((row) => {
|
|
1077
|
-
return {
|
|
1078
|
-
name: row[0],
|
|
1079
|
-
type: row[1],
|
|
1080
|
-
nullable: row[2] !== "NO"
|
|
1081
|
-
};
|
|
1082
|
-
});
|
|
1065
|
+
const descRows = (await connection.runAndReadAll(`DESCRIBE ${table.tableName}`)).getRows();
|
|
1066
|
+
const nullabilityMap = /* @__PURE__ */ new Map();
|
|
1067
|
+
for (const row of descRows) nullabilityMap.set(row[0], row[2] !== "NO");
|
|
1068
|
+
const stream = await (await connection.prepare(`SELECT * FROM ${table.tableName} LIMIT 0`)).stream();
|
|
1069
|
+
const columnNames = stream.columnNames();
|
|
1070
|
+
const columnTypes = stream.columnTypes();
|
|
1071
|
+
table.columns = columnNames.map((name, index) => ({
|
|
1072
|
+
name,
|
|
1073
|
+
type: convertType(columnTypes[index]),
|
|
1074
|
+
nullable: nullabilityMap.get(name) ?? true
|
|
1075
|
+
}));
|
|
1083
1076
|
consola.debug(`Table ${table.tableName} columns:`, table.columns);
|
|
1084
1077
|
consola.success(`Introspected table: ${table.tableName} (${table.columns.length} columns)`);
|
|
1085
1078
|
} catch (error) {
|
|
@@ -1983,6 +1976,24 @@ var JavaDuckDBArrowGenerator = class extends BaseGenerator {
|
|
|
1983
1976
|
|
|
1984
1977
|
//#endregion
|
|
1985
1978
|
//#region src/generators/typescript-generator.ts
|
|
1979
|
+
/** Resolve a ColumnType to its DuckDB type constant name (e.g. "VARCHAR", "INTEGER") for use in generated code. */
|
|
1980
|
+
function resolveElementType(baseType) {
|
|
1981
|
+
if (baseType instanceof ListType) return `new DuckDBListType(${resolveElementType(baseType.baseType)})`;
|
|
1982
|
+
return {
|
|
1983
|
+
VARCHAR: "VARCHAR",
|
|
1984
|
+
TEXT: "VARCHAR",
|
|
1985
|
+
INTEGER: "INTEGER",
|
|
1986
|
+
INT: "INTEGER",
|
|
1987
|
+
BIGINT: "BIGINT",
|
|
1988
|
+
DOUBLE: "DOUBLE",
|
|
1989
|
+
FLOAT: "FLOAT",
|
|
1990
|
+
BOOLEAN: "BOOLEAN",
|
|
1991
|
+
DATE: "DATE",
|
|
1992
|
+
TIMESTAMP: "TIMESTAMP",
|
|
1993
|
+
SMALLINT: "SMALLINT",
|
|
1994
|
+
TINYINT: "TINYINT"
|
|
1995
|
+
}[baseType.toString().toUpperCase()] || "VARCHAR";
|
|
1996
|
+
}
|
|
1986
1997
|
var TsGenerator = class extends BaseGenerator {
|
|
1987
1998
|
constructor(template) {
|
|
1988
1999
|
super(template, new TypeScriptTypeMapper());
|
|
@@ -2002,6 +2013,7 @@ var TsGenerator = class extends BaseGenerator {
|
|
|
2002
2013
|
async beforeGenerate(_projectDir, _gen, _queries, _tables) {
|
|
2003
2014
|
Handlebars.registerHelper("quote", (value) => this.quote(value));
|
|
2004
2015
|
Handlebars.registerHelper("appendMethod", (column) => {
|
|
2016
|
+
if (column.type instanceof ListType) return "List";
|
|
2005
2017
|
const typeStr = column.type?.toString().toUpperCase() || "";
|
|
2006
2018
|
if (typeStr === "INTEGER" || typeStr === "INT" || typeStr === "INT4" || typeStr === "SIGNED") return "Integer";
|
|
2007
2019
|
if (typeStr === "SMALLINT" || typeStr === "INT2" || typeStr === "SHORT") return "SmallInt";
|
|
@@ -2023,7 +2035,15 @@ var TsGenerator = class extends BaseGenerator {
|
|
|
2023
2035
|
if (typeStr === "INTERVAL") return "Interval";
|
|
2024
2036
|
return "Varchar";
|
|
2025
2037
|
});
|
|
2038
|
+
Handlebars.registerHelper("appendListTypeArg", (column) => {
|
|
2039
|
+
if (!(column.type instanceof ListType)) return "";
|
|
2040
|
+
return `, new DuckDBListType(${resolveElementType(column.type.baseType)})`;
|
|
2041
|
+
});
|
|
2026
2042
|
Handlebars.registerHelper("tsTypeForAppender", (column) => {
|
|
2043
|
+
if (column.type instanceof ListType) {
|
|
2044
|
+
const baseType$1 = "readonly DuckDBValue[]";
|
|
2045
|
+
return column.nullable ? `${baseType$1} | null` : baseType$1;
|
|
2046
|
+
}
|
|
2027
2047
|
const typeStr = column.type?.toString().toUpperCase() || "";
|
|
2028
2048
|
let baseType;
|
|
2029
2049
|
if (typeStr === "INTEGER" || typeStr === "INT" || typeStr === "INT4" || typeStr === "SMALLINT" || typeStr === "INT2" || typeStr === "TINYINT" || typeStr === "INT1" || typeStr === "UINTEGER" || typeStr === "UINT4" || typeStr === "USMALLINT" || typeStr === "UINT2" || typeStr === "UTINYINT" || typeStr === "UINT1" || typeStr === "DOUBLE" || typeStr === "FLOAT8" || typeStr === "FLOAT" || typeStr === "FLOAT4" || typeStr === "REAL") baseType = "number";
|
|
@@ -2164,6 +2184,21 @@ var TsDuckDBGenerator = class extends TsGenerator {
|
|
|
2164
2184
|
}
|
|
2165
2185
|
async beforeGenerate(projectDir, gen, queries, tables) {
|
|
2166
2186
|
await super.beforeGenerate(projectDir, gen, queries, tables);
|
|
2187
|
+
Handlebars.registerHelper("hasListParams", (queryHelper) => {
|
|
2188
|
+
const paramTypes = queryHelper.query.parameterTypes;
|
|
2189
|
+
if (!paramTypes) return false;
|
|
2190
|
+
for (const [, colType] of paramTypes) if (colType instanceof ListType) return true;
|
|
2191
|
+
return false;
|
|
2192
|
+
});
|
|
2193
|
+
Handlebars.registerHelper("bindStatements", (queryHelper) => {
|
|
2194
|
+
const paramNames = queryHelper.parameterNames;
|
|
2195
|
+
const paramTypes = queryHelper.query.parameterTypes;
|
|
2196
|
+
return paramNames.map((name, i) => {
|
|
2197
|
+
const colType = paramTypes?.get(name);
|
|
2198
|
+
if (colType instanceof ListType) return `stmt.bindList(${i + 1}, ${name}.items, new DuckDBListType(${resolveElementType(colType.baseType)}));`;
|
|
2199
|
+
return `stmt.bindValue(${i + 1}, ${name});`;
|
|
2200
|
+
}).join("\n ");
|
|
2201
|
+
});
|
|
2167
2202
|
Handlebars.registerHelper("tsType", (column) => {
|
|
2168
2203
|
const inlineType = (col) => {
|
|
2169
2204
|
const t = col.type;
|
|
@@ -2533,7 +2568,10 @@ async function writeGeneratedFile(projectDir, gen, generator, file, queries, tab
|
|
|
2533
2568
|
await generator.beforeGenerate(projectDir, gen, queries, tables);
|
|
2534
2569
|
const templatePath = join(dirname(new URL(import.meta.url).pathname), gen.template ?? generator.template);
|
|
2535
2570
|
const name = gen.name ?? basename(file, extname(file));
|
|
2536
|
-
const sourceFile = generateSourceFile(name, queries, tables, templatePath, generator, engine, gen.projectName ?? name,
|
|
2571
|
+
const sourceFile = generateSourceFile(name, queries, tables, templatePath, generator, engine, gen.projectName ?? name, {
|
|
2572
|
+
migrations: true,
|
|
2573
|
+
...gen.config
|
|
2574
|
+
});
|
|
2537
2575
|
if (writeToStdout) {
|
|
2538
2576
|
process.stdout.write(sourceFile);
|
|
2539
2577
|
if (!sourceFile.endsWith("\n")) process.stdout.write("\n");
|
|
@@ -2687,7 +2725,7 @@ async function processProject(projectPath) {
|
|
|
2687
2725
|
//#region src/mcp-server.ts
|
|
2688
2726
|
const server = new Server({
|
|
2689
2727
|
name: "sqg-mcp",
|
|
2690
|
-
version: process.env.npm_package_version ?? "0.
|
|
2728
|
+
version: process.env.npm_package_version ?? "0.10.0"
|
|
2691
2729
|
}, { capabilities: {
|
|
2692
2730
|
tools: {},
|
|
2693
2731
|
resources: {}
|
|
@@ -3016,7 +3054,7 @@ async function startMcpServer() {
|
|
|
3016
3054
|
|
|
3017
3055
|
//#endregion
|
|
3018
3056
|
//#region src/sqg.ts
|
|
3019
|
-
const version = process.env.npm_package_version ?? "0.
|
|
3057
|
+
const version = process.env.npm_package_version ?? "0.10.0";
|
|
3020
3058
|
const description = process.env.npm_package_description ?? "SQG - SQL Query Generator - Type-safe code generation from SQL (https://sqg.dev)";
|
|
3021
3059
|
consola.level = LogLevels.info;
|
|
3022
3060
|
const program = new Command().name("sqg").description(`${description}
|
|
@@ -17,11 +17,17 @@ import java.time.OffsetDateTime;
|
|
|
17
17
|
import java.time.OffsetTime;
|
|
18
18
|
import java.util.ArrayList;
|
|
19
19
|
import java.util.Arrays;
|
|
20
|
+
import java.util.Iterator;
|
|
20
21
|
import java.util.List;
|
|
21
22
|
import java.util.HashMap;
|
|
22
23
|
import java.util.Collections;
|
|
24
|
+
import java.util.NoSuchElementException;
|
|
25
|
+
import java.util.Spliterator;
|
|
26
|
+
import java.util.Spliterators;
|
|
23
27
|
import java.util.UUID;
|
|
24
28
|
import java.util.function.Function;
|
|
29
|
+
import java.util.stream.Stream;
|
|
30
|
+
import java.util.stream.StreamSupport;
|
|
25
31
|
{{#if tables.length}}
|
|
26
32
|
import org.duckdb.DuckDBAppender;
|
|
27
33
|
import org.duckdb.DuckDBConnection;
|
|
@@ -203,6 +209,36 @@ public class {{className}} {
|
|
|
203
209
|
{{> execute}}
|
|
204
210
|
}
|
|
205
211
|
}
|
|
212
|
+
{{#if isQuery}}{{#unless isOne}}
|
|
213
|
+
public Stream<{{rowType}}> {{functionName}}Stream({{#each variables}}{{{type}}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) throws SQLException {
|
|
214
|
+
var stmt = connection.prepareStatement({{{partsToString sqlQueryParts}}});
|
|
215
|
+
{{#each parameterNames}}stmt.setObject({{plusOne @index}}, {{this}});
|
|
216
|
+
{{/each}}
|
|
217
|
+
var rs = stmt.executeQuery();
|
|
218
|
+
var iter = new Iterator<{{rowType}}>() {
|
|
219
|
+
private Boolean hasNext = null;
|
|
220
|
+
public boolean hasNext() {
|
|
221
|
+
if (hasNext == null) {
|
|
222
|
+
try { hasNext = rs.next(); }
|
|
223
|
+
catch (SQLException e) { throw new RuntimeException(e); }
|
|
224
|
+
}
|
|
225
|
+
return hasNext;
|
|
226
|
+
}
|
|
227
|
+
public {{rowType}} next() {
|
|
228
|
+
if (!hasNext()) throw new NoSuchElementException();
|
|
229
|
+
hasNext = null;
|
|
230
|
+
try { return {{> readRow}}; }
|
|
231
|
+
catch (SQLException e) { throw new RuntimeException(e); }
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
return StreamSupport.stream(
|
|
235
|
+
Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED), false
|
|
236
|
+
).onClose(() -> {
|
|
237
|
+
try { rs.close(); stmt.close(); }
|
|
238
|
+
catch (SQLException e) { throw new RuntimeException(e); }
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
{{/unless}}{{/if}}
|
|
206
242
|
{{/unless}}
|
|
207
243
|
{{/each}}
|
|
208
244
|
|
|
@@ -220,7 +256,7 @@ public class {{className}} {
|
|
|
220
256
|
|
|
221
257
|
{{#each tables}}
|
|
222
258
|
/** Row type for {{tableName}} appender */
|
|
223
|
-
public record {{rowTypeName}}({{#each columns}}{{mapType this}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) {}
|
|
259
|
+
public record {{rowTypeName}}({{#each columns}}{{{mapType this}}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) {}
|
|
224
260
|
|
|
225
261
|
/** Appender for bulk inserts into {{tableName}} */
|
|
226
262
|
public static class {{className}} implements AutoCloseable {
|
|
@@ -246,7 +282,7 @@ public static class {{className}} implements AutoCloseable {
|
|
|
246
282
|
}
|
|
247
283
|
|
|
248
284
|
/** Append a single row with individual values */
|
|
249
|
-
public {{className}} append({{#each columns}}{{mapType this}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) throws SQLException {
|
|
285
|
+
public {{className}} append({{#each columns}}{{{mapType this}}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) throws SQLException {
|
|
250
286
|
appender.beginRow();
|
|
251
287
|
{{#each columns}}
|
|
252
288
|
appender.append({{name}});
|
package/dist/templates/turso.hbs
CHANGED
|
@@ -33,36 +33,32 @@ export class {{className}} {
|
|
|
33
33
|
|
|
34
34
|
{{#if config.migrations}}
|
|
35
35
|
static async applyMigrations(db: Database, projectName = '{{projectName}}'): Promise<void> {
|
|
36
|
-
const createStmt =
|
|
36
|
+
const createStmt = db.prepare(`CREATE TABLE IF NOT EXISTS _sqg_migrations (
|
|
37
37
|
project TEXT NOT NULL,
|
|
38
38
|
migration_id TEXT NOT NULL,
|
|
39
39
|
applied_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
40
40
|
PRIMARY KEY (project, migration_id)
|
|
41
41
|
)`);
|
|
42
42
|
await createStmt.run();
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
];
|
|
43
|
+
const selectStmt = db.prepare('SELECT migration_id FROM _sqg_migrations WHERE project = ?');
|
|
44
|
+
const rows = await selectStmt.all(projectName) as { migration_id: string }[];
|
|
45
|
+
const applied = new Set(rows.map(r => r.migration_id));
|
|
46
|
+
const migrations: [string, string][] = [
|
|
47
|
+
{{#each migrations}}
|
|
48
|
+
['{{{id}}}', {{{quote sqlQuery}}}],
|
|
49
|
+
{{/each}}
|
|
50
|
+
];
|
|
51
|
+
const applyFn = db.transaction(async () => {
|
|
53
52
|
for (const [id, sql] of migrations) {
|
|
54
53
|
if (!applied.has(id)) {
|
|
55
|
-
const execStmt =
|
|
54
|
+
const execStmt = db.prepare(sql);
|
|
56
55
|
await execStmt.run();
|
|
57
|
-
const insertStmt =
|
|
56
|
+
const insertStmt = db.prepare('INSERT INTO _sqg_migrations (project, migration_id) VALUES (?, ?)');
|
|
58
57
|
await insertStmt.run(projectName, id);
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await tx.rollback();
|
|
64
|
-
throw e;
|
|
65
|
-
}
|
|
60
|
+
});
|
|
61
|
+
await applyFn();
|
|
66
62
|
}
|
|
67
63
|
{{/if}}
|
|
68
64
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// {{generatedComment}}
|
|
2
|
-
import type
|
|
2
|
+
import { DuckDBListType, listValue, VARCHAR, INTEGER, BIGINT, DOUBLE, FLOAT, BOOLEAN, SMALLINT, TINYINT, type DuckDBConnection, type DuckDBMaterializedResult, type DuckDBAppender, type DuckDBDateValue, type DuckDBTimeValue, type DuckDBTimestampValue, type DuckDBBlobValue, type DuckDBValue } from "@duckdb/node-api";
|
|
3
3
|
|
|
4
4
|
export class {{className}} {
|
|
5
5
|
|
|
@@ -60,6 +60,28 @@ export class {{className}} {
|
|
|
60
60
|
{{#unless skipGenerateFunction}}
|
|
61
61
|
async {{functionName}}({{#each variables}}{{name}}: {{type}}{{#unless @last}}, {{/unless}}{{/each}}): Promise<{{> returnType }}> {
|
|
62
62
|
const sql = {{{quote sqlQuery}}};
|
|
63
|
+
{{#if (hasListParams this)}}
|
|
64
|
+
const stmt = await this.conn.prepare(sql);
|
|
65
|
+
{{{bindStatements this}}}
|
|
66
|
+
{{#if isQuery}}
|
|
67
|
+
const reader = await stmt.runAndReadAll();
|
|
68
|
+
{{#if isPluck}}
|
|
69
|
+
{{#if isOne}}
|
|
70
|
+
return reader.getRows()[0]?.[0] as {{> rowType}} | undefined;
|
|
71
|
+
{{else}}
|
|
72
|
+
return reader.getRows().map((row) => row[0] as {{> rowType}});
|
|
73
|
+
{{/if}}
|
|
74
|
+
{{else}}
|
|
75
|
+
{{#if isOne}}
|
|
76
|
+
return reader.getRowObjects()[0] as {{> rowType}} | undefined;
|
|
77
|
+
{{else}}
|
|
78
|
+
return reader.getRowObjects() as {{> rowType}}[];
|
|
79
|
+
{{/if}}
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{else}}
|
|
82
|
+
return await stmt.run();
|
|
83
|
+
{{/if}}
|
|
84
|
+
{{else}}
|
|
63
85
|
{{#if isQuery}}
|
|
64
86
|
const reader = await this.conn.runAndReadAll(sql,[{{> params}}]);
|
|
65
87
|
{{#if isPluck}}
|
|
@@ -78,6 +100,7 @@ export class {{className}} {
|
|
|
78
100
|
{{else}}
|
|
79
101
|
return await this.conn.run(sql,[{{> params}}]);
|
|
80
102
|
{{/if}}
|
|
103
|
+
{{/if}}
|
|
81
104
|
}
|
|
82
105
|
{{/unless}}
|
|
83
106
|
|
|
@@ -113,10 +136,10 @@ export class {{className}} {
|
|
|
113
136
|
if (row.{{name}} === null || row.{{name}} === undefined) {
|
|
114
137
|
this.appender.appendNull();
|
|
115
138
|
} else {
|
|
116
|
-
this.appender.append{{appendMethod this}}(row.{{name}});
|
|
139
|
+
this.appender.append{{appendMethod this}}(row.{{name}}{{{appendListTypeArg this}}});
|
|
117
140
|
}
|
|
118
141
|
{{else}}
|
|
119
|
-
this.appender.append{{appendMethod this}}(row.{{name}});
|
|
142
|
+
this.appender.append{{appendMethod this}}(row.{{name}}{{{appendListTypeArg this}}});
|
|
120
143
|
{{/if}}
|
|
121
144
|
{{/each}}
|
|
122
145
|
this.appender.endRow();
|