sasat 0.19.8 → 0.19.11
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/lib/db/connectors_v2/intefaces.d.ts +22 -0
- package/lib/db/connectors_v2/intefaces.js +1 -0
- package/lib/db/connectors_v2/mysql_v2/client.d.ts +14 -0
- package/lib/db/connectors_v2/mysql_v2/client.js +39 -0
- package/lib/db/connectors_v2/mysql_v2/transaction.d.ts +11 -0
- package/lib/db/connectors_v2/mysql_v2/transaction.js +24 -0
- package/lib/db/sql/createTable/createTableParser.js +2 -3
- package/lib/generatorv2/codegen/gql/generateTypeDefs.js +1 -1
- package/lib/generatorv2/codegen/ts/generateUserDefinedCondition.d.ts +1 -1
- package/lib/generatorv2/codegen/ts/generateUserDefinedCondition.js +17 -12
- package/lib/generatorv2/codegen/tscodegen_v2.d.ts +1 -1
- package/lib/generatorv2/codegen_v2.js +6 -4
- package/lib/generatorv2/nodes/entityNode.d.ts +3 -3
- package/lib/generatorv2/nodes/subscriptionNode.d.ts +2 -2
- package/lib/generatorv2/parser/makeMutationNodes.js +2 -3
- package/lib/generatorv2/scripts/columnToGqlType.d.ts +2 -2
- package/lib/generatorv2/scripts/columnToGqlType.js +4 -5
- package/lib/generatorv2/scripts/gqlTypes.d.ts +2 -7
- package/lib/generatorv2/scripts/gqlTypes.js +2 -7
- package/lib/migration/serializable/column.d.ts +3 -3
- package/lib/runtime/dsl/query/sql/hydrate.d.ts +0 -4
- package/lib/runtime/dsl/query/sql/hydrate.js +40 -64
- package/lib/runtime/dsl/query/sql/hydrate2.d.ts +12 -0
- package/lib/runtime/dsl/query/sql/hydrate2.js +73 -0
- package/lib/runtime/dsl/replaceAliases.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare type QueryResponse = Array<{
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
}>;
|
|
4
|
+
export interface CommandResponse {
|
|
5
|
+
insertId: number;
|
|
6
|
+
affectedRows: number;
|
|
7
|
+
changedRows: number;
|
|
8
|
+
}
|
|
9
|
+
export declare type SQLValueType = string | number | boolean | null;
|
|
10
|
+
export interface SQLExecutor {
|
|
11
|
+
query(sql: string, values: SQLValueType[]): Promise<QueryResponse>;
|
|
12
|
+
command(sql: string, values: SQLValueType[]): Promise<CommandResponse>;
|
|
13
|
+
}
|
|
14
|
+
export interface SQLTransaction extends SQLExecutor {
|
|
15
|
+
commit(): Promise<void>;
|
|
16
|
+
rollback(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export interface DBClient extends SQLExecutor {
|
|
19
|
+
released(): boolean;
|
|
20
|
+
transaction(): Promise<SQLTransaction>;
|
|
21
|
+
release(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as mysql from 'mysql2/promise';
|
|
2
|
+
import { CommandResponse, DBClient, QueryResponse, SQLTransaction, SQLValueType } from '../intefaces.js';
|
|
3
|
+
export declare class MysqlClient implements DBClient {
|
|
4
|
+
readonly connectionOption?: Partial<mysql.ConnectionOptions> | undefined;
|
|
5
|
+
private readonly pool;
|
|
6
|
+
private _released;
|
|
7
|
+
constructor(connectionOption?: Partial<mysql.ConnectionOptions> | undefined, poolOption?: Partial<mysql.PoolOptions>);
|
|
8
|
+
transaction(): Promise<SQLTransaction>;
|
|
9
|
+
release(): Promise<void>;
|
|
10
|
+
protected execute(sql: string, values: SQLValueType[]): Promise<QueryResponse | CommandResponse>;
|
|
11
|
+
command(sql: string, values: SQLValueType[]): Promise<CommandResponse>;
|
|
12
|
+
query(sql: string, values: SQLValueType[]): Promise<QueryResponse>;
|
|
13
|
+
released(): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as mysql from 'mysql2/promise';
|
|
2
|
+
import { config } from '../../../config/config.js';
|
|
3
|
+
import { MySqlTransaction } from './transaction.js';
|
|
4
|
+
const defaultConfig = { ...config().db, dateStrings: true };
|
|
5
|
+
export class MysqlClient {
|
|
6
|
+
constructor(connectionOption, poolOption) {
|
|
7
|
+
this.connectionOption = connectionOption;
|
|
8
|
+
this._released = false;
|
|
9
|
+
this.pool = mysql.createPool({
|
|
10
|
+
...defaultConfig,
|
|
11
|
+
...connectionOption,
|
|
12
|
+
...poolOption,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async transaction() {
|
|
16
|
+
const connection = await mysql.createConnection({
|
|
17
|
+
...defaultConfig,
|
|
18
|
+
...this.connectionOption,
|
|
19
|
+
});
|
|
20
|
+
await connection.beginTransaction();
|
|
21
|
+
return new MySqlTransaction(connection);
|
|
22
|
+
}
|
|
23
|
+
async release() {
|
|
24
|
+
await this.pool.end();
|
|
25
|
+
this._released = true;
|
|
26
|
+
}
|
|
27
|
+
execute(sql, values) {
|
|
28
|
+
return this.pool.execute(sql, values);
|
|
29
|
+
}
|
|
30
|
+
command(sql, values) {
|
|
31
|
+
return this.execute(sql, values);
|
|
32
|
+
}
|
|
33
|
+
query(sql, values) {
|
|
34
|
+
return this.execute(sql, values);
|
|
35
|
+
}
|
|
36
|
+
released() {
|
|
37
|
+
return this._released;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as mysql from 'mysql2/promise';
|
|
2
|
+
import { CommandResponse, QueryResponse, SQLTransaction, SQLValueType } from '../intefaces.js';
|
|
3
|
+
export declare class MySqlTransaction implements SQLTransaction {
|
|
4
|
+
private connection;
|
|
5
|
+
constructor(connection: mysql.Connection);
|
|
6
|
+
query(sql: string, values: SQLValueType[]): Promise<QueryResponse>;
|
|
7
|
+
command(sql: string, values: SQLValueType[]): Promise<CommandResponse>;
|
|
8
|
+
commit(): Promise<void>;
|
|
9
|
+
rollback(): Promise<void>;
|
|
10
|
+
protected execute(sql: string, values: SQLValueType[]): Promise<QueryResponse | CommandResponse>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class MySqlTransaction {
|
|
2
|
+
constructor(connection) {
|
|
3
|
+
this.connection = connection;
|
|
4
|
+
}
|
|
5
|
+
query(sql, values) {
|
|
6
|
+
return this.execute(sql, values);
|
|
7
|
+
}
|
|
8
|
+
command(sql, values) {
|
|
9
|
+
return this.execute(sql, values);
|
|
10
|
+
}
|
|
11
|
+
async commit() {
|
|
12
|
+
await this.connection.commit();
|
|
13
|
+
await this.connection.end();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
async rollback() {
|
|
17
|
+
await this.connection.rollback();
|
|
18
|
+
await this.connection.end();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
execute(sql, values) {
|
|
22
|
+
return this.connection.execute(sql, values);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -3,7 +3,6 @@ import { camelize } from '../../../util/stringUtil.js';
|
|
|
3
3
|
import { defaultColumnOption, } from '../../../migration/serialized/serializedColumn.js';
|
|
4
4
|
import { getDefaultGqlOption } from '../../../migration/data/GQLOption.js';
|
|
5
5
|
import { columnTypeToGqlPrimitive } from '../../../generatorv2/scripts/columnToGqlType.js';
|
|
6
|
-
import { GqlPrimitive } from '../../../generatorv2/scripts/gqlTypes.js';
|
|
7
6
|
const splitArray = (array, callback) => {
|
|
8
7
|
const indexes = [];
|
|
9
8
|
array.forEach((it, i) => {
|
|
@@ -94,8 +93,8 @@ export class CreateTableParser {
|
|
|
94
93
|
if (next.kind === 'NULL')
|
|
95
94
|
return undefined;
|
|
96
95
|
if (next.kind === TokenKind.Number ||
|
|
97
|
-
gqlType ===
|
|
98
|
-
gqlType ===
|
|
96
|
+
gqlType === 'Float' ||
|
|
97
|
+
gqlType === 'Int')
|
|
99
98
|
return +next.value;
|
|
100
99
|
if (next.kind === TokenKind.String)
|
|
101
100
|
return next.value;
|
|
@@ -64,7 +64,7 @@ const makeUpdateInput = (node) => {
|
|
|
64
64
|
};
|
|
65
65
|
const makeQueryTypeDef = (entity, query) => {
|
|
66
66
|
const args = getArgs(query, entity);
|
|
67
|
-
return tsg.propertyAssign(query.type === 'primary' ? entity.
|
|
67
|
+
return tsg.propertyAssign(query.type === 'primary' ? entity.name.lowerCase() : query.name, typeFieldDefinitionToTsg({
|
|
68
68
|
return: GQLString.type({
|
|
69
69
|
typeName: entity.name.name,
|
|
70
70
|
entity: true,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { RootNode } from '../../nodes/rootNode.js';
|
|
2
|
-
export declare const generateUserDefinedCondition: (root: RootNode, content: string) => string;
|
|
2
|
+
export declare const generateUserDefinedCondition: (root: RootNode, content: string) => string | null;
|
|
@@ -6,7 +6,10 @@ const { createSourceFile, ScriptTarget, SyntaxKind } = typescript;
|
|
|
6
6
|
const isImported = (sourceFile, type, paths) => {
|
|
7
7
|
const importDeclarations = sourceFile.statements.filter(it => it.kind === SyntaxKind.ImportDeclaration);
|
|
8
8
|
return importDeclarations.some(it => {
|
|
9
|
-
if (!paths.
|
|
9
|
+
if (!paths.some(path => {
|
|
10
|
+
const text = it.moduleSpecifier.getText(sourceFile);
|
|
11
|
+
return `'${path}'` === text || `"${path}"` === text;
|
|
12
|
+
}))
|
|
10
13
|
return false;
|
|
11
14
|
const binding = it.importClause?.namedBindings;
|
|
12
15
|
if (binding?.kind !== SyntaxKind.NamedImports)
|
|
@@ -17,17 +20,6 @@ const isImported = (sourceFile, type, paths) => {
|
|
|
17
20
|
});
|
|
18
21
|
};
|
|
19
22
|
export const generateUserDefinedCondition = (root, content) => {
|
|
20
|
-
const sourceFile = createSourceFile('conditions.ts', content, ScriptTarget.ESNext);
|
|
21
|
-
sourceFile.getChildren().map(it => it);
|
|
22
|
-
const exportedVariables = sourceFile.statements.filter(it => it.kind === SyntaxKind.VariableStatement &&
|
|
23
|
-
it.modifiers?.some(it => it.kind === SyntaxKind.ExportKeyword));
|
|
24
|
-
const contextImported = isImported(sourceFile, 'GQLContext', [
|
|
25
|
-
'"./context"',
|
|
26
|
-
'"./context.js"',
|
|
27
|
-
]);
|
|
28
|
-
const customConditionImported = isImported(sourceFile, 'CustomCondition', [
|
|
29
|
-
'"sasat"',
|
|
30
|
-
]);
|
|
31
23
|
const customConditionNames = unique(root.entities.flatMap(it => [
|
|
32
24
|
...it.references.flatMap(it => it.joinCondition
|
|
33
25
|
.filter(it => it.kind === 'custom')
|
|
@@ -36,6 +28,19 @@ export const generateUserDefinedCondition = (root, content) => {
|
|
|
36
28
|
.filter(it => it.kind === 'custom')
|
|
37
29
|
.map(it => it.conditionName)),
|
|
38
30
|
]));
|
|
31
|
+
if (customConditionNames.length === 0)
|
|
32
|
+
return null;
|
|
33
|
+
const sourceFile = createSourceFile('conditions.ts', content, ScriptTarget.ESNext);
|
|
34
|
+
sourceFile.getChildren().map(it => it);
|
|
35
|
+
const exportedVariables = sourceFile.statements.filter(it => it.kind === SyntaxKind.VariableStatement &&
|
|
36
|
+
it.modifiers?.some(it => it.kind === SyntaxKind.ExportKeyword));
|
|
37
|
+
const contextImported = isImported(sourceFile, 'GQLContext', [
|
|
38
|
+
'./context',
|
|
39
|
+
'./context.js',
|
|
40
|
+
]);
|
|
41
|
+
const customConditionImported = isImported(sourceFile, 'CustomCondition', [
|
|
42
|
+
'sasat',
|
|
43
|
+
]);
|
|
39
44
|
const statements = [];
|
|
40
45
|
customConditionNames.forEach(conditionName => {
|
|
41
46
|
const exists = exportedVariables.some(it => {
|
|
@@ -17,5 +17,5 @@ export declare class TsCodegen_v2 {
|
|
|
17
17
|
generateGQLContext: (root: RootNode) => string;
|
|
18
18
|
generateFiles: (root: RootNode) => FileData[];
|
|
19
19
|
generateOnceFiles: () => FileData[];
|
|
20
|
-
generateConditions: (root: RootNode, currentFile: string) => string;
|
|
20
|
+
generateConditions: (root: RootNode, currentFile: string) => string | null;
|
|
21
21
|
}
|
|
@@ -5,7 +5,6 @@ import { mkDirIfNotExist, writeFileIfNotExist } from '../util/fsUtil.js';
|
|
|
5
5
|
import { TsCodegen_v2 } from './codegen/tscodegen_v2.js';
|
|
6
6
|
import { parse } from './parse.js';
|
|
7
7
|
import { Directory } from './directory.js';
|
|
8
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
9
8
|
const { emptyDir, writeFile } = fs;
|
|
10
9
|
export class CodeGen_v2 {
|
|
11
10
|
constructor(store) {
|
|
@@ -70,8 +69,11 @@ export class CodeGen_v2 {
|
|
|
70
69
|
}
|
|
71
70
|
async generateCondition(rootNode) {
|
|
72
71
|
const filePath = this.getFullPath(this.outDir, 'conditions');
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
const content = fs.existsSync(filePath)
|
|
73
|
+
? fs.readFileSync(filePath).toString()
|
|
74
|
+
: '';
|
|
75
|
+
const nextContent = this.codeGen.generateConditions(rootNode, content);
|
|
76
|
+
if (nextContent)
|
|
77
|
+
fs.writeFileSync(filePath, nextContent);
|
|
76
78
|
}
|
|
77
79
|
}
|
|
@@ -4,7 +4,7 @@ import { Table, TableHandler } from '../../migration/serializable/table.js';
|
|
|
4
4
|
import { ReferenceColumn } from '../../migration/serializable/column.js';
|
|
5
5
|
import { SerializedColumn } from '../../migration/serialized/serializedColumn.js';
|
|
6
6
|
import { EntityName } from './entityName.js';
|
|
7
|
-
import {
|
|
7
|
+
import { GQLPrimitive } from '../scripts/gqlTypes.js';
|
|
8
8
|
import { VirtualRelation } from '../../migration/data/virtualRelation.js';
|
|
9
9
|
import { JoinConditionNode } from './JoinConditionNode.js';
|
|
10
10
|
import { GQLQuery } from '../../migration/data/GQLOption.js';
|
|
@@ -57,7 +57,7 @@ export declare type SubTypeNode = {
|
|
|
57
57
|
export declare type FieldNode = {
|
|
58
58
|
fieldName: string;
|
|
59
59
|
columnName: string;
|
|
60
|
-
gqlType:
|
|
60
|
+
gqlType: GQLPrimitive | string;
|
|
61
61
|
dbType: DBColumnTypes;
|
|
62
62
|
isNullable: boolean;
|
|
63
63
|
isArray: boolean;
|
|
@@ -84,6 +84,6 @@ declare type PrimitiveParameterNode = {
|
|
|
84
84
|
fieldName: string;
|
|
85
85
|
columnName: string;
|
|
86
86
|
dbtype: DBColumnTypes;
|
|
87
|
-
gqltype:
|
|
87
|
+
gqltype: GQLPrimitive;
|
|
88
88
|
};
|
|
89
89
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ArgNode, TypeNode } from './typeNode.js';
|
|
2
2
|
import { EntityName } from './entityName.js';
|
|
3
|
-
import {
|
|
3
|
+
import { GQLPrimitive } from '../scripts/gqlTypes.js';
|
|
4
4
|
declare type MutationType = 'create' | 'delete' | 'update';
|
|
5
5
|
export declare type SubscriptionNode = {
|
|
6
6
|
gqlEnabled: boolean;
|
|
@@ -14,6 +14,6 @@ export declare type SubscriptionNode = {
|
|
|
14
14
|
};
|
|
15
15
|
export declare type SubscriptionFilterNode = {
|
|
16
16
|
field: string;
|
|
17
|
-
gqlType:
|
|
17
|
+
gqlType: GQLPrimitive;
|
|
18
18
|
};
|
|
19
19
|
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DBColumnTypes } from '../../migration/column/columnTypes.js';
|
|
2
|
-
import { GqlPrimitive } from '../scripts/gqlTypes.js';
|
|
3
2
|
export const makeMutationNodes = (store) => {
|
|
4
3
|
return store.tables.flatMap(makeTableMutationNodes);
|
|
5
4
|
};
|
|
@@ -56,7 +55,7 @@ const makeUpdateMutationNode = (table) => {
|
|
|
56
55
|
mutationName: `update${table.getEntityName().name}`,
|
|
57
56
|
refetch: !table.gqlOption.mutation.update.noReFetch,
|
|
58
57
|
returnType: {
|
|
59
|
-
typeName: noRefetch ?
|
|
58
|
+
typeName: noRefetch ? 'Boolean' : table.getEntityName().name,
|
|
60
59
|
dbType: noRefetch
|
|
61
60
|
? DBColumnTypes.boolean
|
|
62
61
|
: undefined,
|
|
@@ -87,7 +86,7 @@ const makeDeleteMutationNode = (table) => {
|
|
|
87
86
|
identifyFields: table.getPrimaryKeyColumns().map(it => it.fieldName()),
|
|
88
87
|
refetch: false,
|
|
89
88
|
returnType: {
|
|
90
|
-
typeName:
|
|
89
|
+
typeName: 'Boolean',
|
|
91
90
|
dbType: DBColumnTypes.boolean,
|
|
92
91
|
nullable: false,
|
|
93
92
|
array: false,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GQLPrimitive } from './gqlTypes.js';
|
|
2
2
|
import { DBColumnTypes } from '../../migration/column/columnTypes.js';
|
|
3
|
-
export declare const columnTypeToGqlPrimitive: (type: DBColumnTypes) =>
|
|
3
|
+
export declare const columnTypeToGqlPrimitive: (type: DBColumnTypes) => GQLPrimitive;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GqlPrimitive } from './gqlTypes.js';
|
|
2
1
|
import { DBColumnTypes } from '../../migration/column/columnTypes.js';
|
|
3
2
|
export const columnTypeToGqlPrimitive = (type) => {
|
|
4
3
|
switch (type) {
|
|
@@ -9,10 +8,10 @@ export const columnTypeToGqlPrimitive = (type) => {
|
|
|
9
8
|
case DBColumnTypes.bigInt:
|
|
10
9
|
case DBColumnTypes.decimal:
|
|
11
10
|
case DBColumnTypes.year:
|
|
12
|
-
return
|
|
11
|
+
return 'Int';
|
|
13
12
|
case DBColumnTypes.float:
|
|
14
13
|
case DBColumnTypes.double:
|
|
15
|
-
return
|
|
14
|
+
return 'Float';
|
|
16
15
|
case DBColumnTypes.char:
|
|
17
16
|
case DBColumnTypes.varchar:
|
|
18
17
|
case DBColumnTypes.text:
|
|
@@ -20,8 +19,8 @@ export const columnTypeToGqlPrimitive = (type) => {
|
|
|
20
19
|
case DBColumnTypes.date:
|
|
21
20
|
case DBColumnTypes.dateTime:
|
|
22
21
|
case DBColumnTypes.timestamp:
|
|
23
|
-
return
|
|
22
|
+
return 'String';
|
|
24
23
|
case DBColumnTypes.boolean:
|
|
25
|
-
return
|
|
24
|
+
return 'Boolean';
|
|
26
25
|
}
|
|
27
26
|
};
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
|
|
3
|
-
Float = "Float",
|
|
4
|
-
String = "String",
|
|
5
|
-
Boolean = "Boolean"
|
|
6
|
-
}
|
|
7
|
-
export declare const toTsType: (type: 'Int' | 'String' | 'Float' | string) => string;
|
|
1
|
+
export declare type GQLPrimitive = 'Int' | 'Float' | 'String' | 'Boolean';
|
|
2
|
+
export declare const toTsType: (type: GQLPrimitive | string) => string;
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
export var GqlPrimitive;
|
|
2
|
-
(function (GqlPrimitive) {
|
|
3
|
-
GqlPrimitive["Int"] = "Int";
|
|
4
|
-
GqlPrimitive["Float"] = "Float";
|
|
5
|
-
GqlPrimitive["String"] = "String";
|
|
6
|
-
GqlPrimitive["Boolean"] = "Boolean";
|
|
7
|
-
})(GqlPrimitive || (GqlPrimitive = {}));
|
|
8
1
|
export const toTsType = (type) => {
|
|
9
2
|
switch (type) {
|
|
10
3
|
case 'Int':
|
|
@@ -12,6 +5,8 @@ export const toTsType = (type) => {
|
|
|
12
5
|
return 'number';
|
|
13
6
|
case 'String':
|
|
14
7
|
return 'string';
|
|
8
|
+
case 'Boolean':
|
|
9
|
+
return 'boolean';
|
|
15
10
|
default:
|
|
16
11
|
return type;
|
|
17
12
|
}
|
|
@@ -2,7 +2,7 @@ import { DBColumnTypes } from '../column/columnTypes.js';
|
|
|
2
2
|
import { Serializable } from './serializable.js';
|
|
3
3
|
import { Reference, SerializedColumn, SerializedNormalColumn, SerializedReferenceColumn } from '../serialized/serializedColumn.js';
|
|
4
4
|
import { Table } from './table.js';
|
|
5
|
-
import {
|
|
5
|
+
import { GQLPrimitive } from '../../generatorv2/scripts/gqlTypes.js';
|
|
6
6
|
export interface Column extends Serializable<SerializedColumn> {
|
|
7
7
|
fieldName(): string;
|
|
8
8
|
columnName(): string;
|
|
@@ -11,7 +11,7 @@ export interface Column extends Serializable<SerializedColumn> {
|
|
|
11
11
|
isReference(): this is ReferenceColumn;
|
|
12
12
|
isNullable(): boolean;
|
|
13
13
|
tsType(): string;
|
|
14
|
-
gqlType():
|
|
14
|
+
gqlType(): GQLPrimitive;
|
|
15
15
|
isNullableOnCreate(): boolean;
|
|
16
16
|
}
|
|
17
17
|
export declare class BaseColumn implements Column {
|
|
@@ -22,7 +22,7 @@ export declare class BaseColumn implements Column {
|
|
|
22
22
|
columnName(): string;
|
|
23
23
|
dataType(): DBColumnTypes;
|
|
24
24
|
tsType(): string;
|
|
25
|
-
gqlType():
|
|
25
|
+
gqlType(): GQLPrimitive;
|
|
26
26
|
isNullable(): boolean;
|
|
27
27
|
isNullableOnCreate(): boolean;
|
|
28
28
|
isReference(): this is ReferenceColumn;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { SqlValueType } from '../../../../db/connectors/dbClient.js';
|
|
2
|
-
import { Query, QueryTable } from '../query.js';
|
|
3
|
-
import { TableInfo } from '../createQueryResolveInfo.js';
|
|
4
2
|
export declare type QueryResolveInfo = {
|
|
5
3
|
tableAlias: string;
|
|
6
4
|
isArray: boolean;
|
|
@@ -10,5 +8,3 @@ export declare type QueryResolveInfo = {
|
|
|
10
8
|
};
|
|
11
9
|
export declare type ResultRow = Record<string, SqlValueType>;
|
|
12
10
|
export declare const hydrate: (data: ResultRow[], info: QueryResolveInfo) => unknown[];
|
|
13
|
-
export declare const getQueryTableName: (table: QueryTable) => string;
|
|
14
|
-
export declare const appendKeysToQuery: (query: Query, identifiableKeyMap: TableInfo) => Query;
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { SELECT_ALIAS_SEPARATOR } from './nodeToSql.js';
|
|
2
|
-
import { QueryNodeKind } from '../query.js';
|
|
3
|
-
import { QExpr } from '../../factory.js';
|
|
4
|
-
const getUnique = (target, info) => info.keyAliases
|
|
5
|
-
.map(it => target[info.tableAlias + SELECT_ALIAS_SEPARATOR + it])
|
|
6
|
-
.join('_~_');
|
|
7
2
|
const rowToObjs = (row) => {
|
|
8
3
|
const objs = {};
|
|
9
4
|
Object.entries(row).forEach(([key, value]) => {
|
|
@@ -15,80 +10,61 @@ const rowToObjs = (row) => {
|
|
|
15
10
|
});
|
|
16
11
|
return objs;
|
|
17
12
|
};
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
result[it.property] = child ? [child] : [];
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
result[it.property] = hydrateRow(it, objs);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
return result;
|
|
32
|
-
};
|
|
33
|
-
const findAndAppend = (base, info, objs) => {
|
|
13
|
+
const getUnique = (obj, info) => info.keyAliases.map(it => obj[it]).join('_~_');
|
|
14
|
+
const execTable = (info, objs, current) => {
|
|
15
|
+
let entity = objs[info.tableAlias];
|
|
16
|
+
if (entity[info.keyAliases[0]] == null)
|
|
17
|
+
entity = null;
|
|
18
|
+
let result;
|
|
19
|
+
let currentTarget;
|
|
34
20
|
if (info.isArray) {
|
|
35
|
-
if (!
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
if (!current) {
|
|
22
|
+
result = entity == null ? [] : [entity];
|
|
23
|
+
currentTarget = entity;
|
|
38
24
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
25
|
+
else {
|
|
26
|
+
currentTarget =
|
|
27
|
+
entity == null
|
|
28
|
+
? null
|
|
29
|
+
: current.find((item) => item &&
|
|
30
|
+
info.keyAliases.every(key => item[key] === entity[key]));
|
|
31
|
+
if (currentTarget) {
|
|
32
|
+
result = current;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
currentTarget = entity;
|
|
36
|
+
result = current;
|
|
37
|
+
if (currentTarget)
|
|
38
|
+
result.push(currentTarget);
|
|
39
|
+
}
|
|
47
40
|
}
|
|
48
|
-
else
|
|
49
|
-
return info.joins.some(info => findAndAppend(target, info, objs));
|
|
50
41
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
else {
|
|
43
|
+
currentTarget = current || entity;
|
|
44
|
+
result = currentTarget;
|
|
45
|
+
}
|
|
46
|
+
if (currentTarget !== null) {
|
|
47
|
+
info.joins.forEach(it => {
|
|
48
|
+
currentTarget[it.property] = execTable(it, objs, currentTarget[it.property]);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
55
52
|
};
|
|
56
53
|
export const hydrate = (data, info) => {
|
|
57
54
|
const result = [];
|
|
58
55
|
const t0mapper = {};
|
|
56
|
+
info.isArray = false;
|
|
59
57
|
data.forEach(row => {
|
|
60
|
-
const unique = getUnique(row, info);
|
|
61
58
|
const objs = rowToObjs(row);
|
|
59
|
+
const currentObj = objs[info.tableAlias];
|
|
60
|
+
const unique = getUnique(currentObj, info);
|
|
62
61
|
if (t0mapper[unique] === undefined) {
|
|
63
62
|
t0mapper[unique] = result.length;
|
|
64
|
-
result.push(
|
|
63
|
+
result.push(execTable(info, objs, currentObj));
|
|
65
64
|
return;
|
|
66
65
|
}
|
|
67
66
|
const base = result[t0mapper[unique]];
|
|
68
|
-
|
|
67
|
+
execTable(info, objs, base);
|
|
69
68
|
});
|
|
70
69
|
return result;
|
|
71
70
|
};
|
|
72
|
-
export const getQueryTableName = (table) => {
|
|
73
|
-
if (!table.subquery)
|
|
74
|
-
return table.name;
|
|
75
|
-
return getQueryTableName(table.query.from);
|
|
76
|
-
};
|
|
77
|
-
export const appendKeysToQuery = (query, identifiableKeyMap) => {
|
|
78
|
-
const getTables = (table) => [
|
|
79
|
-
table,
|
|
80
|
-
...table.joins.flatMap(it => getTables(it.table)),
|
|
81
|
-
];
|
|
82
|
-
const tables = getTables(query.from);
|
|
83
|
-
tables.forEach(table => {
|
|
84
|
-
const keys = identifiableKeyMap[getQueryTableName(table)].identifiableFields;
|
|
85
|
-
keys.forEach(key => {
|
|
86
|
-
if (!query.select.some(it => it.kind === QueryNodeKind.Field &&
|
|
87
|
-
it.table === table.alias &&
|
|
88
|
-
it.name === key)) {
|
|
89
|
-
query.select.push(QExpr.field(table.alias, key, table.alias + SELECT_ALIAS_SEPARATOR + key));
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
return query;
|
|
94
|
-
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SqlValueType } from '../../../../db/connectors/dbClient.js';
|
|
2
|
+
import { QueryTable } from '../query.js';
|
|
3
|
+
export declare type QueryResolveInfo = {
|
|
4
|
+
tableAlias: string;
|
|
5
|
+
isArray: boolean;
|
|
6
|
+
keyAliases: string[];
|
|
7
|
+
joins: QueryResolveInfo[];
|
|
8
|
+
property: string;
|
|
9
|
+
};
|
|
10
|
+
export declare type ResultRow = Record<string, SqlValueType>;
|
|
11
|
+
export declare const hydrate: (data: ResultRow[], info: QueryResolveInfo) => unknown[];
|
|
12
|
+
export declare const getQueryTableName: (table: QueryTable) => string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SELECT_ALIAS_SEPARATOR } from './nodeToSql.js';
|
|
2
|
+
const rowToObjs = (row) => {
|
|
3
|
+
const objs = {};
|
|
4
|
+
Object.entries(row).forEach(([key, value]) => {
|
|
5
|
+
const [table, column] = key.split(SELECT_ALIAS_SEPARATOR);
|
|
6
|
+
if (!objs[table]) {
|
|
7
|
+
objs[table] = {};
|
|
8
|
+
}
|
|
9
|
+
objs[table][column] = value;
|
|
10
|
+
});
|
|
11
|
+
return objs;
|
|
12
|
+
};
|
|
13
|
+
const getUnique = (obj, info) => info.keyAliases
|
|
14
|
+
.map(it => obj[it])
|
|
15
|
+
.join('_~_');
|
|
16
|
+
export const hydrate = (data, info) => {
|
|
17
|
+
const result = [];
|
|
18
|
+
const t0mapper = {};
|
|
19
|
+
info.isArray = false;
|
|
20
|
+
data.forEach(row => {
|
|
21
|
+
const objs = rowToObjs(row);
|
|
22
|
+
const currentObj = objs[info.tableAlias];
|
|
23
|
+
const unique = getUnique(currentObj, info);
|
|
24
|
+
if (t0mapper[unique] === undefined) {
|
|
25
|
+
t0mapper[unique] = result.length;
|
|
26
|
+
result.push(execTable(info, objs, currentObj));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const base = result[t0mapper[unique]];
|
|
30
|
+
execTable(info, objs, base);
|
|
31
|
+
});
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
const execTable = (info, objs, current) => {
|
|
35
|
+
let entity = objs[info.tableAlias];
|
|
36
|
+
if (entity[info.keyAliases[0]] == null)
|
|
37
|
+
entity = null;
|
|
38
|
+
let result;
|
|
39
|
+
let currentTarget;
|
|
40
|
+
if (info.isArray) {
|
|
41
|
+
if (!current) {
|
|
42
|
+
result = entity == null ? [] : [entity];
|
|
43
|
+
currentTarget = entity;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
currentTarget = entity == null ? null : current.find((item) => item && info.keyAliases.every(key => item[key] === entity[key]));
|
|
47
|
+
if (currentTarget) {
|
|
48
|
+
result = current;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
currentTarget = entity;
|
|
52
|
+
result = current;
|
|
53
|
+
if (currentTarget)
|
|
54
|
+
result.push(currentTarget);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
currentTarget = current || entity;
|
|
60
|
+
result = currentTarget;
|
|
61
|
+
}
|
|
62
|
+
if (currentTarget !== null) {
|
|
63
|
+
info.joins.forEach(it => {
|
|
64
|
+
currentTarget[it.property] = execTable(it, objs, currentTarget[it.property]);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
};
|
|
69
|
+
export const getQueryTableName = (table) => {
|
|
70
|
+
if (!table.subquery)
|
|
71
|
+
return table.name;
|
|
72
|
+
return getQueryTableName(table.query.from);
|
|
73
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { QueryNodeKind, NO_ALIAS, } from './query/query.js';
|
|
2
|
-
import { getQueryTableName } from './query/sql/hydrate.js';
|
|
3
2
|
export const createAliasReplacer = (tableInfo, tableAliases = {}) => {
|
|
4
3
|
const replaceAlias = (node) => {
|
|
5
4
|
const map = {
|
|
@@ -96,3 +95,8 @@ export const replaceAliases = (query, tableInfo) => {
|
|
|
96
95
|
offset: query.offset,
|
|
97
96
|
};
|
|
98
97
|
};
|
|
98
|
+
const getQueryTableName = (table) => {
|
|
99
|
+
if (!table.subquery)
|
|
100
|
+
return table.name;
|
|
101
|
+
return getQueryTableName(table.query.from);
|
|
102
|
+
};
|