QueryModifier.ts98 lines · main
1import { safeSql, type SafeSqlFragment } from '../pg-format'
2import {
3 countQuery,
4 deleteQuery,
5 insertQuery,
6 selectQuery,
7 truncateQuery,
8 updateQuery,
9} from './Query.utils'
10import type { ActionConfig, Filter, QueryPagination, QueryTable, Sort } from './types'
11
12export interface IQueryModifier {
13 range: (from: number, to: number) => QueryModifier
14 toSql: () => SafeSqlFragment
15}
16
17export class QueryModifier implements IQueryModifier {
18 protected pagination?: QueryPagination
19
20 constructor(
21 protected table: QueryTable,
22 protected actionConfig: ActionConfig,
23 protected options?: {
24 actionOptions?: { returning?: boolean; cascade?: boolean; enumArrayColumns?: Array<string> }
25 filters?: Array<Filter>
26 sorts?: Array<Sort>
27 }
28 ) {}
29
30 /**
31 * Limits the result to rows within the specified range, inclusive.
32 *
33 * @param from The starting index from which to limit the result, inclusive.
34 * @param to The last index to which to limit the result, inclusive.
35 */
36 range(from: number, to: number) {
37 this.pagination = { offset: from, limit: to - from + 1 }
38 return this
39 }
40
41 /**
42 * Return SQL string for query chains
43 */
44 toSql(
45 options: { isCTE: boolean; isFinal: boolean } = { isCTE: false, isFinal: true }
46 ): SafeSqlFragment {
47 try {
48 const { actionOptions, filters, sorts } = this.options ?? {}
49 switch (this.actionConfig.action) {
50 case 'count': {
51 return countQuery(this.table, { filters })
52 }
53 case 'delete': {
54 return deleteQuery(this.table, filters, {
55 returning: actionOptions?.returning,
56 enumArrayColumns: actionOptions?.enumArrayColumns,
57 })
58 }
59 case 'insert': {
60 return insertQuery(this.table, this.actionConfig.actionValue, {
61 returning: actionOptions?.returning,
62 enumArrayColumns: actionOptions?.enumArrayColumns,
63 })
64 }
65 case 'select': {
66 return selectQuery(
67 this.table,
68 this.actionConfig.actionValue,
69 {
70 filters,
71 pagination: this.pagination,
72 sorts,
73 },
74 options.isFinal,
75 options.isCTE
76 )
77 }
78 case 'update': {
79 return updateQuery(this.table, this.actionConfig.actionValue, {
80 filters,
81 returning: actionOptions?.returning,
82 enumArrayColumns: actionOptions?.enumArrayColumns,
83 })
84 }
85 case 'truncate': {
86 return truncateQuery(this.table, {
87 cascade: actionOptions?.cascade,
88 })
89 }
90 default: {
91 return safeSql``
92 }
93 }
94 } catch (error) {
95 throw error
96 }
97 }
98}