re-jigging things to get counting working properly again.
This commit is contained in:
parent
a97b24658f
commit
2aa911b217
|
@ -114,7 +114,7 @@ function generateSelectStatement(
|
|||
): (string | Knex.Raw)[] | "*" {
|
||||
const { resource, meta } = json
|
||||
|
||||
if (!resource) {
|
||||
if (!resource || !resource.fields || resource.fields.length === 0) {
|
||||
return "*"
|
||||
}
|
||||
|
||||
|
@ -410,14 +410,32 @@ class InternalBuilder {
|
|||
return query
|
||||
}
|
||||
|
||||
addDistinctCount(
|
||||
query: Knex.QueryBuilder,
|
||||
json: QueryJson
|
||||
): Knex.QueryBuilder {
|
||||
const table = json.meta.table
|
||||
const primary = table.primary
|
||||
const aliases = json.tableAliases
|
||||
const aliased =
|
||||
table.name && aliases?.[table.name] ? aliases[table.name] : table.name
|
||||
if (!primary) {
|
||||
throw new Error("SQL counting requires primary key to be supplied")
|
||||
}
|
||||
return query.countDistinct(`${aliased}.${primary[0]} as total`)
|
||||
}
|
||||
|
||||
addSorting(query: Knex.QueryBuilder, json: QueryJson): Knex.QueryBuilder {
|
||||
let { sort } = json
|
||||
const table = json.meta.table
|
||||
const mainPrimaryKey = table.primary![0]
|
||||
const primaryKey = table.primary
|
||||
const tableName = getTableName(table)
|
||||
const aliases = json.tableAliases
|
||||
const aliased =
|
||||
tableName && aliases?.[tableName] ? aliases[tableName] : table?.name
|
||||
if (!Array.isArray(primaryKey)) {
|
||||
throw new Error("Sorting requires primary key to be specified for table")
|
||||
}
|
||||
if (sort && Object.keys(sort || {}).length > 0) {
|
||||
for (let [key, value] of Object.entries(sort)) {
|
||||
const direction =
|
||||
|
@ -432,7 +450,7 @@ class InternalBuilder {
|
|||
}
|
||||
}
|
||||
// always add sorting by the primary key - make sure result is deterministic
|
||||
query = query.orderBy(`${aliased}.${mainPrimaryKey}`)
|
||||
query = query.orderBy(`${aliased}.${primaryKey[0]}`)
|
||||
return query
|
||||
}
|
||||
|
||||
|
@ -600,25 +618,13 @@ class InternalBuilder {
|
|||
json: QueryJson,
|
||||
opts: {
|
||||
limits?: { base: number; query: number }
|
||||
disableSorting?: boolean
|
||||
} = {}
|
||||
): Knex.QueryBuilder {
|
||||
let { endpoint, resource, filters, paginate, relationships, tableAliases } =
|
||||
json
|
||||
const { limits, disableSorting } = opts
|
||||
let { endpoint, filters, paginate, relationships, tableAliases } = json
|
||||
const { limits } = opts
|
||||
const counting = endpoint.operation === Operation.COUNT
|
||||
|
||||
const tableName = endpoint.entityId
|
||||
// select all if not specified
|
||||
if (!resource) {
|
||||
resource = { fields: [] }
|
||||
}
|
||||
let selectStatement: string | (string | Knex.Raw)[] = "*"
|
||||
// handle select
|
||||
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)
|
||||
}
|
||||
// start building the query
|
||||
let query = this.knexWithAlias(knex, endpoint, tableAliases)
|
||||
// handle pagination
|
||||
|
@ -650,7 +656,7 @@ class InternalBuilder {
|
|||
})
|
||||
// add sorting to pre-query
|
||||
// no point in sorting when counting
|
||||
if (!disableSorting) {
|
||||
if (!counting) {
|
||||
query = this.addSorting(query, json)
|
||||
}
|
||||
|
||||
|
@ -662,9 +668,13 @@ class InternalBuilder {
|
|||
// be a table name, not a pre-query
|
||||
[alias]: query as any,
|
||||
})
|
||||
preQuery = preQuery.select(selectStatement)
|
||||
if (!counting) {
|
||||
preQuery = preQuery.select(generateSelectStatement(json, knex))
|
||||
} else {
|
||||
preQuery = this.addDistinctCount(preQuery, json)
|
||||
}
|
||||
// have to add after as well (this breaks MS-SQL)
|
||||
if (this.client !== SqlClient.MS_SQL && !disableSorting) {
|
||||
if (this.client !== SqlClient.MS_SQL && !counting) {
|
||||
preQuery = this.addSorting(preQuery, json)
|
||||
}
|
||||
// handle joins
|
||||
|
@ -688,17 +698,6 @@ class InternalBuilder {
|
|||
})
|
||||
}
|
||||
|
||||
count(knex: Knex, json: QueryJson) {
|
||||
const readQuery = this.read(knex, json, {
|
||||
disableSorting: true,
|
||||
})
|
||||
// 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)
|
||||
|
@ -781,7 +780,8 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
|||
})
|
||||
break
|
||||
case Operation.COUNT:
|
||||
query = builder.count(client, json)
|
||||
// read without any limits to count
|
||||
query = builder.read(client, json)
|
||||
break
|
||||
case Operation.UPDATE:
|
||||
query = builder.update(client, json, opts)
|
||||
|
|
Loading…
Reference in New Issue