xansql 1.0.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/Types/fields/Array.d.ts +7 -0
- package/Types/fields/Array.js +6 -0
- package/Types/fields/Array.js.map +1 -0
- package/Types/fields/Array.mjs +6 -0
- package/Types/fields/Array.mjs.map +1 -0
- package/Types/fields/Boolean.d.ts +8 -0
- package/Types/fields/Boolean.js +11 -0
- package/Types/fields/Boolean.js.map +1 -0
- package/Types/fields/Boolean.mjs +11 -0
- package/Types/fields/Boolean.mjs.map +1 -0
- package/Types/fields/Date.d.ts +10 -0
- package/Types/fields/Date.js +22 -0
- package/Types/fields/Date.js.map +1 -0
- package/Types/fields/Date.mjs +22 -0
- package/Types/fields/Date.mjs.map +1 -0
- package/Types/fields/Enum.d.ts +8 -0
- package/Types/fields/Enum.js +10 -0
- package/Types/fields/Enum.js.map +1 -0
- package/Types/fields/Enum.mjs +10 -0
- package/Types/fields/Enum.mjs.map +1 -0
- package/Types/fields/File.d.ts +7 -0
- package/Types/fields/File.js +6 -0
- package/Types/fields/File.js.map +1 -0
- package/Types/fields/File.mjs +6 -0
- package/Types/fields/File.mjs.map +1 -0
- package/Types/fields/IDField.d.ts +6 -0
- package/Types/fields/IDField.js +2 -0
- package/Types/fields/IDField.js.map +1 -0
- package/Types/fields/IDField.mjs +2 -0
- package/Types/fields/IDField.mjs.map +1 -0
- package/Types/fields/Number.d.ts +8 -0
- package/Types/fields/Number.js +11 -0
- package/Types/fields/Number.js.map +1 -0
- package/Types/fields/Number.mjs +11 -0
- package/Types/fields/Number.mjs.map +1 -0
- package/Types/fields/Object.d.ts +8 -0
- package/Types/fields/Object.js +11 -0
- package/Types/fields/Object.js.map +1 -0
- package/Types/fields/Object.mjs +11 -0
- package/Types/fields/Object.mjs.map +1 -0
- package/Types/fields/Record.d.ts +8 -0
- package/Types/fields/Record.js +11 -0
- package/Types/fields/Record.js.map +1 -0
- package/Types/fields/Record.mjs +11 -0
- package/Types/fields/Record.mjs.map +1 -0
- package/Types/fields/Schema.d.ts +16 -0
- package/Types/fields/Schema.js +34 -0
- package/Types/fields/Schema.js.map +1 -0
- package/Types/fields/Schema.mjs +34 -0
- package/Types/fields/Schema.mjs.map +1 -0
- package/Types/fields/String.d.ts +10 -0
- package/Types/fields/String.js +20 -0
- package/Types/fields/String.js.map +1 -0
- package/Types/fields/String.mjs +20 -0
- package/Types/fields/String.mjs.map +1 -0
- package/Types/fields/Tuple.d.ts +8 -0
- package/Types/fields/Tuple.js +11 -0
- package/Types/fields/Tuple.js.map +1 -0
- package/Types/fields/Tuple.mjs +11 -0
- package/Types/fields/Tuple.mjs.map +1 -0
- package/Types/fields/Union.d.ts +8 -0
- package/Types/fields/Union.js +11 -0
- package/Types/fields/Union.js.map +1 -0
- package/Types/fields/Union.mjs +11 -0
- package/Types/fields/Union.mjs.map +1 -0
- package/Types/index.d.ts +56 -0
- package/Types/index.js +129 -0
- package/Types/index.js.map +1 -0
- package/Types/index.mjs +129 -0
- package/Types/index.mjs.map +1 -0
- package/Types/types.d.ts +20 -0
- package/core/ExcuteMeta.d.ts +11 -0
- package/core/ExcuteMeta.js +22 -0
- package/core/ExcuteMeta.js.map +1 -0
- package/core/ExcuteMeta.mjs +22 -0
- package/core/ExcuteMeta.mjs.map +1 -0
- package/core/Xansql.d.ts +46 -0
- package/core/Xansql.js +132 -0
- package/core/Xansql.js.map +1 -0
- package/core/Xansql.mjs +132 -0
- package/core/Xansql.mjs.map +1 -0
- package/core/XansqlError.js +11 -0
- package/core/XansqlError.js.map +1 -0
- package/core/XansqlError.mjs +11 -0
- package/core/XansqlError.mjs.map +1 -0
- package/core/XansqlResult.d.ts +12 -0
- package/core/XansqlResult.js +32 -0
- package/core/XansqlResult.js.map +1 -0
- package/core/XansqlResult.mjs +32 -0
- package/core/XansqlResult.mjs.map +1 -0
- package/core/classes/EventManager.d.ts +72 -0
- package/core/classes/EventManager.js +21 -0
- package/core/classes/EventManager.js.map +1 -0
- package/core/classes/EventManager.mjs +21 -0
- package/core/classes/EventManager.mjs.map +1 -0
- package/core/classes/ForeignInfo.js +51 -0
- package/core/classes/ForeignInfo.js.map +1 -0
- package/core/classes/ForeignInfo.mjs +51 -0
- package/core/classes/ForeignInfo.mjs.map +1 -0
- package/core/classes/Migration/ForeingMigration.d.ts +12 -0
- package/core/classes/Migration/ForeingMigration.js +52 -0
- package/core/classes/Migration/ForeingMigration.js.map +1 -0
- package/core/classes/Migration/ForeingMigration.mjs +52 -0
- package/core/classes/Migration/ForeingMigration.mjs.map +1 -0
- package/core/classes/Migration/IndexMigration.d.ts +12 -0
- package/core/classes/Migration/IndexMigration.js +49 -0
- package/core/classes/Migration/IndexMigration.js.map +1 -0
- package/core/classes/Migration/IndexMigration.mjs +49 -0
- package/core/classes/Migration/IndexMigration.mjs.map +1 -0
- package/core/classes/Migration/TableMigration.d.ts +33 -0
- package/core/classes/Migration/TableMigration.js +215 -0
- package/core/classes/Migration/TableMigration.js.map +1 -0
- package/core/classes/Migration/TableMigration.mjs +215 -0
- package/core/classes/Migration/TableMigration.mjs.map +1 -0
- package/core/classes/Migration/index.d.ts +12 -0
- package/core/classes/Migration/index.js +189 -0
- package/core/classes/Migration/index.js.map +1 -0
- package/core/classes/Migration/index.mjs +189 -0
- package/core/classes/Migration/index.mjs.map +1 -0
- package/core/classes/ModelFormatter.js +166 -0
- package/core/classes/ModelFormatter.js.map +1 -0
- package/core/classes/ModelFormatter.mjs +166 -0
- package/core/classes/ModelFormatter.mjs.map +1 -0
- package/core/classes/TypesGenerator.d.ts +13 -0
- package/core/classes/TypesGenerator.js +170 -0
- package/core/classes/TypesGenerator.js.map +1 -0
- package/core/classes/TypesGenerator.mjs +170 -0
- package/core/classes/TypesGenerator.mjs.map +1 -0
- package/core/classes/XansqlConfig.js +33 -0
- package/core/classes/XansqlConfig.js.map +1 -0
- package/core/classes/XansqlConfig.mjs +33 -0
- package/core/classes/XansqlConfig.mjs.map +1 -0
- package/core/classes/XansqlFetch.js +304 -0
- package/core/classes/XansqlFetch.js.map +1 -0
- package/core/classes/XansqlFetch.mjs +304 -0
- package/core/classes/XansqlFetch.mjs.map +1 -0
- package/core/classes/XansqlTransaction.d.ts +13 -0
- package/core/classes/XansqlTransaction.js +46 -0
- package/core/classes/XansqlTransaction.js.map +1 -0
- package/core/classes/XansqlTransaction.mjs +46 -0
- package/core/classes/XansqlTransaction.mjs.map +1 -0
- package/core/type.d.ts +117 -0
- package/index.d.ts +3 -0
- package/index.js +1 -0
- package/index.js.map +1 -0
- package/index.mjs +1 -0
- package/index.mjs.map +1 -0
- package/model/Args/RelationExcuteArgs.js +5 -0
- package/model/Args/RelationExcuteArgs.js.map +1 -0
- package/model/Args/RelationExcuteArgs.mjs +5 -0
- package/model/Args/RelationExcuteArgs.mjs.map +1 -0
- package/model/Args/WhereArgs.js +226 -0
- package/model/Args/WhereArgs.js.map +1 -0
- package/model/Args/WhereArgs.mjs +226 -0
- package/model/Args/WhereArgs.mjs.map +1 -0
- package/model/Base.d.ts +26 -0
- package/model/Base.js +64 -0
- package/model/Base.js.map +1 -0
- package/model/Base.mjs +64 -0
- package/model/Base.mjs.map +1 -0
- package/model/Executer/Aggregate/SelectArgs.js +59 -0
- package/model/Executer/Aggregate/SelectArgs.js.map +1 -0
- package/model/Executer/Aggregate/SelectArgs.mjs +59 -0
- package/model/Executer/Aggregate/SelectArgs.mjs.map +1 -0
- package/model/Executer/Aggregate/index.js +59 -0
- package/model/Executer/Aggregate/index.js.map +1 -0
- package/model/Executer/Aggregate/index.mjs +59 -0
- package/model/Executer/Aggregate/index.mjs.map +1 -0
- package/model/Executer/Create/CreateDataArgs.js +145 -0
- package/model/Executer/Create/CreateDataArgs.js.map +1 -0
- package/model/Executer/Create/CreateDataArgs.mjs +145 -0
- package/model/Executer/Create/CreateDataArgs.mjs.map +1 -0
- package/model/Executer/Create/index.js +101 -0
- package/model/Executer/Create/index.js.map +1 -0
- package/model/Executer/Create/index.mjs +101 -0
- package/model/Executer/Create/index.mjs.map +1 -0
- package/model/Executer/Delete/index.js +112 -0
- package/model/Executer/Delete/index.js.map +1 -0
- package/model/Executer/Delete/index.mjs +112 -0
- package/model/Executer/Delete/index.mjs.map +1 -0
- package/model/Executer/Find/DistinctArgs.js +32 -0
- package/model/Executer/Find/DistinctArgs.js.map +1 -0
- package/model/Executer/Find/DistinctArgs.mjs +32 -0
- package/model/Executer/Find/DistinctArgs.mjs.map +1 -0
- package/model/Executer/Find/LimitArgs.js +31 -0
- package/model/Executer/Find/LimitArgs.js.map +1 -0
- package/model/Executer/Find/LimitArgs.mjs +31 -0
- package/model/Executer/Find/LimitArgs.mjs.map +1 -0
- package/model/Executer/Find/OrderByArgs.js +29 -0
- package/model/Executer/Find/OrderByArgs.js.map +1 -0
- package/model/Executer/Find/OrderByArgs.mjs +29 -0
- package/model/Executer/Find/OrderByArgs.mjs.map +1 -0
- package/model/Executer/Find/SelectArgs.js +119 -0
- package/model/Executer/Find/SelectArgs.js.map +1 -0
- package/model/Executer/Find/SelectArgs.mjs +119 -0
- package/model/Executer/Find/SelectArgs.mjs.map +1 -0
- package/model/Executer/Find/index.js +338 -0
- package/model/Executer/Find/index.js.map +1 -0
- package/model/Executer/Find/index.mjs +338 -0
- package/model/Executer/Find/index.mjs.map +1 -0
- package/model/Executer/Update/UpdateDataArgs.js +124 -0
- package/model/Executer/Update/UpdateDataArgs.js.map +1 -0
- package/model/Executer/Update/UpdateDataArgs.mjs +124 -0
- package/model/Executer/Update/UpdateDataArgs.mjs.map +1 -0
- package/model/Executer/Update/index.js +207 -0
- package/model/Executer/Update/index.js.map +1 -0
- package/model/Executer/Update/index.mjs +207 -0
- package/model/Executer/Update/index.mjs.map +1 -0
- package/model/include/ValueFormatter.js +99 -0
- package/model/include/ValueFormatter.js.map +1 -0
- package/model/include/ValueFormatter.mjs +99 -0
- package/model/include/ValueFormatter.mjs.map +1 -0
- package/model/index.d.ts +29 -0
- package/model/index.js +236 -0
- package/model/index.js.map +1 -0
- package/model/index.mjs +236 -0
- package/model/index.mjs.map +1 -0
- package/model/type.d.ts +106 -0
- package/package.json +32 -0
- package/readme.md +359 -0
- package/utils/chunker.js +53 -0
- package/utils/chunker.js.map +1 -0
- package/utils/chunker.mjs +53 -0
- package/utils/chunker.mjs.map +1 -0
- package/utils/index.js +49 -0
- package/utils/index.js.map +1 -0
- package/utils/index.mjs +49 -0
- package/utils/index.mjs.map +1 -0
- package/utils/sha256.js +66 -0
- package/utils/sha256.js.map +1 -0
- package/utils/sha256.mjs +66 -0
- package/utils/sha256.mjs.map +1 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var ExcuteMeta=require('../../../core/ExcuteMeta.js'),XansqlError=require('../../../core/XansqlError.js'),chunker=require('../../../utils/chunker.js'),WhereArgs=require('../../Args/WhereArgs.js'),LimitArgs=require('../Find/LimitArgs.js'),OrderByArgs=require('../Find/OrderByArgs.js'),SelectArgs=require('./SelectArgs.js');class AggregateExecuter {
|
|
2
|
+
constructor(model, removeGroupByColumns = true) {
|
|
3
|
+
this.model = model;
|
|
4
|
+
this.removeGroupByColumns = removeGroupByColumns;
|
|
5
|
+
}
|
|
6
|
+
async execute(args) {
|
|
7
|
+
const xansql = this.model.xansql;
|
|
8
|
+
const model = this.model;
|
|
9
|
+
const select = new SelectArgs.default(model, args.select || {});
|
|
10
|
+
const Where = new WhereArgs.default(model, args.where || {});
|
|
11
|
+
const OrderBy = new OrderByArgs.default(model, args.orderBy || {});
|
|
12
|
+
let LimitSql = "";
|
|
13
|
+
if (args.groupBy && args.groupBy.length) {
|
|
14
|
+
LimitSql = (new LimitArgs.default(model, args.limit || {})).sql;
|
|
15
|
+
}
|
|
16
|
+
if (!LimitSql && Object.keys(args.limit || {}).length) {
|
|
17
|
+
LimitSql = (new LimitArgs.default(model, args.limit || {})).sql;
|
|
18
|
+
}
|
|
19
|
+
let sql = `SELECT `;
|
|
20
|
+
let groupBySql = "";
|
|
21
|
+
if (args.groupBy && args.groupBy.length) {
|
|
22
|
+
// check column is exists
|
|
23
|
+
for (let column of args.groupBy) {
|
|
24
|
+
if (!model.schema[column]) {
|
|
25
|
+
throw new XansqlError.default({
|
|
26
|
+
message: `Column ${column} not found in model ${model.table} for groupBy`,
|
|
27
|
+
model: model.table,
|
|
28
|
+
column: column
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
sql += args.groupBy.join(", ") + ", ";
|
|
33
|
+
groupBySql = ` GROUP BY ${args.groupBy.join(", ")} `;
|
|
34
|
+
}
|
|
35
|
+
sql += `${select.sql} FROM ${model.table} ${Where.sql}${groupBySql}${OrderBy.sql}${LimitSql}`.trim();
|
|
36
|
+
let executeId = undefined;
|
|
37
|
+
if (typeof window !== "undefined") {
|
|
38
|
+
executeId = ExcuteMeta.default.set({
|
|
39
|
+
model,
|
|
40
|
+
action: "AGGREGATE",
|
|
41
|
+
modelType: "main",
|
|
42
|
+
args
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const { results } = await xansql.execute(sql, executeId);
|
|
46
|
+
// remove groupBy columns from results
|
|
47
|
+
if (this.removeGroupByColumns && results.length && args.groupBy && args.groupBy.length) {
|
|
48
|
+
const groupBySet = new Set(args.groupBy);
|
|
49
|
+
for (let { chunk } of chunker.chunkArray(results)) {
|
|
50
|
+
for (let row of chunk) {
|
|
51
|
+
for (let column of groupBySet) {
|
|
52
|
+
delete row[column];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
}exports.default=AggregateExecuter;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/model/Executer/Aggregate/index.ts"],"sourcesContent":["import Model from \"../..\";\nimport ExecuteMeta from \"../../../core/ExcuteMeta\";\nimport XansqlError from \"../../../core/XansqlError\";\nimport { chunkArray } from \"../../../utils/chunker\";\nimport WhereArgs from \"../../Args/WhereArgs\";\nimport { AggregateArgsType } from \"../../type\";\nimport LimitArgs from \"../Find/LimitArgs\";\nimport OrderByArgs from \"../Find/OrderByArgs\";\nimport SelectArgs from \"./SelectArgs\";\n\nclass AggregateExecuter {\n\n private model: Model\n private removeGroupByColumns: boolean\n constructor(model: Model, removeGroupByColumns: boolean = true) {\n this.model = model\n this.removeGroupByColumns = removeGroupByColumns\n }\n\n async execute(args: AggregateArgsType) {\n const xansql = this.model.xansql\n const model = this.model\n const select = new SelectArgs(model, args.select || {})\n const Where = new WhereArgs(model, args.where || {})\n const OrderBy = new OrderByArgs(model, args.orderBy || {})\n let LimitSql = \"\"\n\n\n\n if (args.groupBy && args.groupBy.length) {\n LimitSql = (new LimitArgs(model, args.limit || {})).sql\n }\n\n if (!LimitSql && Object.keys(args.limit || {}).length) {\n LimitSql = (new LimitArgs(model, args.limit || {})).sql\n }\n\n let sql = `SELECT `\n let groupBySql = \"\"\n if (args.groupBy && args.groupBy.length) {\n // check column is exists\n for (let column of args.groupBy) {\n if (!model.schema[column]) {\n throw new XansqlError({\n message: `Column ${column} not found in model ${model.table} for groupBy`,\n model: model.table,\n column: column\n });\n }\n }\n sql += args.groupBy.join(\", \") + \", \"\n groupBySql = ` GROUP BY ${args.groupBy.join(\", \")} `\n }\n sql += `${select.sql} FROM ${model.table} ${Where.sql}${groupBySql}${OrderBy.sql}${LimitSql}`.trim()\n\n let executeId = undefined;\n if (typeof window !== \"undefined\") {\n executeId = ExecuteMeta.set({\n model,\n action: \"AGGREGATE\",\n modelType: \"main\",\n args\n });\n }\n const { results } = await xansql.execute(sql, executeId)\n\n // remove groupBy columns from results\n if (this.removeGroupByColumns && results.length && args.groupBy && args.groupBy.length) {\n const groupBySet = new Set(args.groupBy)\n for (let { chunk } of chunkArray(results)) {\n for (let row of chunk) {\n for (let column of groupBySet) {\n delete (row as any)[column]\n }\n }\n }\n }\n\n return results\n }\n}\n\nexport default AggregateExecuter"],"names":["SelectArgs","WhereArgs","OrderByArgs","LimitArgs","XansqlError","ExecuteMeta","chunkArray"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import ExecuteMeta from'../../../core/ExcuteMeta.mjs';import XansqlError from'../../../core/XansqlError.mjs';import {chunkArray}from'../../../utils/chunker.mjs';import WhereArgs from'../../Args/WhereArgs.mjs';import LimitArgs from'../Find/LimitArgs.mjs';import OrderByArgs from'../Find/OrderByArgs.mjs';import SelectArgs from'./SelectArgs.mjs';class AggregateExecuter {
|
|
2
|
+
constructor(model, removeGroupByColumns = true) {
|
|
3
|
+
this.model = model;
|
|
4
|
+
this.removeGroupByColumns = removeGroupByColumns;
|
|
5
|
+
}
|
|
6
|
+
async execute(args) {
|
|
7
|
+
const xansql = this.model.xansql;
|
|
8
|
+
const model = this.model;
|
|
9
|
+
const select = new SelectArgs(model, args.select || {});
|
|
10
|
+
const Where = new WhereArgs(model, args.where || {});
|
|
11
|
+
const OrderBy = new OrderByArgs(model, args.orderBy || {});
|
|
12
|
+
let LimitSql = "";
|
|
13
|
+
if (args.groupBy && args.groupBy.length) {
|
|
14
|
+
LimitSql = (new LimitArgs(model, args.limit || {})).sql;
|
|
15
|
+
}
|
|
16
|
+
if (!LimitSql && Object.keys(args.limit || {}).length) {
|
|
17
|
+
LimitSql = (new LimitArgs(model, args.limit || {})).sql;
|
|
18
|
+
}
|
|
19
|
+
let sql = `SELECT `;
|
|
20
|
+
let groupBySql = "";
|
|
21
|
+
if (args.groupBy && args.groupBy.length) {
|
|
22
|
+
// check column is exists
|
|
23
|
+
for (let column of args.groupBy) {
|
|
24
|
+
if (!model.schema[column]) {
|
|
25
|
+
throw new XansqlError({
|
|
26
|
+
message: `Column ${column} not found in model ${model.table} for groupBy`,
|
|
27
|
+
model: model.table,
|
|
28
|
+
column: column
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
sql += args.groupBy.join(", ") + ", ";
|
|
33
|
+
groupBySql = ` GROUP BY ${args.groupBy.join(", ")} `;
|
|
34
|
+
}
|
|
35
|
+
sql += `${select.sql} FROM ${model.table} ${Where.sql}${groupBySql}${OrderBy.sql}${LimitSql}`.trim();
|
|
36
|
+
let executeId = undefined;
|
|
37
|
+
if (typeof window !== "undefined") {
|
|
38
|
+
executeId = ExecuteMeta.set({
|
|
39
|
+
model,
|
|
40
|
+
action: "AGGREGATE",
|
|
41
|
+
modelType: "main",
|
|
42
|
+
args
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const { results } = await xansql.execute(sql, executeId);
|
|
46
|
+
// remove groupBy columns from results
|
|
47
|
+
if (this.removeGroupByColumns && results.length && args.groupBy && args.groupBy.length) {
|
|
48
|
+
const groupBySet = new Set(args.groupBy);
|
|
49
|
+
for (let { chunk } of chunkArray(results)) {
|
|
50
|
+
for (let row of chunk) {
|
|
51
|
+
for (let column of groupBySet) {
|
|
52
|
+
delete row[column];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
}export{AggregateExecuter as default};//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/model/Executer/Aggregate/index.ts"],"sourcesContent":["import Model from \"../..\";\nimport ExecuteMeta from \"../../../core/ExcuteMeta\";\nimport XansqlError from \"../../../core/XansqlError\";\nimport { chunkArray } from \"../../../utils/chunker\";\nimport WhereArgs from \"../../Args/WhereArgs\";\nimport { AggregateArgsType } from \"../../type\";\nimport LimitArgs from \"../Find/LimitArgs\";\nimport OrderByArgs from \"../Find/OrderByArgs\";\nimport SelectArgs from \"./SelectArgs\";\n\nclass AggregateExecuter {\n\n private model: Model\n private removeGroupByColumns: boolean\n constructor(model: Model, removeGroupByColumns: boolean = true) {\n this.model = model\n this.removeGroupByColumns = removeGroupByColumns\n }\n\n async execute(args: AggregateArgsType) {\n const xansql = this.model.xansql\n const model = this.model\n const select = new SelectArgs(model, args.select || {})\n const Where = new WhereArgs(model, args.where || {})\n const OrderBy = new OrderByArgs(model, args.orderBy || {})\n let LimitSql = \"\"\n\n\n\n if (args.groupBy && args.groupBy.length) {\n LimitSql = (new LimitArgs(model, args.limit || {})).sql\n }\n\n if (!LimitSql && Object.keys(args.limit || {}).length) {\n LimitSql = (new LimitArgs(model, args.limit || {})).sql\n }\n\n let sql = `SELECT `\n let groupBySql = \"\"\n if (args.groupBy && args.groupBy.length) {\n // check column is exists\n for (let column of args.groupBy) {\n if (!model.schema[column]) {\n throw new XansqlError({\n message: `Column ${column} not found in model ${model.table} for groupBy`,\n model: model.table,\n column: column\n });\n }\n }\n sql += args.groupBy.join(\", \") + \", \"\n groupBySql = ` GROUP BY ${args.groupBy.join(\", \")} `\n }\n sql += `${select.sql} FROM ${model.table} ${Where.sql}${groupBySql}${OrderBy.sql}${LimitSql}`.trim()\n\n let executeId = undefined;\n if (typeof window !== \"undefined\") {\n executeId = ExecuteMeta.set({\n model,\n action: \"AGGREGATE\",\n modelType: \"main\",\n args\n });\n }\n const { results } = await xansql.execute(sql, executeId)\n\n // remove groupBy columns from results\n if (this.removeGroupByColumns && results.length && args.groupBy && args.groupBy.length) {\n const groupBySet = new Set(args.groupBy)\n for (let { chunk } of chunkArray(results)) {\n for (let row of chunk) {\n for (let column of groupBySet) {\n delete (row as any)[column]\n }\n }\n }\n }\n\n return results\n }\n}\n\nexport default AggregateExecuter"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var ForeignInfo=require('../../../core/classes/ForeignInfo.js'),XansqlError=require('../../../core/XansqlError.js'),Date=require('../../../Types/fields/Date.js'),index=require('../../../utils/index.js'),ValueFormatter=require('../../include/ValueFormatter.js');class CreateDataArgs {
|
|
2
|
+
constructor(model, data) {
|
|
3
|
+
/**
|
|
4
|
+
* Generate SQL for data
|
|
5
|
+
* For create mode: (col1, col2, col3) VALUES (val1, val2, val3)
|
|
6
|
+
* For update mode: col1 = val1, col2 = val2, col3 = val3
|
|
7
|
+
*/
|
|
8
|
+
this.data = {};
|
|
9
|
+
this.files = {};
|
|
10
|
+
/**
|
|
11
|
+
* Get data object
|
|
12
|
+
* format: { col1: val1, col2: val2, col3: val3 }
|
|
13
|
+
*/
|
|
14
|
+
this.relations = {};
|
|
15
|
+
/**
|
|
16
|
+
* Get stack of data and relations for nested create or update
|
|
17
|
+
* format: [{ data: { col1: val1, col2: val2 }, relations: { relation1: data1 }, sql: '(col1, col2) VALUES (val1, val2)' }, ...]
|
|
18
|
+
*/
|
|
19
|
+
this.values = [];
|
|
20
|
+
this.errors = [];
|
|
21
|
+
if (Array.isArray(data)) {
|
|
22
|
+
for (let item of data) {
|
|
23
|
+
if (!index.isObject(item)) {
|
|
24
|
+
throw new XansqlError.default({
|
|
25
|
+
message: `Invalid data item for model ${model.table}. Expected object, got ${typeof item}`,
|
|
26
|
+
model: model.table
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const dataArgs = new CreateDataArgs(model, item);
|
|
30
|
+
this.values.push(...dataArgs.values);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
for (let column in data) {
|
|
35
|
+
const field = model.schema[column];
|
|
36
|
+
let value = data[column];
|
|
37
|
+
try {
|
|
38
|
+
if (ForeignInfo.default.is(field)) {
|
|
39
|
+
if (ForeignInfo.default.isSchema(field)) {
|
|
40
|
+
if (index.isNumber(value)) {
|
|
41
|
+
this.data[column] = value;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw new XansqlError.default({
|
|
45
|
+
message: `Invalid value for foreign key column ${model.table}.${column}. Expected number, got ${typeof value}`,
|
|
46
|
+
model: model.table,
|
|
47
|
+
column: column
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// array of foreign keys
|
|
53
|
+
if (index.isObject(value) || index.isArray(value)) {
|
|
54
|
+
const foreign = ForeignInfo.default.get(model, column);
|
|
55
|
+
let rdatas = index.isObject(value) ? [value] : value;
|
|
56
|
+
if (rdatas.length === 0) {
|
|
57
|
+
throw new XansqlError.default({
|
|
58
|
+
message: `Relation data array for column ${model.table}.${column} cannot be empty.`,
|
|
59
|
+
model: model.table,
|
|
60
|
+
column: column
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
this.relations[column] = {
|
|
64
|
+
data: rdatas,
|
|
65
|
+
foreign
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
throw new XansqlError.default({
|
|
70
|
+
message: `Invalid value for relation column ${model.table}.${column}. Expected object or array, got ${typeof value}`,
|
|
71
|
+
model: model.table,
|
|
72
|
+
column: column
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// check is the field is IDField or created_at or updated_at
|
|
79
|
+
if (model.IDColumn === column || field instanceof Date.default && (field.meta.update || field.meta.create)) {
|
|
80
|
+
throw new XansqlError.default({
|
|
81
|
+
message: `Cannot set value for ${model.table}.${column}. It is automatically managed.`,
|
|
82
|
+
model: model.table,
|
|
83
|
+
column: column
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (value instanceof File) {
|
|
87
|
+
this.files[column] = value;
|
|
88
|
+
this.data[column] = '';
|
|
89
|
+
ValueFormatter.default.toSql(model, column, value); // for validation
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.data[column] = ValueFormatter.default.toSql(model, column, value);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof XansqlError.default) {
|
|
98
|
+
this.errors.push(error);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (this.errors.length > 0) {
|
|
106
|
+
throw this.errors;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Auto add missing columns with null value for create mode
|
|
110
|
+
* Auto add updated_at column with current timestamp for update mode
|
|
111
|
+
* Skip foreign key columns which are not optional or nullable in create mode
|
|
112
|
+
* Skip ID column in create mode
|
|
113
|
+
* Skip created_at column in update mode
|
|
114
|
+
* Skip updated_at column in create mode
|
|
115
|
+
* Skip columns which are already set in data
|
|
116
|
+
*/
|
|
117
|
+
for (let column in model.schema) {
|
|
118
|
+
if (column in this.data || column === model.IDColumn)
|
|
119
|
+
continue;
|
|
120
|
+
const field = model.schema[column];
|
|
121
|
+
if (ForeignInfo.default.is(field)) {
|
|
122
|
+
// if foreign key is not optional or nullable, throw error
|
|
123
|
+
if (ForeignInfo.default.isSchema(field) && !(field.meta.optional || field.meta.nullable)) {
|
|
124
|
+
this.errors.push(new XansqlError.default({
|
|
125
|
+
message: `Foreign key column ${model.table}.${column} is required. Cannot create record without it.`,
|
|
126
|
+
model: model.table,
|
|
127
|
+
column: column
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
this.data[column] = ValueFormatter.default.toSql(model, column, null);
|
|
133
|
+
}
|
|
134
|
+
// generate sql
|
|
135
|
+
// const keys = Object.keys(this.data)
|
|
136
|
+
// let sql = `(${keys.join(", ")}) VALUES (${keys.map(k => this.data[k]).join(", ")})`
|
|
137
|
+
this.values.push({
|
|
138
|
+
// sql,
|
|
139
|
+
relations: this.relations,
|
|
140
|
+
data: this.data,
|
|
141
|
+
files: this.files
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}exports.default=CreateDataArgs;//# sourceMappingURL=CreateDataArgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateDataArgs.js","sources":["../../../../src/model/Executer/Create/CreateDataArgs.ts"],"sourcesContent":["import Model from \"../..\"\nimport Foreign, { ForeignInfoType } from \"../../../core/classes/ForeignInfo\"\nimport XansqlError from \"../../../core/XansqlError\"\nimport XqlDate from \"../../../Types/fields/Date\"\nimport { isArray, isNumber, isObject } from \"../../../utils\"\nimport ValueFormatter from \"../../include/ValueFormatter\"\nimport { DataArgsType } from \"../../type\"\n\n\ntype DataObject = { [column: string]: any }\ntype RelationObject = {\n [column: string]: {\n data: DataArgsType[],\n foreign: ForeignInfoType\n }\n}\n\ntype Files = {\n [column: string]: File\n}\ntype DataValue = {\n relations: RelationObject\n data: DataObject,\n files: Files\n}\n\nclass CreateDataArgs {\n\n /**\n * Generate SQL for data\n * For create mode: (col1, col2, col3) VALUES (val1, val2, val3)\n * For update mode: col1 = val1, col2 = val2, col3 = val3\n */\n private data: DataObject = {}\n\n private files: Files = {}\n\n /**\n * Get data object\n * format: { col1: val1, col2: val2, col3: val3 }\n */\n private relations: RelationObject = {}\n\n /**\n * Get stack of data and relations for nested create or update\n * format: [{ data: { col1: val1, col2: val2 }, relations: { relation1: data1 }, sql: '(col1, col2) VALUES (val1, val2)' }, ...]\n */\n readonly values: DataValue[] = []\n\n private errors: XansqlError[] = []\n\n\n constructor(model: Model, data: DataArgsType | DataArgsType[]) {\n\n if (Array.isArray(data)) {\n for (let item of data) {\n if (!isObject(item)) {\n throw new XansqlError({\n message: `Invalid data item for model ${model.table}. Expected object, got ${typeof item}`,\n model: model.table\n });\n }\n const dataArgs = new CreateDataArgs(model, item)\n this.values.push(...dataArgs.values)\n }\n } else {\n for (let column in data) {\n const field = model.schema[column]\n let value: any = data[column]\n\n try {\n\n if (Foreign.is(field)) {\n if (Foreign.isSchema(field)) {\n if (isNumber(value)) {\n this.data[column] = value\n } else {\n throw new XansqlError({\n message: `Invalid value for foreign key column ${model.table}.${column}. Expected number, got ${typeof value}`,\n model: model.table,\n column: column\n });\n }\n } else {\n // array of foreign keys\n if (isObject(value) || isArray(value)) {\n const foreign = Foreign.get(model, column)\n let rdatas = isObject(value) ? [value] : value\n\n if (rdatas.length === 0) {\n throw new XansqlError({\n message: `Relation data array for column ${model.table}.${column} cannot be empty.`,\n model: model.table,\n column: column\n });\n }\n\n this.relations[column] = {\n data: rdatas,\n foreign\n }\n } else {\n throw new XansqlError({\n message: `Invalid value for relation column ${model.table}.${column}. Expected object or array, got ${typeof value}`,\n model: model.table,\n column: column\n });\n }\n }\n } else {\n // check is the field is IDField or created_at or updated_at\n if (model.IDColumn === column || field instanceof XqlDate && (field.meta.update || field.meta.create)) {\n throw new XansqlError({\n message: `Cannot set value for ${model.table}.${column}. It is automatically managed.`,\n model: model.table,\n column: column\n });\n }\n if (value instanceof File) {\n this.files[column] = value\n this.data[column] = ''\n ValueFormatter.toSql(model, column, value) // for validation\n } else {\n this.data[column] = ValueFormatter.toSql(model, column, value)\n }\n }\n } catch (error) {\n if (error instanceof XansqlError) {\n this.errors.push(error);\n } else {\n throw error\n }\n }\n }\n\n if (this.errors.length > 0) {\n throw this.errors\n }\n\n /**\n * Auto add missing columns with null value for create mode\n * Auto add updated_at column with current timestamp for update mode\n * Skip foreign key columns which are not optional or nullable in create mode\n * Skip ID column in create mode\n * Skip created_at column in update mode\n * Skip updated_at column in create mode\n * Skip columns which are already set in data\n */\n for (let column in model.schema) {\n if (column in this.data || column === model.IDColumn) continue\n\n const field = model.schema[column]\n if (Foreign.is(field)) {\n // if foreign key is not optional or nullable, throw error\n if (Foreign.isSchema(field) && !(field.meta.optional || field.meta.nullable)) {\n this.errors.push(new XansqlError({\n message: `Foreign key column ${model.table}.${column} is required. Cannot create record without it.`,\n model: model.table,\n column: column\n }))\n }\n continue\n }\n this.data[column] = ValueFormatter.toSql(model, column, null)\n }\n\n // generate sql\n // const keys = Object.keys(this.data)\n // let sql = `(${keys.join(\", \")}) VALUES (${keys.map(k => this.data[k]).join(\", \")})`\n\n this.values.push({\n // sql,\n relations: this.relations,\n data: this.data,\n files: this.files\n })\n }\n }\n}\n\nexport default CreateDataArgs"],"names":["isObject","XansqlError","Foreign","isNumber","isArray","XqlDate","ValueFormatter"],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import Foreign from'../../../core/classes/ForeignInfo.mjs';import XansqlError from'../../../core/XansqlError.mjs';import XqlDate from'../../../Types/fields/Date.mjs';import {isObject,isNumber,isArray}from'../../../utils/index.mjs';import ValueFormatter from'../../include/ValueFormatter.mjs';class CreateDataArgs {
|
|
2
|
+
constructor(model, data) {
|
|
3
|
+
/**
|
|
4
|
+
* Generate SQL for data
|
|
5
|
+
* For create mode: (col1, col2, col3) VALUES (val1, val2, val3)
|
|
6
|
+
* For update mode: col1 = val1, col2 = val2, col3 = val3
|
|
7
|
+
*/
|
|
8
|
+
this.data = {};
|
|
9
|
+
this.files = {};
|
|
10
|
+
/**
|
|
11
|
+
* Get data object
|
|
12
|
+
* format: { col1: val1, col2: val2, col3: val3 }
|
|
13
|
+
*/
|
|
14
|
+
this.relations = {};
|
|
15
|
+
/**
|
|
16
|
+
* Get stack of data and relations for nested create or update
|
|
17
|
+
* format: [{ data: { col1: val1, col2: val2 }, relations: { relation1: data1 }, sql: '(col1, col2) VALUES (val1, val2)' }, ...]
|
|
18
|
+
*/
|
|
19
|
+
this.values = [];
|
|
20
|
+
this.errors = [];
|
|
21
|
+
if (Array.isArray(data)) {
|
|
22
|
+
for (let item of data) {
|
|
23
|
+
if (!isObject(item)) {
|
|
24
|
+
throw new XansqlError({
|
|
25
|
+
message: `Invalid data item for model ${model.table}. Expected object, got ${typeof item}`,
|
|
26
|
+
model: model.table
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const dataArgs = new CreateDataArgs(model, item);
|
|
30
|
+
this.values.push(...dataArgs.values);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
for (let column in data) {
|
|
35
|
+
const field = model.schema[column];
|
|
36
|
+
let value = data[column];
|
|
37
|
+
try {
|
|
38
|
+
if (Foreign.is(field)) {
|
|
39
|
+
if (Foreign.isSchema(field)) {
|
|
40
|
+
if (isNumber(value)) {
|
|
41
|
+
this.data[column] = value;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw new XansqlError({
|
|
45
|
+
message: `Invalid value for foreign key column ${model.table}.${column}. Expected number, got ${typeof value}`,
|
|
46
|
+
model: model.table,
|
|
47
|
+
column: column
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// array of foreign keys
|
|
53
|
+
if (isObject(value) || isArray(value)) {
|
|
54
|
+
const foreign = Foreign.get(model, column);
|
|
55
|
+
let rdatas = isObject(value) ? [value] : value;
|
|
56
|
+
if (rdatas.length === 0) {
|
|
57
|
+
throw new XansqlError({
|
|
58
|
+
message: `Relation data array for column ${model.table}.${column} cannot be empty.`,
|
|
59
|
+
model: model.table,
|
|
60
|
+
column: column
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
this.relations[column] = {
|
|
64
|
+
data: rdatas,
|
|
65
|
+
foreign
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
throw new XansqlError({
|
|
70
|
+
message: `Invalid value for relation column ${model.table}.${column}. Expected object or array, got ${typeof value}`,
|
|
71
|
+
model: model.table,
|
|
72
|
+
column: column
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// check is the field is IDField or created_at or updated_at
|
|
79
|
+
if (model.IDColumn === column || field instanceof XqlDate && (field.meta.update || field.meta.create)) {
|
|
80
|
+
throw new XansqlError({
|
|
81
|
+
message: `Cannot set value for ${model.table}.${column}. It is automatically managed.`,
|
|
82
|
+
model: model.table,
|
|
83
|
+
column: column
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (value instanceof File) {
|
|
87
|
+
this.files[column] = value;
|
|
88
|
+
this.data[column] = '';
|
|
89
|
+
ValueFormatter.toSql(model, column, value); // for validation
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.data[column] = ValueFormatter.toSql(model, column, value);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof XansqlError) {
|
|
98
|
+
this.errors.push(error);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (this.errors.length > 0) {
|
|
106
|
+
throw this.errors;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Auto add missing columns with null value for create mode
|
|
110
|
+
* Auto add updated_at column with current timestamp for update mode
|
|
111
|
+
* Skip foreign key columns which are not optional or nullable in create mode
|
|
112
|
+
* Skip ID column in create mode
|
|
113
|
+
* Skip created_at column in update mode
|
|
114
|
+
* Skip updated_at column in create mode
|
|
115
|
+
* Skip columns which are already set in data
|
|
116
|
+
*/
|
|
117
|
+
for (let column in model.schema) {
|
|
118
|
+
if (column in this.data || column === model.IDColumn)
|
|
119
|
+
continue;
|
|
120
|
+
const field = model.schema[column];
|
|
121
|
+
if (Foreign.is(field)) {
|
|
122
|
+
// if foreign key is not optional or nullable, throw error
|
|
123
|
+
if (Foreign.isSchema(field) && !(field.meta.optional || field.meta.nullable)) {
|
|
124
|
+
this.errors.push(new XansqlError({
|
|
125
|
+
message: `Foreign key column ${model.table}.${column} is required. Cannot create record without it.`,
|
|
126
|
+
model: model.table,
|
|
127
|
+
column: column
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
this.data[column] = ValueFormatter.toSql(model, column, null);
|
|
133
|
+
}
|
|
134
|
+
// generate sql
|
|
135
|
+
// const keys = Object.keys(this.data)
|
|
136
|
+
// let sql = `(${keys.join(", ")}) VALUES (${keys.map(k => this.data[k]).join(", ")})`
|
|
137
|
+
this.values.push({
|
|
138
|
+
// sql,
|
|
139
|
+
relations: this.relations,
|
|
140
|
+
data: this.data,
|
|
141
|
+
files: this.files
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}export{CreateDataArgs as default};//# sourceMappingURL=CreateDataArgs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateDataArgs.mjs","sources":["../../../../src/model/Executer/Create/CreateDataArgs.ts"],"sourcesContent":["import Model from \"../..\"\nimport Foreign, { ForeignInfoType } from \"../../../core/classes/ForeignInfo\"\nimport XansqlError from \"../../../core/XansqlError\"\nimport XqlDate from \"../../../Types/fields/Date\"\nimport { isArray, isNumber, isObject } from \"../../../utils\"\nimport ValueFormatter from \"../../include/ValueFormatter\"\nimport { DataArgsType } from \"../../type\"\n\n\ntype DataObject = { [column: string]: any }\ntype RelationObject = {\n [column: string]: {\n data: DataArgsType[],\n foreign: ForeignInfoType\n }\n}\n\ntype Files = {\n [column: string]: File\n}\ntype DataValue = {\n relations: RelationObject\n data: DataObject,\n files: Files\n}\n\nclass CreateDataArgs {\n\n /**\n * Generate SQL for data\n * For create mode: (col1, col2, col3) VALUES (val1, val2, val3)\n * For update mode: col1 = val1, col2 = val2, col3 = val3\n */\n private data: DataObject = {}\n\n private files: Files = {}\n\n /**\n * Get data object\n * format: { col1: val1, col2: val2, col3: val3 }\n */\n private relations: RelationObject = {}\n\n /**\n * Get stack of data and relations for nested create or update\n * format: [{ data: { col1: val1, col2: val2 }, relations: { relation1: data1 }, sql: '(col1, col2) VALUES (val1, val2)' }, ...]\n */\n readonly values: DataValue[] = []\n\n private errors: XansqlError[] = []\n\n\n constructor(model: Model, data: DataArgsType | DataArgsType[]) {\n\n if (Array.isArray(data)) {\n for (let item of data) {\n if (!isObject(item)) {\n throw new XansqlError({\n message: `Invalid data item for model ${model.table}. Expected object, got ${typeof item}`,\n model: model.table\n });\n }\n const dataArgs = new CreateDataArgs(model, item)\n this.values.push(...dataArgs.values)\n }\n } else {\n for (let column in data) {\n const field = model.schema[column]\n let value: any = data[column]\n\n try {\n\n if (Foreign.is(field)) {\n if (Foreign.isSchema(field)) {\n if (isNumber(value)) {\n this.data[column] = value\n } else {\n throw new XansqlError({\n message: `Invalid value for foreign key column ${model.table}.${column}. Expected number, got ${typeof value}`,\n model: model.table,\n column: column\n });\n }\n } else {\n // array of foreign keys\n if (isObject(value) || isArray(value)) {\n const foreign = Foreign.get(model, column)\n let rdatas = isObject(value) ? [value] : value\n\n if (rdatas.length === 0) {\n throw new XansqlError({\n message: `Relation data array for column ${model.table}.${column} cannot be empty.`,\n model: model.table,\n column: column\n });\n }\n\n this.relations[column] = {\n data: rdatas,\n foreign\n }\n } else {\n throw new XansqlError({\n message: `Invalid value for relation column ${model.table}.${column}. Expected object or array, got ${typeof value}`,\n model: model.table,\n column: column\n });\n }\n }\n } else {\n // check is the field is IDField or created_at or updated_at\n if (model.IDColumn === column || field instanceof XqlDate && (field.meta.update || field.meta.create)) {\n throw new XansqlError({\n message: `Cannot set value for ${model.table}.${column}. It is automatically managed.`,\n model: model.table,\n column: column\n });\n }\n if (value instanceof File) {\n this.files[column] = value\n this.data[column] = ''\n ValueFormatter.toSql(model, column, value) // for validation\n } else {\n this.data[column] = ValueFormatter.toSql(model, column, value)\n }\n }\n } catch (error) {\n if (error instanceof XansqlError) {\n this.errors.push(error);\n } else {\n throw error\n }\n }\n }\n\n if (this.errors.length > 0) {\n throw this.errors\n }\n\n /**\n * Auto add missing columns with null value for create mode\n * Auto add updated_at column with current timestamp for update mode\n * Skip foreign key columns which are not optional or nullable in create mode\n * Skip ID column in create mode\n * Skip created_at column in update mode\n * Skip updated_at column in create mode\n * Skip columns which are already set in data\n */\n for (let column in model.schema) {\n if (column in this.data || column === model.IDColumn) continue\n\n const field = model.schema[column]\n if (Foreign.is(field)) {\n // if foreign key is not optional or nullable, throw error\n if (Foreign.isSchema(field) && !(field.meta.optional || field.meta.nullable)) {\n this.errors.push(new XansqlError({\n message: `Foreign key column ${model.table}.${column} is required. Cannot create record without it.`,\n model: model.table,\n column: column\n }))\n }\n continue\n }\n this.data[column] = ValueFormatter.toSql(model, column, null)\n }\n\n // generate sql\n // const keys = Object.keys(this.data)\n // let sql = `(${keys.join(\", \")}) VALUES (${keys.map(k => this.data[k]).join(\", \")})`\n\n this.values.push({\n // sql,\n relations: this.relations,\n data: this.data,\n files: this.files\n })\n }\n }\n}\n\nexport default CreateDataArgs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var CreateDataArgs=require('./CreateDataArgs.js'),SelectArgs=require('../Find/SelectArgs.js'),chunker=require('../../../utils/chunker.js'),RelationExcuteArgs=require('../../Args/RelationExcuteArgs.js'),ExcuteMeta=require('../../../core/ExcuteMeta.js');class CreateExecuter {
|
|
2
|
+
constructor(model) {
|
|
3
|
+
this.model = model;
|
|
4
|
+
}
|
|
5
|
+
async execute(args) {
|
|
6
|
+
const xansql = this.model.xansql;
|
|
7
|
+
const model = this.model;
|
|
8
|
+
const createArgs = new CreateDataArgs.default(model, args.data);
|
|
9
|
+
const isRelation = args instanceof RelationExcuteArgs.default;
|
|
10
|
+
// only for validation
|
|
11
|
+
if (args.select)
|
|
12
|
+
new SelectArgs.default(model, args.select || {});
|
|
13
|
+
const insertIds = [];
|
|
14
|
+
let results = [];
|
|
15
|
+
for (let { chunk } of chunker.chunkArray(createArgs.values)) {
|
|
16
|
+
for (let arg of chunk) {
|
|
17
|
+
let insertId;
|
|
18
|
+
const fileColumns = Object.keys(arg.files);
|
|
19
|
+
const uploadedFileIds = [];
|
|
20
|
+
try {
|
|
21
|
+
if (fileColumns.length > 0) {
|
|
22
|
+
let executeId = undefined;
|
|
23
|
+
if (typeof window !== "undefined") {
|
|
24
|
+
executeId = ExcuteMeta.default.set({
|
|
25
|
+
model,
|
|
26
|
+
action: "UPLOAD_FILE",
|
|
27
|
+
modelType: isRelation ? "child" : "main",
|
|
28
|
+
args: arg
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
for (let file_col of fileColumns) {
|
|
32
|
+
const filemeta = await xansql.uploadFile(arg.files[file_col], executeId);
|
|
33
|
+
uploadedFileIds.push(filemeta.fileId);
|
|
34
|
+
arg.data[file_col] = `'${JSON.stringify(filemeta)}'`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
let executeId = undefined;
|
|
38
|
+
if (typeof window !== "undefined") {
|
|
39
|
+
executeId = ExcuteMeta.default.set({
|
|
40
|
+
model,
|
|
41
|
+
action: "INSERT",
|
|
42
|
+
modelType: isRelation ? "child" : "main",
|
|
43
|
+
args: arg
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const keys = Object.keys(arg.data);
|
|
47
|
+
const sql = `INSERT INTO ${model.table} (${keys.join(", ")}) VALUES (${keys.map(k => arg.data[k]).join(", ")})`;
|
|
48
|
+
const created = await xansql.execute(sql, executeId);
|
|
49
|
+
insertId = created.insertId;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (fileColumns.length > 0) {
|
|
53
|
+
let executeId = undefined;
|
|
54
|
+
if (typeof window !== "undefined") {
|
|
55
|
+
executeId = ExcuteMeta.default.set({
|
|
56
|
+
model,
|
|
57
|
+
action: "DELETE_FILE",
|
|
58
|
+
modelType: isRelation ? "child" : "main",
|
|
59
|
+
args: arg
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (let fileId of uploadedFileIds) {
|
|
63
|
+
try {
|
|
64
|
+
await xansql.deleteFile(fileId, executeId);
|
|
65
|
+
}
|
|
66
|
+
catch (error) { }
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (insertId) {
|
|
72
|
+
insertIds.push(insertId);
|
|
73
|
+
results.push({ [model.IDColumn]: insertId });
|
|
74
|
+
// execute relations
|
|
75
|
+
for (let rel_column in arg.relations) {
|
|
76
|
+
const relInfo = arg.relations[rel_column];
|
|
77
|
+
const foreign = relInfo.foreign;
|
|
78
|
+
const FModel = xansql.getModel(foreign.table);
|
|
79
|
+
for (let relData of relInfo.data) {
|
|
80
|
+
const fdata = Object.assign(Object.assign({}, relData), { [foreign.column]: insertId });
|
|
81
|
+
const rargs = new RelationExcuteArgs.default({
|
|
82
|
+
data: fdata
|
|
83
|
+
});
|
|
84
|
+
await FModel.create(rargs);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (args.select) {
|
|
91
|
+
results = await model.find({
|
|
92
|
+
where: {
|
|
93
|
+
[model.IDColumn]: insertIds.length === 1 ? insertIds[0] : { in: insertIds }
|
|
94
|
+
},
|
|
95
|
+
limit: "all",
|
|
96
|
+
select: args.select
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return results;
|
|
100
|
+
}
|
|
101
|
+
}exports.default=CreateExecuter;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/model/Executer/Create/index.ts"],"sourcesContent":["import Model from \"../..\"\nimport CreateDataArgs from \"./CreateDataArgs\"\nimport { CreateArgsType } from \"../../type\"\nimport SelectArgs from \"../Find/SelectArgs\"\nimport { chunkArray } from \"../../../utils/chunker\"\nimport RelationExecuteArgs from \"../../Args/RelationExcuteArgs\"\nimport ExecuteMeta from \"../../../core/ExcuteMeta\"\n\nclass CreateExecuter {\n model: Model\n constructor(model: Model) {\n this.model = model\n }\n async execute(args: CreateArgsType) {\n const xansql = this.model.xansql\n const model = this.model\n const createArgs = new CreateDataArgs(model, args.data)\n const isRelation = args instanceof RelationExecuteArgs\n\n // only for validation\n if (args.select) new SelectArgs(model, args.select || {})\n\n const insertIds = []\n let results = []\n\n for (let { chunk } of chunkArray(createArgs.values)) {\n for (let arg of chunk) {\n let insertId\n const fileColumns = Object.keys(arg.files)\n const uploadedFileIds: string[] = []\n try {\n\n if (fileColumns.length > 0) {\n let executeId = undefined;\n if (typeof window !== \"undefined\") {\n executeId = ExecuteMeta.set({\n model,\n action: \"UPLOAD_FILE\",\n modelType: isRelation ? \"child\" : \"main\",\n args: arg\n });\n }\n for (let file_col of fileColumns) {\n const filemeta = await xansql.uploadFile(arg.files[file_col], executeId)\n uploadedFileIds.push(filemeta.fileId)\n arg.data[file_col] = `'${JSON.stringify(filemeta)}'`\n }\n }\n let executeId = undefined;\n if (typeof window !== \"undefined\") {\n executeId = ExecuteMeta.set({\n model,\n action: \"INSERT\",\n modelType: isRelation ? \"child\" : \"main\",\n args: arg\n });\n }\n const keys = Object.keys(arg.data)\n const sql = `INSERT INTO ${model.table} (${keys.join(\", \")}) VALUES (${keys.map(k => arg.data[k]).join(\", \")})`\n const created = await xansql.execute(sql, executeId)\n insertId = created.insertId\n } catch (error: any) {\n if (fileColumns.length > 0) {\n let executeId = undefined;\n if (typeof window !== \"undefined\") {\n executeId = ExecuteMeta.set({\n model,\n action: \"DELETE_FILE\",\n modelType: isRelation ? \"child\" : \"main\",\n args: arg\n });\n }\n for (let fileId of uploadedFileIds) {\n try {\n await xansql.deleteFile(fileId, executeId)\n } catch (error) { }\n }\n throw error\n }\n }\n if (insertId) {\n insertIds.push(insertId)\n results.push({ [model.IDColumn]: insertId })\n\n // execute relations\n for (let rel_column in arg.relations) {\n const relInfo = arg.relations[rel_column]\n const foreign = relInfo.foreign\n const FModel = xansql.getModel(foreign.table)\n for (let relData of relInfo.data) {\n const fdata = {\n ...relData,\n [foreign.column]: insertId\n }\n const rargs = new RelationExecuteArgs({\n data: fdata\n })\n await FModel.create(rargs as any)\n }\n }\n }\n }\n }\n\n if (args.select) {\n results = await model.find({\n where: {\n [model.IDColumn]: insertIds.length === 1 ? insertIds[0] : { in: insertIds }\n },\n limit: \"all\",\n select: args.select\n })\n }\n\n return results\n }\n\n}\n\nexport default CreateExecuter"],"names":["CreateDataArgs","RelationExecuteArgs","SelectArgs","chunkArray","ExecuteMeta"],"mappings":"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"}
|