@subsquid/openreader 1.0.1 → 2.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.
Files changed (279) hide show
  1. package/bin/main.js +2 -1
  2. package/lib/context.d.ts +11 -0
  3. package/lib/context.d.ts.map +1 -0
  4. package/lib/context.js +3 -0
  5. package/lib/context.js.map +1 -0
  6. package/lib/db.d.ts +23 -0
  7. package/lib/db.d.ts.map +1 -0
  8. package/lib/db.js +57 -0
  9. package/lib/db.js.map +1 -0
  10. package/{dist → lib}/dialect.d.ts +0 -0
  11. package/{dist → lib}/dialect.d.ts.map +0 -0
  12. package/{dist → lib}/dialect.js +0 -0
  13. package/{dist → lib}/dialect.js.map +0 -0
  14. package/lib/ir/args.d.ts +47 -0
  15. package/lib/ir/args.d.ts.map +1 -0
  16. package/lib/ir/args.js +3 -0
  17. package/lib/ir/args.js.map +1 -0
  18. package/lib/ir/connection.d.ts +30 -0
  19. package/lib/ir/connection.d.ts.map +1 -0
  20. package/lib/ir/connection.js +17 -0
  21. package/lib/ir/connection.js.map +1 -0
  22. package/lib/ir/fields.d.ts +22 -0
  23. package/lib/ir/fields.d.ts.map +1 -0
  24. package/lib/ir/fields.js +3 -0
  25. package/lib/ir/fields.js.map +1 -0
  26. package/lib/limit.size.d.ts +3 -0
  27. package/lib/limit.size.d.ts.map +1 -0
  28. package/lib/limit.size.js +44 -0
  29. package/lib/limit.size.js.map +1 -0
  30. package/{dist → lib}/main.d.ts +0 -0
  31. package/{dist → lib}/main.d.ts.map +0 -0
  32. package/lib/main.js +53 -0
  33. package/lib/main.js.map +1 -0
  34. package/{dist → lib}/model.d.ts +10 -1
  35. package/lib/model.d.ts.map +1 -0
  36. package/{dist → lib}/model.js +0 -0
  37. package/{dist → lib}/model.js.map +0 -0
  38. package/{dist/gql/schema.d.ts → lib/model.schema.d.ts} +2 -2
  39. package/lib/model.schema.d.ts.map +1 -0
  40. package/{dist/gql/schema.js → lib/model.schema.js} +44 -7
  41. package/lib/model.schema.js.map +1 -0
  42. package/{dist → lib}/model.tools.d.ts +0 -0
  43. package/{dist → lib}/model.tools.d.ts.map +0 -0
  44. package/{dist → lib}/model.tools.js +0 -0
  45. package/{dist → lib}/model.tools.js.map +0 -0
  46. package/{dist → lib/opencrud}/orderBy.d.ts +2 -5
  47. package/lib/opencrud/orderBy.d.ts.map +1 -0
  48. package/{dist → lib/opencrud}/orderBy.js +1 -1
  49. package/lib/opencrud/orderBy.js.map +1 -0
  50. package/lib/opencrud/schema.d.ts +31 -0
  51. package/lib/opencrud/schema.d.ts.map +1 -0
  52. package/lib/opencrud/schema.js +522 -0
  53. package/lib/opencrud/schema.js.map +1 -0
  54. package/lib/opencrud/tree.d.ts +8 -0
  55. package/lib/opencrud/tree.d.ts.map +1 -0
  56. package/lib/opencrud/tree.js +131 -0
  57. package/lib/opencrud/tree.js.map +1 -0
  58. package/lib/opencrud/where.d.ts +7 -0
  59. package/lib/opencrud/where.d.ts.map +1 -0
  60. package/lib/opencrud/where.js +141 -0
  61. package/lib/opencrud/where.js.map +1 -0
  62. package/{dist/gql → lib}/scalars/BigInt.d.ts +0 -0
  63. package/lib/scalars/BigInt.d.ts.map +1 -0
  64. package/{dist/gql → lib}/scalars/BigInt.js +1 -1
  65. package/lib/scalars/BigInt.js.map +1 -0
  66. package/{dist/gql → lib}/scalars/Bytes.d.ts +0 -0
  67. package/lib/scalars/Bytes.d.ts.map +1 -0
  68. package/{dist/gql → lib}/scalars/Bytes.js +2 -2
  69. package/lib/scalars/Bytes.js.map +1 -0
  70. package/{dist/gql → lib}/scalars/DateTime.d.ts +0 -0
  71. package/lib/scalars/DateTime.d.ts.map +1 -0
  72. package/{dist/gql → lib}/scalars/DateTime.js +1 -1
  73. package/lib/scalars/DateTime.js.map +1 -0
  74. package/{dist/gql → lib}/scalars/JSON.d.ts +0 -0
  75. package/lib/scalars/JSON.d.ts.map +1 -0
  76. package/{dist/gql → lib}/scalars/JSON.js +0 -0
  77. package/lib/scalars/JSON.js.map +1 -0
  78. package/{dist/gql → lib}/scalars/index.d.ts +0 -0
  79. package/lib/scalars/index.d.ts.map +1 -0
  80. package/{dist/gql → lib}/scalars/index.js +0 -0
  81. package/lib/scalars/index.js.map +1 -0
  82. package/lib/server.d.ts +38 -0
  83. package/lib/server.d.ts.map +1 -0
  84. package/lib/server.js +146 -0
  85. package/lib/server.js.map +1 -0
  86. package/lib/sql/cursor.d.ts +52 -0
  87. package/lib/sql/cursor.d.ts.map +1 -0
  88. package/lib/sql/cursor.js +234 -0
  89. package/lib/sql/cursor.js.map +1 -0
  90. package/lib/sql/mapping.d.ts +4 -0
  91. package/lib/sql/mapping.d.ts.map +1 -0
  92. package/lib/sql/mapping.js +71 -0
  93. package/lib/sql/mapping.js.map +1 -0
  94. package/lib/sql/printer.d.ts +37 -0
  95. package/lib/sql/printer.d.ts.map +1 -0
  96. package/lib/sql/printer.js +311 -0
  97. package/lib/sql/printer.js.map +1 -0
  98. package/lib/sql/query.d.ts +46 -0
  99. package/lib/sql/query.d.ts.map +1 -0
  100. package/lib/sql/query.js +134 -0
  101. package/lib/sql/query.js.map +1 -0
  102. package/lib/sql/util.d.ts +30 -0
  103. package/lib/sql/util.d.ts.map +1 -0
  104. package/lib/sql/util.js +75 -0
  105. package/lib/sql/util.js.map +1 -0
  106. package/lib/subscription.d.ts +18 -0
  107. package/lib/subscription.d.ts.map +1 -0
  108. package/lib/subscription.js +47 -0
  109. package/lib/subscription.js.map +1 -0
  110. package/{dist → lib}/test/basic.test.d.ts +0 -0
  111. package/{dist → lib}/test/basic.test.d.ts.map +0 -0
  112. package/{dist → lib}/test/basic.test.js +0 -0
  113. package/{dist → lib}/test/basic.test.js.map +0 -0
  114. package/{dist → lib}/test/connection.test.d.ts +0 -0
  115. package/{dist → lib}/test/connection.test.d.ts.map +0 -0
  116. package/{dist → lib}/test/connection.test.js +0 -0
  117. package/{dist → lib}/test/connection.test.js.map +0 -0
  118. package/{dist → lib}/test/fts.test.d.ts +0 -0
  119. package/{dist → lib}/test/fts.test.d.ts.map +0 -0
  120. package/{dist → lib}/test/fts.test.js +1 -1
  121. package/lib/test/fts.test.js.map +1 -0
  122. package/{dist → lib}/test/isNull.test.d.ts +0 -0
  123. package/{dist → lib}/test/isNull.test.d.ts.map +0 -0
  124. package/{dist → lib}/test/isNull.test.js +0 -0
  125. package/{dist → lib}/test/isNull.test.js.map +0 -0
  126. package/{dist → lib}/test/lists.test.d.ts +0 -0
  127. package/{dist → lib}/test/lists.test.d.ts.map +0 -0
  128. package/{dist → lib}/test/lists.test.js +0 -0
  129. package/{dist → lib}/test/lists.test.js.map +0 -0
  130. package/{dist → lib}/test/lookup.test.d.ts +0 -0
  131. package/{dist → lib}/test/lookup.test.d.ts.map +0 -0
  132. package/{dist → lib}/test/lookup.test.js +0 -0
  133. package/{dist → lib}/test/lookup.test.js.map +0 -0
  134. package/{dist → lib}/test/regressions.test.d.ts +0 -0
  135. package/{dist → lib}/test/regressions.test.d.ts.map +0 -0
  136. package/{dist → lib}/test/regressions.test.js +0 -0
  137. package/{dist → lib}/test/regressions.test.js.map +0 -0
  138. package/{dist → lib}/test/scalars.test.d.ts +0 -0
  139. package/{dist → lib}/test/scalars.test.d.ts.map +0 -0
  140. package/{dist → lib}/test/scalars.test.js +0 -0
  141. package/{dist → lib}/test/scalars.test.js.map +0 -0
  142. package/{dist → lib}/test/setup.d.ts +3 -1
  143. package/lib/test/setup.d.ts.map +1 -0
  144. package/{dist → lib}/test/setup.js +14 -12
  145. package/lib/test/setup.js.map +1 -0
  146. package/lib/test/subscription.test.d.ts +2 -0
  147. package/lib/test/subscription.test.d.ts.map +1 -0
  148. package/lib/test/subscription.test.js +99 -0
  149. package/lib/test/subscription.test.js.map +1 -0
  150. package/{dist → lib}/test/tools.test.d.ts +0 -0
  151. package/{dist → lib}/test/tools.test.d.ts.map +0 -0
  152. package/{dist → lib}/test/tools.test.js +0 -0
  153. package/{dist → lib}/test/tools.test.js.map +0 -0
  154. package/{dist → lib}/test/typed-json.test.d.ts +0 -0
  155. package/{dist → lib}/test/typed-json.test.d.ts.map +0 -0
  156. package/{dist → lib}/test/typed-json.test.js +0 -0
  157. package/{dist → lib}/test/typed-json.test.js.map +0 -0
  158. package/{dist → lib}/test/unions.test.d.ts +0 -0
  159. package/{dist → lib}/test/unions.test.d.ts.map +0 -0
  160. package/{dist → lib}/test/unions.test.js +0 -0
  161. package/{dist → lib}/test/unions.test.js.map +0 -0
  162. package/{dist → lib}/test/where.test.d.ts +0 -0
  163. package/{dist → lib}/test/where.test.d.ts.map +0 -0
  164. package/{dist → lib}/test/where.test.js +0 -0
  165. package/{dist → lib}/test/where.test.js.map +0 -0
  166. package/{dist → lib}/tools.d.ts +0 -0
  167. package/{dist → lib}/tools.d.ts.map +0 -0
  168. package/{dist → lib}/tools.js +3 -3
  169. package/{dist → lib}/tools.js.map +1 -1
  170. package/lib/util/error-handling.d.ts +11 -0
  171. package/lib/util/error-handling.d.ts.map +1 -0
  172. package/lib/util/error-handling.js +42 -0
  173. package/lib/util/error-handling.js.map +1 -0
  174. package/lib/util/lazy-transaction.d.ts +10 -0
  175. package/lib/util/lazy-transaction.d.ts.map +1 -0
  176. package/lib/util/lazy-transaction.js +43 -0
  177. package/lib/util/lazy-transaction.js.map +1 -0
  178. package/lib/util/resolve-tree.d.ts +14 -0
  179. package/lib/util/resolve-tree.d.ts.map +1 -0
  180. package/lib/util/resolve-tree.js +52 -0
  181. package/lib/util/resolve-tree.js.map +1 -0
  182. package/{dist → lib/util}/util.d.ts +2 -3
  183. package/lib/util/util.d.ts.map +1 -0
  184. package/{dist → lib/util}/util.js +9 -13
  185. package/lib/util/util.js.map +1 -0
  186. package/package.json +17 -9
  187. package/src/context.ts +14 -0
  188. package/src/db.ts +46 -57
  189. package/src/ir/args.ts +85 -0
  190. package/src/ir/connection.ts +48 -0
  191. package/src/ir/fields.ts +40 -0
  192. package/src/limit.size.ts +46 -0
  193. package/src/main.ts +62 -37
  194. package/src/{gql/schema.ts → model.schema.ts} +51 -8
  195. package/src/model.ts +12 -1
  196. package/src/{orderBy.ts → opencrud/orderBy.ts} +3 -10
  197. package/src/opencrud/schema.ts +632 -0
  198. package/src/opencrud/tree.ts +144 -0
  199. package/src/opencrud/where.ts +141 -0
  200. package/src/{gql/scalars → scalars}/BigInt.ts +1 -1
  201. package/src/{gql/scalars → scalars}/Bytes.ts +4 -4
  202. package/src/{gql/scalars → scalars}/DateTime.ts +1 -1
  203. package/src/{gql/scalars → scalars}/JSON.ts +0 -0
  204. package/src/{gql/scalars → scalars}/index.ts +0 -0
  205. package/src/server.ts +128 -48
  206. package/src/sql/cursor.ts +291 -0
  207. package/src/sql/mapping.ts +66 -0
  208. package/src/sql/printer.ts +328 -0
  209. package/src/sql/query.ts +194 -0
  210. package/src/sql/util.ts +89 -0
  211. package/src/subscription.ts +46 -0
  212. package/src/test/fts.test.ts +1 -1
  213. package/src/test/setup.ts +12 -10
  214. package/src/test/subscription.test.ts +98 -0
  215. package/src/tools.ts +1 -1
  216. package/src/util/error-handling.ts +40 -0
  217. package/src/util/lazy-transaction.ts +49 -0
  218. package/src/util/resolve-tree.ts +65 -0
  219. package/src/{util.ts → util/util.ts} +9 -14
  220. package/dist/db.d.ts +0 -28
  221. package/dist/db.d.ts.map +0 -1
  222. package/dist/db.js +0 -69
  223. package/dist/db.js.map +0 -1
  224. package/dist/gql/opencrud.d.ts +0 -6
  225. package/dist/gql/opencrud.d.ts.map +0 -1
  226. package/dist/gql/opencrud.js +0 -326
  227. package/dist/gql/opencrud.js.map +0 -1
  228. package/dist/gql/scalars/BigInt.d.ts.map +0 -1
  229. package/dist/gql/scalars/BigInt.js.map +0 -1
  230. package/dist/gql/scalars/Bytes.d.ts.map +0 -1
  231. package/dist/gql/scalars/Bytes.js.map +0 -1
  232. package/dist/gql/scalars/DateTime.d.ts.map +0 -1
  233. package/dist/gql/scalars/DateTime.js.map +0 -1
  234. package/dist/gql/scalars/JSON.d.ts.map +0 -1
  235. package/dist/gql/scalars/JSON.js.map +0 -1
  236. package/dist/gql/scalars/index.d.ts.map +0 -1
  237. package/dist/gql/scalars/index.js.map +0 -1
  238. package/dist/gql/schema.d.ts.map +0 -1
  239. package/dist/gql/schema.js.map +0 -1
  240. package/dist/main.js +0 -43
  241. package/dist/main.js.map +0 -1
  242. package/dist/model.d.ts.map +0 -1
  243. package/dist/orderBy.d.ts.map +0 -1
  244. package/dist/orderBy.js.map +0 -1
  245. package/dist/queryBuilder.d.ts +0 -56
  246. package/dist/queryBuilder.d.ts.map +0 -1
  247. package/dist/queryBuilder.js +0 -733
  248. package/dist/queryBuilder.js.map +0 -1
  249. package/dist/relayConnection.d.ts +0 -37
  250. package/dist/relayConnection.d.ts.map +0 -1
  251. package/dist/relayConnection.js +0 -43
  252. package/dist/relayConnection.js.map +0 -1
  253. package/dist/requestedFields.d.ts +0 -33
  254. package/dist/requestedFields.d.ts.map +0 -1
  255. package/dist/requestedFields.js +0 -179
  256. package/dist/requestedFields.js.map +0 -1
  257. package/dist/resolver.d.ts +0 -9
  258. package/dist/resolver.d.ts.map +0 -1
  259. package/dist/resolver.js +0 -158
  260. package/dist/resolver.js.map +0 -1
  261. package/dist/server.d.ts +0 -22
  262. package/dist/server.d.ts.map +0 -1
  263. package/dist/server.js +0 -96
  264. package/dist/server.js.map +0 -1
  265. package/dist/test/fts.test.js.map +0 -1
  266. package/dist/test/setup.d.ts.map +0 -1
  267. package/dist/test/setup.js.map +0 -1
  268. package/dist/util.d.ts.map +0 -1
  269. package/dist/util.js.map +0 -1
  270. package/dist/where.d.ts +0 -9
  271. package/dist/where.d.ts.map +0 -1
  272. package/dist/where.js +0 -101
  273. package/dist/where.js.map +0 -1
  274. package/src/gql/opencrud.ts +0 -350
  275. package/src/queryBuilder.ts +0 -891
  276. package/src/relayConnection.ts +0 -80
  277. package/src/requestedFields.ts +0 -246
  278. package/src/resolver.ts +0 -201
  279. package/src/where.ts +0 -119
@@ -1,733 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.QueryBuilder = void 0;
7
- const util_naming_1 = require("@subsquid/util-naming");
8
- const assert_1 = __importDefault(require("assert"));
9
- const model_tools_1 = require("./model.tools");
10
- const orderBy_1 = require("./orderBy");
11
- const util_1 = require("./util");
12
- const where_1 = require("./where");
13
- class QueryBuilder {
14
- constructor(model, dialect, db) {
15
- this.model = model;
16
- this.dialect = dialect;
17
- this.db = db;
18
- this.params = [];
19
- this.aliases = new AliasSet();
20
- }
21
- param(value) {
22
- return '$' + this.params.push(value);
23
- }
24
- ident(name) {
25
- return this.db.escapeIdentifier(name);
26
- }
27
- select(entityName, args, fields, variant) {
28
- let entity = (0, model_tools_1.getEntity)(this.model, entityName);
29
- let table = (0, util_1.toTable)(entityName);
30
- let alias = this.aliases.add(table);
31
- let join = new JoinSet(this.aliases);
32
- let cursor = new Cursor(this.model, this.dialect, this.ident.bind(this), this.aliases, join, entityName, entity, alias, '');
33
- let whereExps = [];
34
- let orderByExps = [];
35
- let columns = new ColumnSet();
36
- let out = '';
37
- if (fields) {
38
- this.populateColumns(columns, cursor, fields);
39
- }
40
- switch (variant?.kind) {
41
- case 'fts':
42
- out += 'SELECT\n';
43
- out += ` '${entityName}' AS isTypeOf`;
44
- out += ',\n';
45
- out += ` ts_rank(${cursor.tsv(variant.queryName)}, phraseto_tsquery('english', ${variant.textParam})) AS rank`;
46
- out += ',\n';
47
- out += ` ts_headline(${cursor.doc(variant.queryName)}, phraseto_tsquery('english', ${variant.textParam})) AS highlight`;
48
- out += ',\n';
49
- out += columns.size() ? ` json_build_array(${columns.render()})` : " '[]'::json";
50
- out += ' AS item\n';
51
- break;
52
- case 'list-subquery':
53
- if (columns.size()) {
54
- out += `SELECT json_build_array(${columns.render()}) AS row `;
55
- }
56
- break;
57
- default:
58
- if (columns.size()) {
59
- out += `SELECT ${columns.render(true)}\n`;
60
- }
61
- }
62
- out += `FROM ${this.ident(table)} ${this.ident(alias)}`;
63
- if ((0, where_1.hasConditions)(args.where)) {
64
- whereExps.push(this.generateWhere(cursor, args.where));
65
- }
66
- if (variant?.kind == 'list-subquery') {
67
- whereExps.push(`${cursor.fk(variant.field)} = ${variant.parent}`);
68
- }
69
- if (variant?.kind == 'fts') {
70
- whereExps.push(`phraseto_tsquery('english', ${variant.textParam}) @@ ${cursor.tsv(variant.queryName)}`);
71
- }
72
- let orderByInput = args.orderBy && (0, util_1.ensureArray)(args.orderBy);
73
- if (orderByInput?.length) {
74
- let orderBy = (0, orderBy_1.parseOrderBy)(this.model, entityName, orderByInput);
75
- this.populateOrderBy(orderByExps, cursor, orderBy);
76
- }
77
- join.forEach(j => {
78
- let table = this.ident(j.table);
79
- let alias = this.ident(j.alias);
80
- out += `\nLEFT OUTER JOIN ${table} ${alias} ON ${alias}.${j.column} = ${j.rhs}`;
81
- });
82
- if (whereExps.length) {
83
- out += '\nWHERE ' + whereExps.join(' AND ');
84
- }
85
- if (orderByExps.length > 0) {
86
- out += '\nORDER BY ' + orderByExps.join(', ');
87
- }
88
- if (args.limit) {
89
- out += '\nLIMIT ' + this.param(args.limit);
90
- }
91
- if (args.offset) {
92
- out += '\nOFFSET ' + this.param(args.offset);
93
- }
94
- if (variant?.kind == 'list-subquery') {
95
- out = out.replace(/\n/g, ' ');
96
- }
97
- return out;
98
- }
99
- populateOrderBy(exps, cursor, orderBy) {
100
- for (let key in orderBy) {
101
- let spec = orderBy[key];
102
- let propType = cursor.object.properties[key].type;
103
- switch (propType.kind) {
104
- case 'scalar':
105
- case 'enum':
106
- (0, assert_1.default)(typeof spec == 'string');
107
- exps.push(`${cursor.native(key)} ${spec}`);
108
- break;
109
- case 'object':
110
- case 'union':
111
- case 'fk':
112
- case 'lookup':
113
- (0, assert_1.default)(typeof spec == 'object');
114
- this.populateOrderBy(exps, cursor.child(key), spec);
115
- break;
116
- default:
117
- throw (0, util_1.unsupportedCase)(propType.kind);
118
- }
119
- }
120
- }
121
- populateColumns(columns, cursor, fields$) {
122
- for (let fieldName in fields$) {
123
- let field = fields$[fieldName];
124
- for (let i = 0; i < field.requests.length; i++) {
125
- let req = field.requests[i];
126
- switch (field.propType.kind) {
127
- case 'scalar':
128
- case 'enum':
129
- case 'list':
130
- req.index = columns.add(cursor.output(fieldName));
131
- break;
132
- case 'object':
133
- req.index = columns.add(cursor.field(fieldName) + ' IS NULL');
134
- this.populateColumns(columns, cursor.child(fieldName), req.children);
135
- break;
136
- case 'union':
137
- let cu = cursor.child(fieldName);
138
- req.index = columns.add(cu.output('isTypeOf'));
139
- this.populateColumns(columns, cu, req.children);
140
- break;
141
- case 'fk':
142
- case 'lookup': {
143
- let cu = cursor.child(fieldName);
144
- req.index = columns.add(cu.output('id'));
145
- this.populateColumns(columns, cu, req.children);
146
- break;
147
- }
148
- case 'list-lookup':
149
- req.index = columns.add('(SELECT jsonb_agg(row) FROM (' + this.select(field.propType.entity, req.args, req.children, {
150
- kind: 'list-subquery',
151
- field: field.propType.field,
152
- parent: cursor.native('id')
153
- }) + ') as rows)');
154
- break;
155
- default:
156
- throw (0, util_1.unsupportedCase)(field.propType.kind);
157
- }
158
- }
159
- }
160
- }
161
- generateWhere(cursor, where) {
162
- let { AND, OR, ...conditions } = where;
163
- let exps = [];
164
- for (let key in conditions) {
165
- let opArg = conditions[key];
166
- let f = (0, where_1.parseWhereField)(key);
167
- switch (f.op) {
168
- case 'every':
169
- if ((0, where_1.hasConditions)(opArg)) {
170
- let rel = cursor.object.properties[f.field].type;
171
- (0, assert_1.default)(rel.kind == 'list-lookup');
172
- let conditionedFrom = this.select(rel.entity, { where: opArg }, undefined, { kind: 'list-subquery', parent: cursor.native('id'), field: rel.field });
173
- let allFrom = this.select(rel.entity, {}, undefined, { kind: 'list-subquery', parent: cursor.native('id'), field: rel.field });
174
- exps.push(`(SELECT count(*) ${conditionedFrom}) = (SELECT count(*) ${allFrom})`);
175
- }
176
- break;
177
- case 'some':
178
- case 'none':
179
- let rel = cursor.object.properties[f.field].type;
180
- (0, assert_1.default)(rel.kind == 'list-lookup');
181
- let q = '(SELECT true ' + this.select(rel.entity, { where: opArg }, undefined, { kind: 'list-subquery', parent: cursor.native('id'), field: rel.field }) + ' LIMIT 1)';
182
- if (f.op == 'some') {
183
- exps.push(q);
184
- }
185
- else {
186
- exps.push(`(SELECT count(*) FROM ${q} ${this.ident(this.aliases.add(key))}) = 0`);
187
- }
188
- break;
189
- default: {
190
- let prop = cursor.object.properties[f.field];
191
- (0, assert_1.default)(prop != null);
192
- this.addPropCondition(exps, cursor, f.field, f.op, opArg);
193
- }
194
- }
195
- }
196
- if (AND) {
197
- // We are getting objects here, although we have array in schema
198
- (0, util_1.ensureArray)(AND).forEach((andWhere) => {
199
- if ((0, where_1.hasConditions)(andWhere)) {
200
- exps.push(this.generateWhere(cursor, andWhere));
201
- }
202
- });
203
- }
204
- if (OR) {
205
- let ors = [];
206
- if (exps.length) {
207
- ors.push('(' + exps.join(' AND ') + ')');
208
- }
209
- // We are getting objects here, although we have array in schema
210
- (0, util_1.ensureArray)(OR).forEach((orWhere) => {
211
- if ((0, where_1.hasConditions)(orWhere)) {
212
- ors.push('(' + this.generateWhere(cursor, orWhere) + ')');
213
- }
214
- });
215
- return '(' + ors.join(' OR ') + ')';
216
- }
217
- else {
218
- return exps.join(' AND ');
219
- }
220
- }
221
- addPropCondition(exps, cursor, field, op, arg) {
222
- let propType = cursor.object.properties[field].type;
223
- if (op == 'isNull') {
224
- let lhs = propType.kind == 'fk' ? cursor.fk(field) : cursor.field(field);
225
- if (arg) {
226
- exps.push(`${lhs} IS NULL`);
227
- }
228
- else {
229
- exps.push(`${lhs} IS NOT NULL`);
230
- }
231
- return;
232
- }
233
- switch (propType.kind) {
234
- case 'scalar':
235
- case 'enum': {
236
- let lhs = cursor.native(field);
237
- switch (op) {
238
- case 'in':
239
- case 'not_in': {
240
- // We have 2 options here
241
- // 1. use array parameter and do: WHERE col IN (SELECT * FROM unnest($array_param))
242
- // 2. use arg list
243
- // Let's try second option first.
244
- let list = (0, util_1.ensureArray)(arg).map(a => this.param(a));
245
- let param = `(${list.join(', ')})`;
246
- exps.push(`${lhs} ${(0, where_1.whereOpToSqlOperator)(op)} ${param}`);
247
- break;
248
- }
249
- case 'startsWith':
250
- if (this.dialect == 'cockroach') {
251
- let p = this.param(arg) + '::text';
252
- exps.push(`${lhs} >= ${p}`);
253
- exps.push(`left(${lhs}, length(${p})) = ${p}`);
254
- }
255
- else {
256
- exps.push(`starts_with(${lhs}, ${this.param(arg)})`);
257
- }
258
- break;
259
- case 'not_startsWith':
260
- if (this.dialect == 'cockroach') {
261
- let p = this.param(arg) + '::text';
262
- exps.push(`(${lhs} < ${p} OR left(${lhs}, length(${p})) != ${p})`);
263
- }
264
- else {
265
- exps.push(`NOT starts_with(${lhs}, ${this.param(arg)})`);
266
- }
267
- break;
268
- case 'endsWith': {
269
- let param = this.param(arg) + '::text';
270
- exps.push(`right(${lhs}, length(${param})) = ${param}`);
271
- break;
272
- }
273
- case 'not_endsWith': {
274
- let param = this.param(arg) + '::text';
275
- exps.push(`right(${lhs}, length(${param})) != ${param}`);
276
- break;
277
- }
278
- case 'contains':
279
- exps.push(`position(${this.param(arg)} in ${lhs}) > 0`);
280
- break;
281
- case 'not_contains':
282
- exps.push(`position(${this.param(arg)} in ${lhs}) = 0`);
283
- break;
284
- case 'containsInsensitive':
285
- exps.push(`position(lower(${this.param(arg)}) in lower(${lhs})) > 0`);
286
- break;
287
- case 'not_containsInsensitive':
288
- exps.push(`position(lower(${this.param(arg)}) in lower(${lhs})) = 0`);
289
- break;
290
- case 'jsonContains':
291
- exps.push(`${lhs} @> ${this.param(arg)}`);
292
- break;
293
- case 'jsonHasKey':
294
- exps.push(`${lhs} ? ${this.param(arg)}`);
295
- break;
296
- default: {
297
- exps.push(`${lhs} ${(0, where_1.whereOpToSqlOperator)(op)} ${this.param(arg)}`);
298
- }
299
- }
300
- break;
301
- }
302
- case 'list': {
303
- let item = propType.item.type;
304
- (0, assert_1.default)(item.kind == 'scalar' || item.kind == 'enum');
305
- let param = this.param(arg);
306
- let lhs = cursor.native(field);
307
- switch (op) {
308
- case 'containsAll':
309
- exps.push(`${lhs} @> ${param}`);
310
- break;
311
- case 'containsAny':
312
- exps.push(`${lhs} && ${param}`);
313
- break;
314
- case 'containsNone':
315
- exps.push(`NOT (${lhs} && ${param})`);
316
- break;
317
- default:
318
- throw (0, util_1.unsupportedCase)(op);
319
- }
320
- break;
321
- }
322
- case 'object':
323
- case 'union': {
324
- (0, assert_1.default)(op == '-');
325
- let cu = cursor.child(field);
326
- for (let key in arg) {
327
- let f = (0, where_1.parseWhereField)(key);
328
- this.addPropCondition(exps, cu, f.field, f.op, arg[key]);
329
- }
330
- break;
331
- }
332
- case 'fk':
333
- case 'lookup': {
334
- (0, assert_1.default)(op == '-');
335
- if ((0, where_1.hasConditions)(arg)) {
336
- exps.push(this.generateWhere(cursor.child(field), arg));
337
- }
338
- break;
339
- }
340
- default:
341
- throw (0, util_1.unsupportedCase)(propType.kind);
342
- }
343
- }
344
- toResult(rows, fields) {
345
- let out = new Array(rows.length);
346
- for (let i = 0; i < rows.length; i++) {
347
- out[i] = this.mapRow(rows[i], fields);
348
- }
349
- return out;
350
- }
351
- mapRow(row, fields, ifType) {
352
- let rec = {};
353
- for (let key in fields) {
354
- let f = fields[key];
355
- for (let i = 0; i < f.requests.length; i++) {
356
- let req = f.requests[i];
357
- if (req.ifType != ifType)
358
- continue;
359
- switch (f.propType.kind) {
360
- case 'scalar':
361
- case 'enum':
362
- case 'list':
363
- rec[req.alias] = row[req.index];
364
- break;
365
- case 'object': {
366
- let isNull = row[req.index];
367
- if (!isNull) {
368
- rec[req.alias] = this.mapRow(row, req.children);
369
- }
370
- break;
371
- }
372
- case 'union': {
373
- let isTypeOf = row[req.index];
374
- if (isTypeOf != null) {
375
- let obj = this.mapRow(row, req.children, isTypeOf);
376
- obj.isTypeOf = isTypeOf;
377
- rec[req.alias] = obj;
378
- }
379
- break;
380
- }
381
- case 'fk':
382
- case 'lookup': {
383
- let id = row[req.index];
384
- if (id != null) {
385
- rec[req.alias] = this.mapRow(row, req.children);
386
- }
387
- break;
388
- }
389
- case 'list-lookup': {
390
- let rows = row[req.index];
391
- if (rows == null) {
392
- rec[req.alias] = [];
393
- }
394
- else {
395
- rec[req.alias] = this.toResult(row[req.index], req.children);
396
- }
397
- break;
398
- }
399
- default:
400
- throw (0, util_1.unsupportedCase)(f.propType.kind);
401
- }
402
- }
403
- }
404
- return rec;
405
- }
406
- async executeSelect(entityName, args, fields$) {
407
- let sql = this.select(entityName, args, fields$);
408
- let rows = await this.query(sql);
409
- return this.toResult(rows, fields$);
410
- }
411
- async executeSelectCount(entityName, where) {
412
- let sql = `SELECT count(*) ${this.select(entityName, { where })}`;
413
- let rows = await this.query(sql);
414
- return (0, util_1.toInt)(rows[0][0]);
415
- }
416
- async executeListCount(entityName, args) {
417
- let sql = `SELECT count(*) FROM (SELECT true ${this.select(entityName, args)}) AS ${this.aliases.add('list')}`;
418
- let rows = await this.query(sql);
419
- return (0, util_1.toInt)(rows[0][0]);
420
- }
421
- query(sql) {
422
- return this.db.query(sql, this.params);
423
- }
424
- fulltextSearchSelect(queryName, args, $fields) {
425
- let query = (0, model_tools_1.getFtsQuery)(this.model, queryName);
426
- let { limit, offset, text } = args;
427
- let textParam = this.param(text);
428
- let srcSelects = [];
429
- query.sources.forEach(src => {
430
- let where = args[`where${src.entity}`];
431
- let itemFields = $fields.item?.[src.entity];
432
- let sql = this.select(src.entity, { where }, itemFields, { kind: 'fts', textParam, queryName });
433
- srcSelects.push(sql);
434
- });
435
- let cols = [];
436
- cols.push('isTypeOf');
437
- cols.push('rank');
438
- if ($fields.highlight) {
439
- cols.push('highlight');
440
- }
441
- if ($fields.item) {
442
- cols.push('item');
443
- }
444
- let sql = `SELECT ${cols.join(', ')} FROM (\n\n`;
445
- sql += srcSelects.join('\n\nUNION ALL\n\n');
446
- sql += `\n\n) AS ${this.aliases.add('tsv')}`;
447
- sql += ` ORDER BY rank DESC`;
448
- if (limit != null) {
449
- sql += ` LIMIT ${this.param(limit)}`;
450
- }
451
- if (offset != null) {
452
- sql += ` OFFSET ${this.param(offset)}`;
453
- }
454
- return sql;
455
- }
456
- toFulltextSearchResult(rows, fields) {
457
- let out = new Array(rows.length);
458
- for (let i = 0; i < rows.length; i++) {
459
- let row = rows[i];
460
- let isTypeOf = row[0];
461
- let highlight = fields.highlight ? row[2] : undefined;
462
- let itemIdx = fields.highlight ? 3 : 2;
463
- let itemFields = fields.item?.[isTypeOf];
464
- let item;
465
- if (itemFields) {
466
- item = this.mapRow(row[itemIdx], itemFields);
467
- item.isTypeOf = isTypeOf;
468
- }
469
- else {
470
- item = { isTypeOf };
471
- }
472
- out[i] = {
473
- rank: row[1],
474
- highlight,
475
- item
476
- };
477
- }
478
- return out;
479
- }
480
- async executeFulltextSearch(queryName, args, $fields) {
481
- let sql = this.fulltextSearchSelect(queryName, args, $fields);
482
- let rows = await this.query(sql);
483
- return this.toFulltextSearchResult(rows, $fields);
484
- }
485
- }
486
- exports.QueryBuilder = QueryBuilder;
487
- /**
488
- * A pointer to an entity or nested json object within SQL query.
489
- *
490
- * It has convenience methods for building various SQL expressions
491
- * related to individual properties of an entity or of an object it points to.
492
- */
493
- class Cursor {
494
- constructor(model, dialect, ident, aliases, join, name, object, alias, prefix) {
495
- this.model = model;
496
- this.dialect = dialect;
497
- this.ident = ident;
498
- this.aliases = aliases;
499
- this.join = join;
500
- this.name = name;
501
- this.object = object;
502
- this.alias = alias;
503
- this.prefix = prefix;
504
- }
505
- output(propName) {
506
- let prop = this.object.properties[propName];
507
- switch (prop.type.kind) {
508
- case 'scalar':
509
- if (this.object.kind == 'object') {
510
- switch (prop.type.name) {
511
- case 'Int':
512
- return `(${this.prefix}->'${propName}')::integer`;
513
- case 'Float':
514
- return `(${this.prefix}->'${propName}')::numeric`;
515
- case 'Boolean':
516
- return `(${this.prefix}->>'${propName}')::bool`;
517
- case 'JSON':
518
- return `${this.prefix}->'${propName}'`;
519
- default:
520
- return `${this.prefix}->>'${propName}'`;
521
- }
522
- }
523
- else {
524
- let exp = this.column(propName);
525
- switch (prop.type.name) {
526
- case 'BigInt':
527
- return `(${exp})::text`;
528
- case 'Bytes':
529
- return `'0x' || encode(${exp}, 'hex')`;
530
- case 'DateTime':
531
- if (this.dialect == 'cockroach') {
532
- return `experimental_strftime((${exp}) at time zone 'UTC', '%Y-%m-%dT%H:%M:%S.%fZ')`;
533
- }
534
- else {
535
- return `to_char((${exp}) at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"')`;
536
- }
537
- default:
538
- return exp;
539
- }
540
- }
541
- case 'enum':
542
- if (this.object.kind == 'object') {
543
- return `${this.prefix}->>'${propName}'`;
544
- }
545
- else {
546
- return this.column(propName);
547
- }
548
- case 'list':
549
- let itemType = prop.type.item.type;
550
- if (this.object.kind == 'object' || itemType.kind != 'scalar' && itemType.kind != 'enum') {
551
- // this is json
552
- return this.field(propName);
553
- }
554
- else {
555
- let exp = this.column(propName);
556
- switch (itemType.name) {
557
- case 'BigInt':
558
- return `(${exp})::text[]`;
559
- case 'Bytes':
560
- return `array(select '0x' || encode(i, 'hex') from unnest(${exp}) as i)`;
561
- case 'DateTime':
562
- if (this.dialect == 'cockroach') {
563
- return `array(select experimental_strftime(i at time zone 'UTC', '%Y-%m-%dT%H:%M:%S.%fZ') from unnest(${exp}) as i)`;
564
- }
565
- else {
566
- return `array(select to_char(i at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') from unnest(${exp}) as i)`;
567
- }
568
- default:
569
- return exp;
570
- }
571
- }
572
- default:
573
- throw (0, util_1.unsupportedCase)(prop.type.kind);
574
- }
575
- }
576
- native(propName) {
577
- let prop = this.object.properties[propName];
578
- if (prop.type.kind == 'list') {
579
- let item = prop.type.item.type;
580
- (0, assert_1.default)(item.kind == 'scalar' || item.kind == 'enum');
581
- return this.column(propName);
582
- }
583
- (0, assert_1.default)(prop.type.kind == 'scalar' || prop.type.kind == 'enum');
584
- if (this.object.kind == 'object') {
585
- let js = `${this.prefix}->'${propName}'`;
586
- let str = `${this.prefix}->>'${propName}'`;
587
- switch (prop.type.name) {
588
- case 'Int':
589
- return `(${js})::integer`;
590
- case 'Float':
591
- return `(${js})::numeric`;
592
- case 'Boolean':
593
- return `(${str})::bool`;
594
- case 'BigInt':
595
- return `(${str})::numeric`;
596
- case 'Bytes':
597
- return `decode(substr(${str}, 3), 'hex')`;
598
- case 'DateTime':
599
- return `(${str})::timestamptz`;
600
- default:
601
- return str;
602
- }
603
- }
604
- else {
605
- return this.column(propName);
606
- }
607
- }
608
- child(propName) {
609
- let name;
610
- let object;
611
- let alias;
612
- let prefix;
613
- let prop = this.object.properties[propName];
614
- switch (prop.type.kind) {
615
- case 'object':
616
- name = prop.type.name;
617
- object = (0, model_tools_1.getObject)(this.model, name);
618
- alias = this.alias;
619
- prefix = this.field(propName);
620
- break;
621
- case 'union':
622
- name = prop.type.name;
623
- object = (0, model_tools_1.getUnionProps)(this.model, name);
624
- alias = this.alias;
625
- prefix = this.field(propName);
626
- break;
627
- case 'fk':
628
- name = prop.type.foreignEntity;
629
- object = (0, model_tools_1.getEntity)(this.model, name);
630
- alias = this.join.add((0, util_1.toTable)(name), '"id"', this.fk(propName));
631
- prefix = '';
632
- break;
633
- case 'lookup':
634
- name = prop.type.entity;
635
- object = (0, model_tools_1.getEntity)(this.model, name);
636
- alias = this.join.add((0, util_1.toTable)(name), this.ident((0, util_1.toFkColumn)(prop.type.field)), this.field('id'));
637
- prefix = '';
638
- break;
639
- default:
640
- throw (0, util_1.unsupportedCase)(prop.type.kind);
641
- }
642
- return new Cursor(this.model, this.dialect, this.ident, this.aliases, this.join, name, object, alias, prefix);
643
- }
644
- field(name) {
645
- if (this.object.kind == 'entity') {
646
- return this.column(name);
647
- }
648
- else {
649
- return `${this.prefix}->'${name}'`;
650
- }
651
- }
652
- column(name) {
653
- (0, assert_1.default)(this.object.kind == 'entity');
654
- return this.ident(this.alias) + '.' + this.ident((0, util_1.toColumn)(name));
655
- }
656
- fk(propName) {
657
- return this.object.kind == 'entity'
658
- ? this.ident(this.alias) + '.' + this.ident((0, util_1.toFkColumn)(propName))
659
- : `${this.prefix}->>'${propName}'`;
660
- }
661
- tsv(queryName) {
662
- (0, assert_1.default)(this.object.kind == 'entity');
663
- return this.ident(this.alias) + '.' + this.ident((0, util_naming_1.toSnakeCase)(queryName) + '_tsv');
664
- }
665
- doc(queryName) {
666
- (0, assert_1.default)(this.object.kind == 'entity');
667
- let query = (0, model_tools_1.getFtsQuery)(this.model, queryName);
668
- let src = query.sources.find(src => src.entity == this.name);
669
- (0, assert_1.default)(src != null);
670
- return src.fields.map(f => `coalesce(${this.field(f)}, '')`).join(` || E'\\n\\n' || `);
671
- }
672
- }
673
- class ColumnSet {
674
- constructor() {
675
- this.columns = new Map();
676
- }
677
- add(column) {
678
- let idx = this.columns.get(column);
679
- if (idx == null) {
680
- idx = this.columns.size;
681
- this.columns.set(column, idx);
682
- }
683
- return idx;
684
- }
685
- render(withAliases) {
686
- let cols = Array.from(this.columns.keys());
687
- if (withAliases) {
688
- cols = cols.map((col, idx) => `${col} AS _c${idx}`);
689
- }
690
- return cols.join(', ');
691
- }
692
- size() {
693
- return this.columns.size;
694
- }
695
- }
696
- class JoinSet {
697
- constructor(aliases) {
698
- this.aliases = aliases;
699
- this.joins = new Map();
700
- }
701
- add(table, column, rhs) {
702
- let key = `${table} ${column} ${rhs}`;
703
- let e = this.joins.get(key);
704
- if (!e) {
705
- e = {
706
- table,
707
- alias: this.aliases.add(table),
708
- column,
709
- rhs
710
- };
711
- this.joins.set(key, e);
712
- }
713
- return e.alias;
714
- }
715
- forEach(cb) {
716
- this.joins.forEach(join => cb(join));
717
- }
718
- }
719
- class AliasSet {
720
- constructor() {
721
- this.aliases = {};
722
- }
723
- add(name) {
724
- if (this.aliases[name]) {
725
- return name + '_' + (this.aliases[name]++);
726
- }
727
- else {
728
- this.aliases[name] = 1;
729
- return name;
730
- }
731
- }
732
- }
733
- //# sourceMappingURL=queryBuilder.js.map