Changing how counting occurs in SQL layer.

This commit is contained in:
mike12345567 2024-06-19 14:56:06 +01:00
parent aab100b130
commit 1056efdbf6
1 changed files with 32 additions and 15 deletions

View File

@ -595,19 +595,23 @@ class InternalBuilder {
return query.upsert(parsedBody)
}
read(knex: Knex, json: QueryJson, limit: number): Knex.QueryBuilder {
read(
knex: Knex,
json: QueryJson,
limits?: { base?: number; query?: number }
): Knex.QueryBuilder {
let { endpoint, resource, filters, paginate, relationships, tableAliases } =
json
const counting = endpoint.operation === Operation.COUNT
const tableName = endpoint.entityId
const counting = endpoint.operation === Operation.COUNT
// select all if not specified
if (!resource) {
resource = { fields: [] }
}
let selectStatement: string | (string | Knex.Raw)[] = "*"
// handle select
if (!counting && resource.fields && resource.fields.length > 0) {
if (resource.fields && resource.fields.length > 0) {
// select the resources as the format "table.columnName" - this is what is provided
// by the resource builder further up
selectStatement = generateSelectStatement(json, knex)
@ -616,7 +620,7 @@ class InternalBuilder {
let query = this.knexWithAlias(knex, endpoint, tableAliases)
// handle pagination
let foundOffset: number | null = null
let foundLimit = limit || BASE_LIMIT
let foundLimit = limits?.query || limits?.base
if (paginate && paginate.page && paginate.limit) {
// @ts-ignore
const page = paginate.page <= 1 ? 0 : paginate.page - 1
@ -629,12 +633,12 @@ class InternalBuilder {
} else if (paginate && paginate.limit) {
foundLimit = paginate.limit
}
// always add the found limit, unless counting
if (!counting) {
// add the found limit if supplied
if (foundLimit) {
query = query.limit(foundLimit)
}
// add overall pagination
if (!counting && foundOffset) {
if (foundOffset) {
query = query.offset(foundOffset)
}
// add filters to the query (where)
@ -642,9 +646,11 @@ class InternalBuilder {
aliases: tableAliases,
})
// add sorting to pre-query
// no point in sorting when counting
if (!counting) {
query = this.addSorting(query, json)
}
const alias = tableAliases?.[tableName] || tableName
let preQuery: Knex.QueryBuilder = knex({
// the typescript definition for the knex constructor doesn't support this
@ -653,11 +659,7 @@ class InternalBuilder {
// be a table name, not a pre-query
[alias]: query as any,
})
if (counting) {
preQuery = preQuery.count("* as total")
} else {
preQuery = preQuery.select(selectStatement)
}
// have to add after as well (this breaks MS-SQL)
if (this.client !== SqlClient.MS_SQL && !counting) {
preQuery = this.addSorting(preQuery, json)
@ -672,8 +674,9 @@ class InternalBuilder {
)
// add a base limit over the whole query
if (!counting) {
query = query.limit(BASE_LIMIT)
// if counting we can't set this limit
if (limits?.base) {
query = query.limit(limits.base)
}
return this.addFilters(query, filters, json.meta.table, {
@ -682,6 +685,15 @@ class InternalBuilder {
})
}
count(knex: Knex, json: QueryJson) {
const readQuery = this.read(knex, json)
// have to alias the sub-query, this is a requirement for my-sql and ms-sql
// without this we get an error "Every derived table must have its own alias"
return knex({
subquery: readQuery as any,
}).count("* as total")
}
update(knex: Knex, json: QueryJson, opts: QueryOptions): Knex.QueryBuilder {
const { endpoint, body, filters, tableAliases } = json
let query = this.knexWithAlias(knex, endpoint, tableAliases)
@ -756,8 +768,13 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
query = builder.create(client, json, opts)
break
case Operation.READ:
query = builder.read(client, json, {
query: this.limit,
base: BASE_LIMIT,
})
break
case Operation.COUNT:
query = builder.read(client, json, this.limit)
query = builder.count(client, json)
break
case Operation.UPDATE:
query = builder.update(client, json, opts)