@deterministic-code/datasources 0.0.0-stage → 0.1.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/package.json +16 -4
- package/src/ArrayReader.ts +32 -0
- package/src/BatchCommandIBulkWriteStrategy.ts +228 -0
- package/src/BuiltRepository.ts +17 -0
- package/src/BulkCRUDRepository.ts +84 -0
- package/src/BulkCommand.ts +6 -0
- package/src/BulkWriteEnrichment.ts +19 -0
- package/src/CRUDRepository.ts +264 -0
- package/src/CRUDRepositoryBuilder.ts +53 -0
- package/src/CRUDRepositoryOptions.ts +8 -0
- package/src/CRUDRepositoryStatements.ts +43 -0
- package/src/CascadeDeleteEnrichmentStrategy.ts +51 -0
- package/src/CascadeDeleteUpdateEnrichmentStrategy.ts +28 -0
- package/src/CommandMiddlewareHost.ts +113 -0
- package/src/ConsoleCommandMiddleware.ts +64 -0
- package/src/CreateEnrichmentStrategy.ts +82 -0
- package/src/Datasource.ts +152 -0
- package/src/DatasourceError.ts +6 -0
- package/src/DatasourceFactory.ts +86 -0
- package/src/DatasourceOptions.ts +1 -0
- package/src/DatasourceUrl.ts +37 -0
- package/src/DatasourceUrlParser.ts +188 -0
- package/src/DefaultCreateEnrichmentStrategy.ts +21 -0
- package/src/DefaultReadonlyEnrichmentStrategy.ts +164 -0
- package/src/DefaultUpdateEnrichmentStrategy.ts +40 -0
- package/src/DefaultWriteEnrichmentStrategy.ts +151 -0
- package/src/DeleteEnrichmentStrategy.ts +56 -0
- package/src/DriverLoader.ts +97 -0
- package/src/Enrichment.ts +15 -0
- package/src/EnrichmentPropertyType.ts +9 -0
- package/src/ExpectConsoleMiddleware.ts +47 -0
- package/src/FirstResultReader.ts +49 -0
- package/src/HashsetOptimizedReadonlyEnrichmentStrategy.ts +80 -0
- package/src/IBulkWriteStrategy.ts +13 -0
- package/src/ICRUDRepository.ts +13 -0
- package/src/ICRUDRepositoryFactory.ts +8 -0
- package/src/ICommand.ts +45 -0
- package/src/ICommandMiddleware.ts +20 -0
- package/src/IConnection.ts +13 -0
- package/src/IDatasource.ts +27 -0
- package/src/IDatasourceFactory.ts +6 -0
- package/src/IDriver.ts +24 -0
- package/src/IEnriched.ts +11 -0
- package/src/IReader.ts +8 -0
- package/src/IReadonlyEnrichmentStrategy.ts +19 -0
- package/src/IReadonlyRepository.ts +21 -0
- package/src/IRepository.ts +5 -0
- package/src/IRepositoryFactory.ts +8 -0
- package/src/IRepositoryTree.ts +5 -0
- package/src/IRepositoryTreeNode.ts +8 -0
- package/src/ITransaction.ts +9 -0
- package/src/IUnitOfWork.ts +5 -0
- package/src/IWriteEnrichmentStrategy.ts +8 -0
- package/src/Information.ts +5 -0
- package/src/IsolationLevel.ts +8 -0
- package/src/LazyWriteEnrichmentStrategy.ts +5 -0
- package/src/NestedToObjectEnrichmentStrategy.ts +33 -0
- package/src/Parameter.ts +8 -0
- package/src/ParameterDirection.ts +9 -0
- package/src/ProviderCatalog.ts +21 -0
- package/src/ProviderNotImplementedError.ts +9 -0
- package/src/ProviderNotInstalledError.ts +9 -0
- package/src/ReadonlyRepository.ts +276 -0
- package/src/ReadonlyRepositoryBuilder.ts +53 -0
- package/src/ReadonlyRepositoryMappingOptions.ts +15 -0
- package/src/ReadonlyRepositoryStatements.ts +13 -0
- package/src/RepositoryAccess.ts +14 -0
- package/src/RepositoryFactory.ts +115 -0
- package/src/RepositoryNotRegisteredError.ts +9 -0
- package/src/RepositoryTree.ts +6 -0
- package/src/RepositoryTreeNode.ts +11 -0
- package/src/Response.ts +15 -0
- package/src/Row.ts +3 -0
- package/src/SingleCommandIBulkWriteStrategy.ts +35 -0
- package/src/StatementMappers.ts +110 -0
- package/src/StoredEnrichment.ts +25 -0
- package/src/StoredProcedureBulkWriteStrategy.ts +164 -0
- package/src/StreamingReader.ts +64 -0
- package/src/UnitOfWorkTransaction.ts +50 -0
- package/src/UpdateEnrichmentStrategy.ts +97 -0
- package/src/WriteMode.ts +1 -0
- package/src/builders/Field.ts +6 -0
- package/src/builders/Scalar.ts +1 -0
- package/src/builders/index.ts +2 -0
- package/src/collectAsync.ts +7 -0
- package/src/converters/Cell.ts +10 -0
- package/src/converters/ChangeCasingConverter.ts +59 -0
- package/src/converters/Constructable.ts +1 -0
- package/src/converters/MetaDataRowTypeConverter.ts +80 -0
- package/src/converters/PluralizerConverter.ts +67 -0
- package/src/converters/RegexConverter.ts +14 -0
- package/src/converters/ReplaceConverter.ts +6 -0
- package/src/converters/RowTypeConverter.ts +33 -0
- package/src/converters/ToLowerCaseConverter.ts +4 -0
- package/src/converters/ToUpperCaseConverter.ts +4 -0
- package/src/converters/TypeConverter.ts +6 -0
- package/src/createCRUDRepositoryOptions.ts +21 -0
- package/src/createReadonlyRepositoryMappingOptions.ts +26 -0
- package/src/dotEnv.ts +16 -0
- package/src/index.ts +222 -0
- package/src/mappers/ChangeCasingMapper.ts +15 -0
- package/src/mappers/DictionaryMapper.ts +16 -0
- package/src/mappers/FlatToNestedMapper.ts +127 -0
- package/src/mappers/IFlatToNestedMapper.ts +7 -0
- package/src/mappers/IMapper.ts +4 -0
- package/src/mappers/IdentityMapper.ts +6 -0
- package/src/mappers/PluralizerMapper.ts +9 -0
- package/src/mappers/RowTypeMapper.ts +13 -0
- package/src/mappers/TransformConverterMapper.ts +11 -0
- package/src/mappers/TransformMapper.ts +8 -0
- package/src/mappers/TypeMap.ts +10 -0
- package/src/mappers/TypeMapGroup.ts +6 -0
- package/src/mocks/index.ts +9 -0
- package/src/mocks/mock-command.ts +66 -0
- package/src/mocks/mock-connection.ts +57 -0
- package/src/mocks/mock-datasource.ts +65 -0
- package/src/mocks/mock-driver.ts +27 -0
- package/src/mocks/mock-reader.ts +38 -0
- package/src/mocks/mock-repository.ts +91 -0
- package/src/mocks/mock-select-statement.ts +17 -0
- package/src/mocks/mock-transaction.ts +31 -0
- package/src/mocks/mock-where.ts +13 -0
- package/src/parametersToRecord.ts +11 -0
- package/src/readerToAsyncIterable.ts +11 -0
- package/src/splitStatements.ts +99 -0
- package/src/statementParameters.ts +22 -0
- package/src/statementUsesParameter.ts +4 -0
- package/src/statements/Aggregate.ts +9 -0
- package/src/statements/ArrayExpression.ts +5 -0
- package/src/statements/BulkDeleteStatement.ts +18 -0
- package/src/statements/BulkDeleteStatementTextRenderer.ts +16 -0
- package/src/statements/BulkInsertStatement.ts +37 -0
- package/src/statements/BulkInsertStatementTextRenderer.ts +10 -0
- package/src/statements/BulkUpdateStatement.ts +24 -0
- package/src/statements/BulkUpdateStatementTextRenderer.ts +29 -0
- package/src/statements/CheckConstraint.ts +9 -0
- package/src/statements/Cmp.ts +12 -0
- package/src/statements/Column.ts +10 -0
- package/src/statements/ColumnDefault.ts +6 -0
- package/src/statements/Condition.ts +3 -0
- package/src/statements/ConditionRenderer.ts +17 -0
- package/src/statements/CreateIndexStatement.ts +18 -0
- package/src/statements/CreateIndexStatementTextRenderer.ts +11 -0
- package/src/statements/CreateTableStatement.ts +18 -0
- package/src/statements/CreateTableStatementTextRenderer.ts +92 -0
- package/src/statements/DefaultStatementTextRenderer.ts +9 -0
- package/src/statements/DeleteStatement.ts +15 -0
- package/src/statements/DeleteStatementTextRenderer.ts +12 -0
- package/src/statements/ExecuteStoredProcedureStatement.ts +15 -0
- package/src/statements/ExecuteStoredProcedureStatementTextRenderer.ts +15 -0
- package/src/statements/ExpressionEvaluator.ts +166 -0
- package/src/statements/ExpressionRenderer.ts +161 -0
- package/src/statements/ForeignKey.ts +23 -0
- package/src/statements/IBulkDeleteStatement.ts +3 -0
- package/src/statements/IBulkInsertStatement.ts +3 -0
- package/src/statements/IBulkUpdateStatement.ts +3 -0
- package/src/statements/ICondition.ts +5 -0
- package/src/statements/IConditionVisitor.ts +7 -0
- package/src/statements/ICreateIndexStatement.ts +3 -0
- package/src/statements/ICreateTableStatement.ts +3 -0
- package/src/statements/IDeleteStatement.ts +6 -0
- package/src/statements/IExecuteStoredProcedureStatement.ts +3 -0
- package/src/statements/IExpression.ts +1 -0
- package/src/statements/IInsertStatement.ts +3 -0
- package/src/statements/IReturnStatement.ts +3 -0
- package/src/statements/ISelectStatement.ts +6 -0
- package/src/statements/IStatement.ts +5 -0
- package/src/statements/IStatementVisitor.ts +27 -0
- package/src/statements/ITableConstraint.ts +6 -0
- package/src/statements/IUpdateStatement.ts +6 -0
- package/src/statements/IWhere.ts +7 -0
- package/src/statements/Identifier.ts +5 -0
- package/src/statements/InsertStatement.ts +15 -0
- package/src/statements/InsertStatementTextRenderer.ts +7 -0
- package/src/statements/Join.ts +26 -0
- package/src/statements/Literal.ts +6 -0
- package/src/statements/Native.ts +5 -0
- package/src/statements/NotNull.ts +3 -0
- package/src/statements/Operator.ts +234 -0
- package/src/statements/OrderBy.ts +19 -0
- package/src/statements/PrimaryKey.ts +9 -0
- package/src/statements/ReturnStatement.ts +15 -0
- package/src/statements/ReturnStatementTextRenderer.ts +15 -0
- package/src/statements/SelectInsertedIdStatement.ts +11 -0
- package/src/statements/SelectInsertedIdStatementTextRenderer.ts +7 -0
- package/src/statements/SelectStatement.ts +34 -0
- package/src/statements/SelectStatementOptions.ts +16 -0
- package/src/statements/SelectStatementTextRenderer.ts +71 -0
- package/src/statements/StatementEvaluator.ts +5 -0
- package/src/statements/StatementParser.ts +461 -0
- package/src/statements/StatementRenderer.ts +120 -0
- package/src/statements/StatementTextRenderer.ts +60 -0
- package/src/statements/Subquery.ts +6 -0
- package/src/statements/UniqueConstraint.ts +9 -0
- package/src/statements/UpdateStatement.ts +34 -0
- package/src/statements/UpdateStatementTextRenderer.ts +63 -0
- package/src/statements/Where.ts +250 -0
- package/src/statements/WhereText.ts +10 -0
- package/src/statements/index.ts +75 -0
- package/src/stubs/StubCommand.ts +30 -0
- package/src/stubs/StubConnection.ts +21 -0
- package/src/stubs/StubDatasource.ts +60 -0
- package/src/stubs/StubReader.ts +25 -0
- package/src/stubs/StubRepository.ts +42 -0
- package/src/stubs/StubTransaction.ts +17 -0
- package/src/stubs/createStubDatasource.ts +4 -0
- package/src/stubs/index.ts +7 -0
- package/src/stubs/notImplemented.ts +5 -0
- package/README.md +0 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Field } from "../builders/Field.ts";
|
|
2
|
+
import type { IInsertStatement } from "./IInsertStatement.ts";
|
|
3
|
+
import type { IStatementVisitor } from "./IStatementVisitor.ts";
|
|
4
|
+
|
|
5
|
+
export class InsertStatement implements IInsertStatement {
|
|
6
|
+
readonly table: string;
|
|
7
|
+
readonly fields: Field[];
|
|
8
|
+
|
|
9
|
+
constructor(table: string, fields: Field[]) {
|
|
10
|
+
this.table = table;
|
|
11
|
+
this.fields = fields;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
accept = (visitor: IStatementVisitor): string => visitor.visit(this);
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InsertStatement } from "./InsertStatement.ts";
|
|
2
|
+
|
|
3
|
+
export class InsertStatementTextRenderer {
|
|
4
|
+
render(statement: InsertStatement): string {
|
|
5
|
+
return `INSERT INTO ${statement.table} (${statement.fields.map((field) => field.name).join(", ")}) VALUES (${statement.fields.map((field) => `$${field.name}`).join(", ")})`;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Identifier } from "./Identifier.ts";
|
|
2
|
+
import type { IExpression } from "./IExpression.ts";
|
|
3
|
+
import { Operator } from "./Operator.ts";
|
|
4
|
+
|
|
5
|
+
export type JoinKind = "inner" | "left" | "right" | "full" | "cross";
|
|
6
|
+
|
|
7
|
+
export type Join = {
|
|
8
|
+
kind: JoinKind;
|
|
9
|
+
table: string;
|
|
10
|
+
on?: IExpression;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const equality = (left: string, right: string): IExpression =>
|
|
14
|
+
new Operator.Equals(new Identifier(left), new Identifier(right));
|
|
15
|
+
|
|
16
|
+
export const Join = {
|
|
17
|
+
inner: (table: string, left: string, right: string): Join =>
|
|
18
|
+
({ kind: "inner", table, on: equality(left, right) }),
|
|
19
|
+
left: (table: string, left: string, right: string): Join =>
|
|
20
|
+
({ kind: "left", table, on: equality(left, right) }),
|
|
21
|
+
right: (table: string, left: string, right: string): Join =>
|
|
22
|
+
({ kind: "right", table, on: equality(left, right) }),
|
|
23
|
+
full: (table: string, left: string, right: string): Join =>
|
|
24
|
+
({ kind: "full", table, on: equality(left, right) }),
|
|
25
|
+
cross: (table: string): Join => ({ kind: "cross", table }),
|
|
26
|
+
};
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { Cell } from "../converters/Cell.ts";
|
|
2
|
+
import { ArrayExpression } from "./ArrayExpression.ts";
|
|
3
|
+
import { Condition } from "./Condition.ts";
|
|
4
|
+
import { Identifier } from "./Identifier.ts";
|
|
5
|
+
import type { IExpression } from "./IExpression.ts";
|
|
6
|
+
import { Literal } from "./Literal.ts";
|
|
7
|
+
|
|
8
|
+
const pair = (
|
|
9
|
+
left: string | IExpression,
|
|
10
|
+
right: IExpression | Cell,
|
|
11
|
+
): [IExpression, IExpression] =>
|
|
12
|
+
typeof left === "string"
|
|
13
|
+
? [new Identifier(left), new Literal(right as Cell)]
|
|
14
|
+
: [left, right as IExpression];
|
|
15
|
+
|
|
16
|
+
export abstract class Operator extends Condition {}
|
|
17
|
+
|
|
18
|
+
export namespace Operator {
|
|
19
|
+
export class Equals extends Operator {
|
|
20
|
+
readonly left: IExpression;
|
|
21
|
+
readonly right: IExpression;
|
|
22
|
+
constructor(field: string, value: Cell);
|
|
23
|
+
constructor(left: IExpression, right: IExpression);
|
|
24
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
25
|
+
super();
|
|
26
|
+
[this.left, this.right] = pair(left, right);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class NotEquals extends Operator {
|
|
31
|
+
readonly left: IExpression;
|
|
32
|
+
readonly right: IExpression;
|
|
33
|
+
constructor(field: string, value: Cell);
|
|
34
|
+
constructor(left: IExpression, right: IExpression);
|
|
35
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
36
|
+
super();
|
|
37
|
+
[this.left, this.right] = pair(left, right);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class GreaterThan extends Operator {
|
|
42
|
+
readonly left: IExpression;
|
|
43
|
+
readonly right: IExpression;
|
|
44
|
+
constructor(field: string, value: Cell);
|
|
45
|
+
constructor(left: IExpression, right: IExpression);
|
|
46
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
47
|
+
super();
|
|
48
|
+
[this.left, this.right] = pair(left, right);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class LessThan extends Operator {
|
|
53
|
+
readonly left: IExpression;
|
|
54
|
+
readonly right: IExpression;
|
|
55
|
+
constructor(field: string, value: Cell);
|
|
56
|
+
constructor(left: IExpression, right: IExpression);
|
|
57
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
58
|
+
super();
|
|
59
|
+
[this.left, this.right] = pair(left, right);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class GreaterThanOrEqual extends Operator {
|
|
64
|
+
readonly left: IExpression;
|
|
65
|
+
readonly right: IExpression;
|
|
66
|
+
constructor(field: string, value: Cell);
|
|
67
|
+
constructor(left: IExpression, right: IExpression);
|
|
68
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
69
|
+
super();
|
|
70
|
+
[this.left, this.right] = pair(left, right);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class LessThanOrEqual extends Operator {
|
|
75
|
+
readonly left: IExpression;
|
|
76
|
+
readonly right: IExpression;
|
|
77
|
+
constructor(field: string, value: Cell);
|
|
78
|
+
constructor(left: IExpression, right: IExpression);
|
|
79
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
80
|
+
super();
|
|
81
|
+
[this.left, this.right] = pair(left, right);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export class And extends Operator {
|
|
86
|
+
constructor(
|
|
87
|
+
readonly left: IExpression,
|
|
88
|
+
readonly right: IExpression,
|
|
89
|
+
) {
|
|
90
|
+
super();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export class Or extends Operator {
|
|
95
|
+
constructor(
|
|
96
|
+
readonly left: IExpression,
|
|
97
|
+
readonly right: IExpression,
|
|
98
|
+
) {
|
|
99
|
+
super();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class In extends Operator {
|
|
104
|
+
readonly left: IExpression;
|
|
105
|
+
readonly right: IExpression;
|
|
106
|
+
constructor(field: string, values: Cell[]);
|
|
107
|
+
constructor(left: IExpression, right: IExpression);
|
|
108
|
+
constructor(left: string | IExpression, right: Cell[] | IExpression) {
|
|
109
|
+
super();
|
|
110
|
+
if (typeof left === "string") {
|
|
111
|
+
this.left = new Identifier(left);
|
|
112
|
+
this.right = new ArrayExpression(
|
|
113
|
+
(right as Cell[]).map((value) => new Literal(value)),
|
|
114
|
+
);
|
|
115
|
+
} else {
|
|
116
|
+
this.left = left;
|
|
117
|
+
this.right = right as IExpression;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* v8 ignore next 6 */
|
|
123
|
+
export class Not extends Operator {
|
|
124
|
+
readonly argument: IExpression;
|
|
125
|
+
constructor(argument: IExpression) {
|
|
126
|
+
super();
|
|
127
|
+
this.argument = argument;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export class IsNull extends Operator {
|
|
132
|
+
readonly argument: IExpression;
|
|
133
|
+
constructor(argument: IExpression) {
|
|
134
|
+
super();
|
|
135
|
+
this.argument = argument;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export class IsNotNull extends Operator {
|
|
140
|
+
readonly argument: IExpression;
|
|
141
|
+
constructor(argument: IExpression) {
|
|
142
|
+
super();
|
|
143
|
+
this.argument = argument;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class Like extends Operator {
|
|
148
|
+
readonly left: IExpression;
|
|
149
|
+
readonly right: IExpression;
|
|
150
|
+
constructor(field: string, value: Cell);
|
|
151
|
+
constructor(left: IExpression, right: IExpression);
|
|
152
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
153
|
+
super();
|
|
154
|
+
[this.left, this.right] = pair(left, right);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export class NotLike extends Operator {
|
|
159
|
+
readonly left: IExpression;
|
|
160
|
+
readonly right: IExpression;
|
|
161
|
+
constructor(field: string, value: Cell);
|
|
162
|
+
constructor(left: IExpression, right: IExpression);
|
|
163
|
+
constructor(left: string | IExpression, right: IExpression | Cell) {
|
|
164
|
+
super();
|
|
165
|
+
[this.left, this.right] = pair(left, right);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export class Between extends Operator {
|
|
170
|
+
readonly value: IExpression;
|
|
171
|
+
readonly low: IExpression;
|
|
172
|
+
readonly high: IExpression;
|
|
173
|
+
constructor(field: string, low: Cell, high: Cell);
|
|
174
|
+
constructor(value: IExpression, low: IExpression, high: IExpression);
|
|
175
|
+
constructor(value: string | IExpression, low: IExpression | Cell, high: IExpression | Cell) {
|
|
176
|
+
super();
|
|
177
|
+
if (typeof value === "string") {
|
|
178
|
+
this.value = new Identifier(value);
|
|
179
|
+
this.low = new Literal(low as Cell);
|
|
180
|
+
this.high = new Literal(high as Cell);
|
|
181
|
+
} else {
|
|
182
|
+
this.value = value;
|
|
183
|
+
this.low = low as IExpression;
|
|
184
|
+
this.high = high as IExpression;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class NotBetween extends Operator {
|
|
190
|
+
readonly value: IExpression;
|
|
191
|
+
readonly low: IExpression;
|
|
192
|
+
readonly high: IExpression;
|
|
193
|
+
constructor(field: string, low: Cell, high: Cell);
|
|
194
|
+
constructor(value: IExpression, low: IExpression, high: IExpression);
|
|
195
|
+
constructor(value: string | IExpression, low: IExpression | Cell, high: IExpression | Cell) {
|
|
196
|
+
super();
|
|
197
|
+
if (typeof value === "string") {
|
|
198
|
+
this.value = new Identifier(value);
|
|
199
|
+
this.low = new Literal(low as Cell);
|
|
200
|
+
this.high = new Literal(high as Cell);
|
|
201
|
+
} else {
|
|
202
|
+
this.value = value;
|
|
203
|
+
this.low = low as IExpression;
|
|
204
|
+
this.high = high as IExpression;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export class NotIn extends Operator {
|
|
210
|
+
readonly left: IExpression;
|
|
211
|
+
readonly right: IExpression;
|
|
212
|
+
constructor(field: string, values: Cell[]);
|
|
213
|
+
constructor(left: IExpression, right: IExpression);
|
|
214
|
+
constructor(left: string | IExpression, right: Cell[] | IExpression) {
|
|
215
|
+
super();
|
|
216
|
+
if (typeof left === "string") {
|
|
217
|
+
this.left = new Identifier(left);
|
|
218
|
+
this.right = new ArrayExpression((right as Cell[]).map((value) => new Literal(value)));
|
|
219
|
+
} else {
|
|
220
|
+
this.left = left;
|
|
221
|
+
this.right = right as IExpression;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* v8 ignore next */
|
|
227
|
+
export class Exists extends Operator {
|
|
228
|
+
readonly argument: IExpression;
|
|
229
|
+
constructor(argument: IExpression) {
|
|
230
|
+
super();
|
|
231
|
+
this.argument = argument;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type SortDirection = "asc" | "desc";
|
|
2
|
+
|
|
3
|
+
export type OrderBy = {
|
|
4
|
+
column: string;
|
|
5
|
+
direction: SortDirection;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const directionSql: Record<SortDirection, string> = {
|
|
9
|
+
asc: "ASC",
|
|
10
|
+
desc: "DESC",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const OrderBy = {
|
|
14
|
+
asc: (column: string): OrderBy => ({ column, direction: "asc" }),
|
|
15
|
+
desc: (column: string): OrderBy => ({ column, direction: "desc" }),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const orderText = (order: OrderBy): string =>
|
|
19
|
+
`${order.column} ${directionSql[order.direction]}`;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Parameter } from "../Parameter.ts";
|
|
2
|
+
import type { IReturnStatement } from "./IReturnStatement.ts";
|
|
3
|
+
import type { IStatementVisitor } from "./IStatementVisitor.ts";
|
|
4
|
+
|
|
5
|
+
export class ReturnStatement implements IReturnStatement {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly parameters: Parameter[];
|
|
8
|
+
|
|
9
|
+
constructor(name: string, parameters: Parameter[]) {
|
|
10
|
+
this.name = name;
|
|
11
|
+
this.parameters = parameters;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
accept = (visitor: IStatementVisitor): string => visitor.visit(this);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ParameterDirection } from "../ParameterDirection.ts";
|
|
2
|
+
import type { Parameter } from "../Parameter.ts";
|
|
3
|
+
import type { ReturnStatement } from "./ReturnStatement.ts";
|
|
4
|
+
|
|
5
|
+
const args = (parameters: Parameter[]): string =>
|
|
6
|
+
parameters
|
|
7
|
+
.filter((parameter) => parameter.direction !== ParameterDirection.ReturnValue)
|
|
8
|
+
.map((parameter) => `$${parameter.name}`)
|
|
9
|
+
.join(", ");
|
|
10
|
+
|
|
11
|
+
export class ReturnStatementTextRenderer {
|
|
12
|
+
render(statement: ReturnStatement): string {
|
|
13
|
+
return `SELECT ${statement.name}(${args(statement.parameters)})`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IStatement } from "./IStatement.ts";
|
|
2
|
+
import type { IStatementVisitor } from "./IStatementVisitor.ts";
|
|
3
|
+
|
|
4
|
+
export class SelectInsertedIdStatement implements IStatement {
|
|
5
|
+
constructor(
|
|
6
|
+
readonly table: string,
|
|
7
|
+
readonly column: string,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
accept = (visitor: IStatementVisitor): string => visitor.visit(this);
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SelectInsertedIdStatement } from "./SelectInsertedIdStatement.ts";
|
|
2
|
+
|
|
3
|
+
export class SelectInsertedIdStatementTextRenderer {
|
|
4
|
+
render(_statement: SelectInsertedIdStatement): string {
|
|
5
|
+
throw new Error("provider must implement SelectInsertIdStatement");
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ISelectStatement } from "./ISelectStatement.ts";
|
|
2
|
+
import type { IStatementVisitor } from "./IStatementVisitor.ts";
|
|
3
|
+
import type { IWhere } from "./IWhere.ts";
|
|
4
|
+
import type { Join } from "./Join.ts";
|
|
5
|
+
import type { OrderBy } from "./OrderBy.ts";
|
|
6
|
+
import type { SelectStatementOptions } from "./SelectStatementOptions.ts";
|
|
7
|
+
|
|
8
|
+
export class SelectStatement implements ISelectStatement {
|
|
9
|
+
readonly where?: IWhere;
|
|
10
|
+
readonly distinct: boolean;
|
|
11
|
+
readonly table?: string;
|
|
12
|
+
readonly fields: string[];
|
|
13
|
+
readonly joins: Join[];
|
|
14
|
+
readonly groupBy: string[];
|
|
15
|
+
readonly having?: IWhere;
|
|
16
|
+
readonly orderBy: OrderBy[];
|
|
17
|
+
readonly limit?: number;
|
|
18
|
+
readonly offset?: number;
|
|
19
|
+
|
|
20
|
+
constructor(options: SelectStatementOptions) {
|
|
21
|
+
this.where = options.where;
|
|
22
|
+
this.distinct = options.distinct ?? false;
|
|
23
|
+
this.table = options.table;
|
|
24
|
+
this.fields = options.fields ?? [];
|
|
25
|
+
this.joins = options.joins ?? [];
|
|
26
|
+
this.groupBy = options.groupBy ?? [];
|
|
27
|
+
this.having = options.having;
|
|
28
|
+
this.orderBy = options.orderBy ?? [];
|
|
29
|
+
this.limit = options.limit;
|
|
30
|
+
this.offset = options.offset;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
accept = (visitor: IStatementVisitor): string => visitor.visit(this);
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Join } from "./Join.ts";
|
|
2
|
+
import type { IWhere } from "./IWhere.ts";
|
|
3
|
+
import type { OrderBy } from "./OrderBy.ts";
|
|
4
|
+
|
|
5
|
+
export type SelectStatementOptions = {
|
|
6
|
+
table?: string;
|
|
7
|
+
fields?: string[];
|
|
8
|
+
distinct?: boolean;
|
|
9
|
+
where?: IWhere;
|
|
10
|
+
joins?: Join[];
|
|
11
|
+
groupBy?: string[];
|
|
12
|
+
having?: IWhere;
|
|
13
|
+
orderBy?: OrderBy[];
|
|
14
|
+
limit?: number;
|
|
15
|
+
offset?: number;
|
|
16
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { IWhere } from "./IWhere.ts";
|
|
2
|
+
import type { Join, JoinKind } from "./Join.ts";
|
|
3
|
+
import { orderText, type OrderBy } from "./OrderBy.ts";
|
|
4
|
+
import type { SelectStatement } from "./SelectStatement.ts";
|
|
5
|
+
import type { StatementTextRenderer } from "./StatementTextRenderer.ts";
|
|
6
|
+
import { Where } from "./Where.ts";
|
|
7
|
+
|
|
8
|
+
export class SelectStatementTextRenderer {
|
|
9
|
+
constructor(private readonly text: StatementTextRenderer) {}
|
|
10
|
+
|
|
11
|
+
render(statement: SelectStatement): string {
|
|
12
|
+
return `SELECT ${statement.distinct ? "DISTINCT " : ""}${
|
|
13
|
+
statement.fields.length === 0 ? "*" : statement.fields.join(", ")
|
|
14
|
+
} FROM ${statement.table}${this.joinSql(statement.joins)}${this.whereSql(statement.where)}${this.groupSql(statement.groupBy)}${this.havingSql(statement.having)}${this.orderSql(statement.orderBy)}${this.limit(statement.limit)}${this.offset(statement.offset)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
protected whereSql(where?: IWhere): string {
|
|
18
|
+
return where ? ` WHERE ${this.text.render(where)}` : "";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected havingSql(having?: IWhere): string {
|
|
22
|
+
return having ? ` HAVING ${this.text.render(having)}` : "";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
protected groupSql(columns?: string[]): string {
|
|
26
|
+
return !columns || columns.length === 0 ? "" : ` GROUP BY ${columns.join(", ")}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected orderSql(order?: OrderBy[]): string {
|
|
30
|
+
return !order || order.length === 0 ? "" : ` ORDER BY ${order.map(orderText).join(", ")}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected limit(limit?: number): string {
|
|
34
|
+
return this.bound("LIMIT", limit);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected offset(offset?: number): string {
|
|
38
|
+
return this.bound("OFFSET", offset);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected bound(keyword: string, value?: number): string {
|
|
42
|
+
if (value === undefined) return "";
|
|
43
|
+
if (value < 0) throw new Error(`negative ${keyword.toLowerCase()}`);
|
|
44
|
+
return ` ${keyword} ${value}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected joinSql(joins?: Join[]): string {
|
|
48
|
+
if (!joins || joins.length === 0) return "";
|
|
49
|
+
return joins
|
|
50
|
+
.map((join) =>
|
|
51
|
+
join.kind === "cross"
|
|
52
|
+
? ` CROSS JOIN ${join.table}`
|
|
53
|
+
: ` ${this.keyword(join.kind)} ${join.table} ON ${this.text.render(
|
|
54
|
+
new Where(join.on ?? (() => { throw new Error("empty join"); })()),
|
|
55
|
+
)}`,
|
|
56
|
+
)
|
|
57
|
+
.join("");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected keyword(kind: JoinKind): string {
|
|
61
|
+
return (
|
|
62
|
+
{
|
|
63
|
+
inner: "INNER JOIN",
|
|
64
|
+
left: "LEFT JOIN",
|
|
65
|
+
right: "RIGHT JOIN",
|
|
66
|
+
full: "FULL JOIN",
|
|
67
|
+
cross: "CROSS JOIN",
|
|
68
|
+
} as Record<JoinKind, string>
|
|
69
|
+
)[kind];
|
|
70
|
+
}
|
|
71
|
+
}
|