Base implementation of counting (plumbing).
This commit is contained in:
parent
d47c7d9227
commit
7491021ca0
|
@ -12,6 +12,7 @@ import {
|
||||||
SortOrder,
|
SortOrder,
|
||||||
SortType,
|
SortType,
|
||||||
SqlClient,
|
SqlClient,
|
||||||
|
SqlQuery,
|
||||||
Table,
|
Table,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import {
|
import {
|
||||||
|
@ -101,12 +102,29 @@ function buildTableMap(tables: Table[]) {
|
||||||
return tableMap
|
return tableMap
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runSqlQuery(json: QueryJson, tables: Table[]) {
|
function runSqlQuery(json: QueryJson, tables: Table[]): Promise<Row[]>
|
||||||
|
function runSqlQuery(
|
||||||
|
json: QueryJson,
|
||||||
|
tables: Table[],
|
||||||
|
opts: { countTotalRows: boolean }
|
||||||
|
): Promise<number>
|
||||||
|
async function runSqlQuery(
|
||||||
|
json: QueryJson,
|
||||||
|
tables: Table[],
|
||||||
|
opts?: { countTotalRows?: boolean }
|
||||||
|
) {
|
||||||
const alias = new AliasTables(tables.map(table => table.name))
|
const alias = new AliasTables(tables.map(table => table.name))
|
||||||
return await alias.queryWithAliasing(json, async json => {
|
const processSQLQuery = async (json: QueryJson) => {
|
||||||
const query = builder._query(json, {
|
let query: SqlQuery | SqlQuery[]
|
||||||
|
if (opts?.countTotalRows) {
|
||||||
|
query = builder._count(json, {
|
||||||
disableReturning: true,
|
disableReturning: true,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
query = builder._query(json, {
|
||||||
|
disableReturning: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(query)) {
|
if (Array.isArray(query)) {
|
||||||
throw new Error("SQS cannot currently handle multiple queries")
|
throw new Error("SQS cannot currently handle multiple queries")
|
||||||
|
@ -125,7 +143,12 @@ async function runSqlQuery(json: QueryJson, tables: Table[]) {
|
||||||
|
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
return await db.sql<Row>(sql, bindings)
|
return await db.sql<Row>(sql, bindings)
|
||||||
})
|
}
|
||||||
|
if (opts?.countTotalRows) {
|
||||||
|
return await alias.countWithAliasing(json, processSQLQuery)
|
||||||
|
} else {
|
||||||
|
return await alias.queryWithAliasing(json, processSQLQuery)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function search(
|
export async function search(
|
||||||
|
@ -204,8 +227,11 @@ export async function search(
|
||||||
)
|
)
|
||||||
|
|
||||||
// check for pagination final row
|
// check for pagination final row
|
||||||
let nextRow: Row | undefined
|
let nextRow: Row | undefined, rowCount: number | undefined
|
||||||
if (paginate && params.limit && processed.length > params.limit) {
|
if (paginate && params.limit && processed.length > params.limit) {
|
||||||
|
// get the total count of rows
|
||||||
|
rowCount = await runSqlQuery(request, allTables, { countTotalRows: true })
|
||||||
|
// remove the extra row that confirmed if there is another row to move to
|
||||||
nextRow = processed.pop()
|
nextRow = processed.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,14 +252,10 @@ export async function search(
|
||||||
const response: SearchResponse<Row> = {
|
const response: SearchResponse<Row> = {
|
||||||
rows: finalRows,
|
rows: finalRows,
|
||||||
}
|
}
|
||||||
const prevLimit = request.paginate!.limit
|
|
||||||
request.paginate = {
|
|
||||||
limit: 1,
|
|
||||||
page: bookmark * prevLimit + 1,
|
|
||||||
}
|
|
||||||
const hasNextPage = !!nextRow
|
const hasNextPage = !!nextRow
|
||||||
response.hasNextPage = hasNextPage
|
response.hasNextPage = hasNextPage
|
||||||
if (hasNextPage) {
|
if (hasNextPage) {
|
||||||
|
response.totalRows = rowCount
|
||||||
response.bookmark = bookmark + 1
|
response.bookmark = bookmark + 1
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -65,7 +65,7 @@ export default class AliasTables {
|
||||||
this.charSeq = new CharSequence()
|
this.charSeq = new CharSequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
isAliasingEnabled(json: QueryJson, datasource: Datasource) {
|
isAliasingEnabled(json: QueryJson, datasource?: Datasource) {
|
||||||
const operation = json.endpoint.operation
|
const operation = json.endpoint.operation
|
||||||
const fieldLength = json.resource?.fields?.length
|
const fieldLength = json.resource?.fields?.length
|
||||||
if (
|
if (
|
||||||
|
@ -75,6 +75,10 @@ export default class AliasTables {
|
||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// SQS - doesn't have a datasource
|
||||||
|
if (!datasource) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const sqlClient = getSQLClient(datasource)
|
const sqlClient = getSQLClient(datasource)
|
||||||
const isWrite = WRITE_OPERATIONS.includes(operation)
|
const isWrite = WRITE_OPERATIONS.includes(operation)
|
||||||
|
@ -173,7 +177,7 @@ export default class AliasTables {
|
||||||
const isSqs = datasourceId === SQS_DATASOURCE_INTERNAL
|
const isSqs = datasourceId === SQS_DATASOURCE_INTERNAL
|
||||||
let aliasingEnabled: boolean, datasource: Datasource | undefined
|
let aliasingEnabled: boolean, datasource: Datasource | undefined
|
||||||
if (isSqs) {
|
if (isSqs) {
|
||||||
aliasingEnabled = true
|
aliasingEnabled = this.isAliasingEnabled(json)
|
||||||
} else {
|
} else {
|
||||||
datasource = await datasources.get(datasourceId)
|
datasource = await datasources.get(datasourceId)
|
||||||
aliasingEnabled = this.isAliasingEnabled(json, datasource)
|
aliasingEnabled = this.isAliasingEnabled(json, datasource)
|
||||||
|
@ -239,4 +243,17 @@ export default class AliasTables {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handles getting the count out of the query
|
||||||
|
async countWithAliasing(
|
||||||
|
json: QueryJson,
|
||||||
|
queryFn?: (json: QueryJson) => Promise<DatasourcePlusQueryResponse>
|
||||||
|
): Promise<number> {
|
||||||
|
let response = await this.queryWithAliasing(json, queryFn)
|
||||||
|
if (response && response.length === 1 && "total" in response[0]) {
|
||||||
|
return response[0].total
|
||||||
|
} else {
|
||||||
|
throw new Error("Unable to count rows in query - no count response")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ export enum Operation {
|
||||||
READ = "READ",
|
READ = "READ",
|
||||||
UPDATE = "UPDATE",
|
UPDATE = "UPDATE",
|
||||||
DELETE = "DELETE",
|
DELETE = "DELETE",
|
||||||
|
COUNT = "COUNT",
|
||||||
BULK_CREATE = "BULK_CREATE",
|
BULK_CREATE = "BULK_CREATE",
|
||||||
CREATE_TABLE = "CREATE_TABLE",
|
CREATE_TABLE = "CREATE_TABLE",
|
||||||
UPDATE_TABLE = "UPDATE_TABLE",
|
UPDATE_TABLE = "UPDATE_TABLE",
|
||||||
|
|
24
yarn.lock
24
yarn.lock
|
@ -3495,10 +3495,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
|
|
||||||
"@koa/cors@^3.1.0":
|
"@koa/cors@^5.0.0":
|
||||||
version "3.4.3"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.4.3.tgz#d669ee6e8d6e4f0ec4a7a7b0a17e7a3ed3752ebb"
|
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd"
|
||||||
integrity sha512-WPXQUaAeAMVaLTEFpoq3T2O1C+FstkjJnDQqy95Ck1UdILajsRhu6mhJ8H2f4NFPRBoCNN+qywTJfq/gGki5mw==
|
integrity sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==
|
||||||
dependencies:
|
dependencies:
|
||||||
vary "^1.1.2"
|
vary "^1.1.2"
|
||||||
|
|
||||||
|
@ -5817,10 +5817,10 @@
|
||||||
"@types/koa-compose" "*"
|
"@types/koa-compose" "*"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/koa__cors@^3.1.1":
|
"@types/koa__cors@^5.0.0":
|
||||||
version "3.3.1"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-3.3.1.tgz#0ec7543c4c620fd23451bfdd3e21b9a6aadedccd"
|
resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-5.0.0.tgz#74567a045b599266e2cd3940cef96cedecc2ef1f"
|
||||||
integrity sha512-aFGYhTFW7651KhmZZ05VG0QZJre7QxBxDj2LF1lf6GA/wSXEfKVAJxiQQWzRV4ZoMzQIO8vJBXKsUcRuvYK9qw==
|
integrity sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/koa" "*"
|
"@types/koa" "*"
|
||||||
|
|
||||||
|
@ -16343,10 +16343,10 @@ node-source-walk@^5.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.0.0"
|
"@babel/parser" "^7.0.0"
|
||||||
|
|
||||||
nodemailer@6.7.2:
|
nodemailer@6.9.13:
|
||||||
version "6.7.2"
|
version "6.9.13"
|
||||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.2.tgz#44b2ad5f7ed71b7067f7a21c4fedabaec62b85e0"
|
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.13.tgz#5b292bf1e92645f4852ca872c56a6ba6c4a3d3d6"
|
||||||
integrity sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==
|
integrity sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==
|
||||||
|
|
||||||
nodemailer@6.9.9:
|
nodemailer@6.9.9:
|
||||||
version "6.9.9"
|
version "6.9.9"
|
||||||
|
|
Loading…
Reference in New Issue