@budibase/server 1.2.39-alpha.5 → 1.2.39-alpha.6
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/builder/assets/{index.db2ba95c.js → index.03c8e17f.js} +143 -143
- package/builder/index.html +1 -1
- package/coverage/clover.xml +204 -186
- package/coverage/coverage-final.json +1 -1
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +1 -1
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +18 -18
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +223 -115
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/utils/index.html +1 -1
- package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +1 -1
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +1 -1
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +1 -1
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +1 -1
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +18 -18
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
- package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +1 -1
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +1 -1
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +399 -364
- package/dist/api/controllers/row/internalSearch.js +34 -4
- package/dist/integrations/base/sql.js +57 -26
- package/dist/package.json +6 -6
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/api/controllers/row/internalSearch.js +39 -3
- package/src/api/routes/tests/internalSearch.spec.js +20 -1
- package/src/integrations/base/sql.ts +62 -26
- package/src/integrations/tests/sql.spec.js +100 -10
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.2.39-alpha.
|
|
4
|
+
"version": "1.2.39-alpha.6",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -77,11 +77,11 @@
|
|
|
77
77
|
"license": "GPL-3.0",
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
80
|
-
"@budibase/backend-core": "1.2.39-alpha.
|
|
81
|
-
"@budibase/client": "1.2.39-alpha.
|
|
82
|
-
"@budibase/pro": "1.2.39-alpha.
|
|
83
|
-
"@budibase/string-templates": "1.2.39-alpha.
|
|
84
|
-
"@budibase/types": "1.2.39-alpha.
|
|
80
|
+
"@budibase/backend-core": "1.2.39-alpha.6",
|
|
81
|
+
"@budibase/client": "1.2.39-alpha.6",
|
|
82
|
+
"@budibase/pro": "1.2.39-alpha.5",
|
|
83
|
+
"@budibase/string-templates": "1.2.39-alpha.6",
|
|
84
|
+
"@budibase/types": "1.2.39-alpha.6",
|
|
85
85
|
"@bull-board/api": "3.7.0",
|
|
86
86
|
"@bull-board/koa": "3.9.4",
|
|
87
87
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -195,5 +195,5 @@
|
|
|
195
195
|
"optionalDependencies": {
|
|
196
196
|
"oracledb": "5.3.0"
|
|
197
197
|
},
|
|
198
|
-
"gitHead": "
|
|
198
|
+
"gitHead": "68ab1f529626e218019b1a7257f010ea21766251"
|
|
199
199
|
}
|
|
@@ -21,6 +21,8 @@ class QueryBuilder {
|
|
|
21
21
|
notEmpty: {},
|
|
22
22
|
oneOf: {},
|
|
23
23
|
contains: {},
|
|
24
|
+
notContains: {},
|
|
25
|
+
containsAny: {},
|
|
24
26
|
...base,
|
|
25
27
|
}
|
|
26
28
|
this.limit = 50
|
|
@@ -126,6 +128,16 @@ class QueryBuilder {
|
|
|
126
128
|
return this
|
|
127
129
|
}
|
|
128
130
|
|
|
131
|
+
addNotContains(key, value) {
|
|
132
|
+
this.query.notContains[key] = value
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
addContainsAny(key, value) {
|
|
137
|
+
this.query.containsAny[key] = value
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
|
|
129
141
|
/**
|
|
130
142
|
* Preprocesses a value before going into a lucene search.
|
|
131
143
|
* Transforms strings to lowercase and wraps strings and bools in quotes.
|
|
@@ -171,11 +183,29 @@ class QueryBuilder {
|
|
|
171
183
|
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
|
|
172
184
|
}
|
|
173
185
|
|
|
174
|
-
const contains = (key, value) => {
|
|
175
|
-
if (
|
|
186
|
+
const contains = (key, value, mode = "AND") => {
|
|
187
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
176
188
|
return null
|
|
177
189
|
}
|
|
178
|
-
|
|
190
|
+
if (!Array.isArray(value)) {
|
|
191
|
+
return `${key}:${value}`
|
|
192
|
+
}
|
|
193
|
+
let statement = `${builder.preprocess(value[0], { escape: true })}`
|
|
194
|
+
for (let i = 1; i < value.length; i++) {
|
|
195
|
+
statement += ` ${mode} ${builder.preprocess(value[i], {
|
|
196
|
+
escape: true,
|
|
197
|
+
})}`
|
|
198
|
+
}
|
|
199
|
+
return `${key}:(${statement})`
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const notContains = (key, value) => {
|
|
203
|
+
const allPrefix = allOr === "" ? "*:* AND" : ""
|
|
204
|
+
return allPrefix + "NOT " + contains(key, value)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const containsAny = (key, value) => {
|
|
208
|
+
return contains(key, value, "OR")
|
|
179
209
|
}
|
|
180
210
|
|
|
181
211
|
const oneOf = (key, value) => {
|
|
@@ -278,6 +308,12 @@ class QueryBuilder {
|
|
|
278
308
|
if (this.query.contains) {
|
|
279
309
|
build(this.query.contains, contains)
|
|
280
310
|
}
|
|
311
|
+
if (this.query.notContains) {
|
|
312
|
+
build(this.query.notContains, notContains)
|
|
313
|
+
}
|
|
314
|
+
if (this.query.containsAny) {
|
|
315
|
+
build(this.query.containsAny, containsAny)
|
|
316
|
+
}
|
|
281
317
|
// make sure table ID is always added as an AND
|
|
282
318
|
if (tableId) {
|
|
283
319
|
query = `(${query})`
|
|
@@ -129,9 +129,10 @@ describe("internal search", () => {
|
|
|
129
129
|
const response = await search.paginatedSearch({
|
|
130
130
|
contains: {
|
|
131
131
|
"column": "a",
|
|
132
|
+
"colArr": [1, 2, 3],
|
|
132
133
|
},
|
|
133
134
|
}, PARAMS)
|
|
134
|
-
checkLucene(response, `*:* AND column:a`, PARAMS)
|
|
135
|
+
checkLucene(response, `*:* AND column:a AND colArr:(1 AND 2 AND 3)`, PARAMS)
|
|
135
136
|
})
|
|
136
137
|
|
|
137
138
|
it("test multiple of same column", async () => {
|
|
@@ -154,4 +155,22 @@ describe("internal search", () => {
|
|
|
154
155
|
}, PARAMS)
|
|
155
156
|
checkLucene(response, `*:* AND 1\\:column:"a"`, PARAMS)
|
|
156
157
|
})
|
|
158
|
+
|
|
159
|
+
it("test containsAny query", async () => {
|
|
160
|
+
const response = await search.paginatedSearch({
|
|
161
|
+
containsAny: {
|
|
162
|
+
"column": ["a", "b", "c"]
|
|
163
|
+
},
|
|
164
|
+
}, PARAMS)
|
|
165
|
+
checkLucene(response, `*:* AND column:(a OR b OR c)`, PARAMS)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it("test notContains query", async () => {
|
|
169
|
+
const response = await search.paginatedSearch({
|
|
170
|
+
notContains: {
|
|
171
|
+
"column": ["a", "b", "c"]
|
|
172
|
+
},
|
|
173
|
+
}, PARAMS)
|
|
174
|
+
checkLucene(response, `*:* AND NOT column:(a AND b AND c)`, PARAMS)
|
|
175
|
+
})
|
|
157
176
|
})
|
|
@@ -159,6 +159,61 @@ class InternalBuilder {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
const contains = (mode: object, any: boolean = false) => {
|
|
163
|
+
const fnc = allOr ? "orWhere" : "where"
|
|
164
|
+
const rawFnc = `${fnc}Raw`
|
|
165
|
+
const not = mode === filters?.notContains ? "NOT " : ""
|
|
166
|
+
function stringifyArray(value: Array<any>, quoteStyle = '"'): string {
|
|
167
|
+
for (let i in value) {
|
|
168
|
+
if (typeof value[i] === "string") {
|
|
169
|
+
value[i] = `${quoteStyle}${value[i]}${quoteStyle}`
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return `[${value.join(",")}]`
|
|
173
|
+
}
|
|
174
|
+
if (this.client === SqlClient.POSTGRES) {
|
|
175
|
+
iterate(mode, (key: string, value: Array<any>) => {
|
|
176
|
+
const wrap = any ? "" : "'"
|
|
177
|
+
const containsOp = any ? "\\?| array" : "@>"
|
|
178
|
+
const fieldNames = key.split(/\./g)
|
|
179
|
+
const tableName = fieldNames[0]
|
|
180
|
+
const columnName = fieldNames[1]
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
query = query[rawFnc](
|
|
183
|
+
`${not}"${tableName}"."${columnName}"::jsonb ${containsOp} ${wrap}${stringifyArray(
|
|
184
|
+
value,
|
|
185
|
+
any ? "'" : '"'
|
|
186
|
+
)}${wrap}`
|
|
187
|
+
)
|
|
188
|
+
})
|
|
189
|
+
} else if (this.client === SqlClient.MY_SQL) {
|
|
190
|
+
const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS"
|
|
191
|
+
iterate(mode, (key: string, value: Array<any>) => {
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
query = query[rawFnc](
|
|
194
|
+
`${not}${jsonFnc}(${key}, '${stringifyArray(value)}')`
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
} else {
|
|
198
|
+
const andOr = mode === filters?.containsAny ? " OR " : " AND "
|
|
199
|
+
iterate(mode, (key: string, value: Array<any>) => {
|
|
200
|
+
let statement = ""
|
|
201
|
+
for (let i in value) {
|
|
202
|
+
if (typeof value[i] === "string") {
|
|
203
|
+
value[i] = `%"${value[i]}"%`
|
|
204
|
+
} else {
|
|
205
|
+
value[i] = `%${value[i]}%`
|
|
206
|
+
}
|
|
207
|
+
statement +=
|
|
208
|
+
(statement ? andOr : "") +
|
|
209
|
+
`LOWER(${likeKey(this.client, key)}) LIKE ?`
|
|
210
|
+
}
|
|
211
|
+
// @ts-ignore
|
|
212
|
+
query = query[rawFnc](`${not}(${statement})`, value)
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
162
217
|
if (!filters) {
|
|
163
218
|
return query
|
|
164
219
|
}
|
|
@@ -229,32 +284,13 @@ class InternalBuilder {
|
|
|
229
284
|
})
|
|
230
285
|
}
|
|
231
286
|
if (filters.contains) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (typeof value === "string") {
|
|
240
|
-
value = `"${value}"`
|
|
241
|
-
}
|
|
242
|
-
// @ts-ignore
|
|
243
|
-
query = query[rawFnc](
|
|
244
|
-
`"${tableName}"."${columnName}"::jsonb @> '[${value}]'`
|
|
245
|
-
)
|
|
246
|
-
})
|
|
247
|
-
} else if (this.client === SqlClient.MY_SQL) {
|
|
248
|
-
iterate(filters.contains, (key: string, value: any) => {
|
|
249
|
-
if (typeof value === "string") {
|
|
250
|
-
value = `"${value}"`
|
|
251
|
-
}
|
|
252
|
-
// @ts-ignore
|
|
253
|
-
query = query[rawFnc](`JSON_CONTAINS(${key}, '${value}')`)
|
|
254
|
-
})
|
|
255
|
-
} else {
|
|
256
|
-
iterate(filters.contains, like)
|
|
257
|
-
}
|
|
287
|
+
contains(filters.contains)
|
|
288
|
+
}
|
|
289
|
+
if (filters.notContains) {
|
|
290
|
+
contains(filters.notContains)
|
|
291
|
+
}
|
|
292
|
+
if (filters.containsAny) {
|
|
293
|
+
contains(filters.containsAny, true)
|
|
258
294
|
}
|
|
259
295
|
return query
|
|
260
296
|
}
|
|
@@ -240,18 +240,18 @@ describe("SQL query builder", () => {
|
|
|
240
240
|
})
|
|
241
241
|
})
|
|
242
242
|
|
|
243
|
-
it("should use like expression for MS-SQL when filter is contains", () => {
|
|
243
|
+
it("should use AND like expression for MS-SQL when filter is contains", () => {
|
|
244
244
|
const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({
|
|
245
245
|
filters: {
|
|
246
246
|
contains: {
|
|
247
|
-
age: 20,
|
|
248
|
-
name: "John"
|
|
247
|
+
age: [20, 25],
|
|
248
|
+
name: ["John", "Mary"]
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
}))
|
|
252
252
|
expect(query).toEqual({
|
|
253
|
-
bindings: [10, "%20%", "%
|
|
254
|
-
sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where LOWER(${TABLE_NAME}.age) LIKE @p1 and LOWER(${TABLE_NAME}.name) LIKE @
|
|
253
|
+
bindings: [10, "%20%", "%25%", `%"John"%`, `%"Mary"%`],
|
|
254
|
+
sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER(${TABLE_NAME}.age) LIKE @p1 AND LOWER(${TABLE_NAME}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 AND LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]`
|
|
255
255
|
})
|
|
256
256
|
})
|
|
257
257
|
|
|
@@ -259,14 +259,14 @@ describe("SQL query builder", () => {
|
|
|
259
259
|
const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({
|
|
260
260
|
filters: {
|
|
261
261
|
contains: {
|
|
262
|
-
age: 20,
|
|
263
|
-
name: "John"
|
|
262
|
+
age: [20],
|
|
263
|
+
name: ["John"]
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
}))
|
|
267
267
|
expect(query).toEqual({
|
|
268
268
|
bindings: [10],
|
|
269
|
-
sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_CONTAINS(${TABLE_NAME}.age, '20') and JSON_CONTAINS(${TABLE_NAME}.name, '"John"') limit ?) as \`${TABLE_NAME}\``
|
|
269
|
+
sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_CONTAINS(${TABLE_NAME}.age, '[20]') and JSON_CONTAINS(${TABLE_NAME}.name, '["John"]') limit ?) as \`${TABLE_NAME}\``
|
|
270
270
|
})
|
|
271
271
|
})
|
|
272
272
|
|
|
@@ -274,8 +274,8 @@ describe("SQL query builder", () => {
|
|
|
274
274
|
const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({
|
|
275
275
|
filters: {
|
|
276
276
|
contains: {
|
|
277
|
-
age: 20,
|
|
278
|
-
name: "John"
|
|
277
|
+
age: [20],
|
|
278
|
+
name: ["John"]
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
}))
|
|
@@ -284,4 +284,94 @@ describe("SQL query builder", () => {
|
|
|
284
284
|
sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"`
|
|
285
285
|
})
|
|
286
286
|
})
|
|
287
|
+
|
|
288
|
+
it("should use NOT like expression for MS-SQL when filter is notContains", () => {
|
|
289
|
+
const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({
|
|
290
|
+
filters: {
|
|
291
|
+
notContains: {
|
|
292
|
+
age: [20],
|
|
293
|
+
name: ["John"]
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}))
|
|
297
|
+
expect(query).toEqual({
|
|
298
|
+
bindings: [10, "%20%", `%"John"%`],
|
|
299
|
+
sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where NOT (LOWER(${TABLE_NAME}.age) LIKE @p1) and NOT (LOWER(${TABLE_NAME}.name) LIKE @p2)) as [${TABLE_NAME}]`
|
|
300
|
+
})
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it("should use NOT JSON_CONTAINS expression for MySQL when filter is notContains", () => {
|
|
304
|
+
const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({
|
|
305
|
+
filters: {
|
|
306
|
+
notContains: {
|
|
307
|
+
age: [20],
|
|
308
|
+
name: ["John"]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}))
|
|
312
|
+
expect(query).toEqual({
|
|
313
|
+
bindings: [10],
|
|
314
|
+
sql: `select * from (select * from \`${TABLE_NAME}\` where NOT JSON_CONTAINS(${TABLE_NAME}.age, '[20]') and NOT JSON_CONTAINS(${TABLE_NAME}.name, '["John"]') limit ?) as \`${TABLE_NAME}\``
|
|
315
|
+
})
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it("should use jsonb operator NOT expression for PostgreSQL when filter is notContains", () => {
|
|
319
|
+
const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({
|
|
320
|
+
filters: {
|
|
321
|
+
notContains: {
|
|
322
|
+
age: [20],
|
|
323
|
+
name: ["John"]
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}))
|
|
327
|
+
expect(query).toEqual({
|
|
328
|
+
bindings: [10],
|
|
329
|
+
sql: `select * from (select * from \"${TABLE_NAME}\" where NOT \"${TABLE_NAME}\".\"age\"::jsonb @> '[20]' and NOT \"${TABLE_NAME}\".\"name\"::jsonb @> '["John"]' limit $1) as \"${TABLE_NAME}\"`
|
|
330
|
+
})
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
it("should use OR like expression for MS-SQL when filter is containsAny", () => {
|
|
334
|
+
const query = new Sql(SqlClient.MS_SQL, 10)._query(generateReadJson({
|
|
335
|
+
filters: {
|
|
336
|
+
containsAny: {
|
|
337
|
+
age: [20, 25],
|
|
338
|
+
name: ["John", "Mary"]
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}))
|
|
342
|
+
expect(query).toEqual({
|
|
343
|
+
bindings: [10, "%20%", "%25%", `%"John"%`, `%"Mary"%`],
|
|
344
|
+
sql: `select * from (select top (@p0) * from [${TABLE_NAME}] where (LOWER(${TABLE_NAME}.age) LIKE @p1 OR LOWER(${TABLE_NAME}.age) LIKE @p2) and (LOWER(${TABLE_NAME}.name) LIKE @p3 OR LOWER(${TABLE_NAME}.name) LIKE @p4)) as [${TABLE_NAME}]`
|
|
345
|
+
})
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it("should use JSON_OVERLAPS expression for MySQL when filter is containsAny", () => {
|
|
349
|
+
const query = new Sql(SqlClient.MY_SQL, 10)._query(generateReadJson({
|
|
350
|
+
filters: {
|
|
351
|
+
containsAny: {
|
|
352
|
+
age: [20, 25],
|
|
353
|
+
name: ["John", "Mary"]
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}))
|
|
357
|
+
expect(query).toEqual({
|
|
358
|
+
bindings: [10],
|
|
359
|
+
sql: `select * from (select * from \`${TABLE_NAME}\` where JSON_OVERLAPS(${TABLE_NAME}.age, '[20,25]') and JSON_OVERLAPS(${TABLE_NAME}.name, '["John","Mary"]') limit ?) as \`${TABLE_NAME}\``
|
|
360
|
+
})
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it("should use ?| operator expression for PostgreSQL when filter is containsAny", () => {
|
|
364
|
+
const query = new Sql(SqlClient.POSTGRES, 10)._query(generateReadJson({
|
|
365
|
+
filters: {
|
|
366
|
+
containsAny: {
|
|
367
|
+
age: [20, 25],
|
|
368
|
+
name: ["John", "Mary"]
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}))
|
|
372
|
+
expect(query).toEqual({
|
|
373
|
+
bindings: [10],
|
|
374
|
+
sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb ?| array [20,25] and \"${TABLE_NAME}\".\"name\"::jsonb ?| array ['John','Mary'] limit $1) as \"${TABLE_NAME}\"`
|
|
375
|
+
})
|
|
376
|
+
})
|
|
287
377
|
})
|