sql.d.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import type { CasingCache } from "../casing.js";
  2. import { entityKind } from "../entity.js";
  3. import type { SelectResult } from "../query-builders/select.types.js";
  4. import { Subquery } from "../subquery.js";
  5. import type { Assume, Equal } from "../utils.js";
  6. import type { AnyColumn } from "../column.js";
  7. import { Column } from "../column.js";
  8. import { Table } from "../table.js";
  9. /**
  10. * This class is used to indicate a primitive param value that is used in `sql` tag.
  11. * It is only used on type level and is never instantiated at runtime.
  12. * If you see a value of this type in the code, its runtime value is actually the primitive param value.
  13. */
  14. export declare class FakePrimitiveParam {
  15. static readonly [entityKind]: string;
  16. }
  17. export type Chunk = string | Table | View | AnyColumn | Name | Param | Placeholder | SQL;
  18. export interface BuildQueryConfig {
  19. casing: CasingCache;
  20. escapeName(name: string): string;
  21. escapeParam(num: number, value: unknown): string;
  22. escapeString(str: string): string;
  23. prepareTyping?: (encoder: DriverValueEncoder<unknown, unknown>) => QueryTypingsValue;
  24. paramStartIndex?: {
  25. value: number;
  26. };
  27. inlineParams?: boolean;
  28. invokeSource?: 'indexes' | undefined;
  29. }
  30. export type QueryTypingsValue = 'json' | 'decimal' | 'time' | 'timestamp' | 'uuid' | 'date' | 'none';
  31. export interface Query {
  32. sql: string;
  33. params: unknown[];
  34. }
  35. export interface QueryWithTypings extends Query {
  36. typings?: QueryTypingsValue[];
  37. }
  38. /**
  39. * Any value that implements the `getSQL` method. The implementations include:
  40. * - `Table`
  41. * - `Column`
  42. * - `View`
  43. * - `Subquery`
  44. * - `SQL`
  45. * - `SQL.Aliased`
  46. * - `Placeholder`
  47. * - `Param`
  48. */
  49. export interface SQLWrapper {
  50. getSQL(): SQL;
  51. shouldOmitSQLParens?(): boolean;
  52. }
  53. export declare function isSQLWrapper(value: unknown): value is SQLWrapper;
  54. export declare class StringChunk implements SQLWrapper {
  55. static readonly [entityKind]: string;
  56. readonly value: string[];
  57. constructor(value: string | string[]);
  58. getSQL(): SQL<unknown>;
  59. }
  60. export declare class SQL<T = unknown> implements SQLWrapper {
  61. readonly queryChunks: SQLChunk[];
  62. static readonly [entityKind]: string;
  63. _: {
  64. brand: 'SQL';
  65. type: T;
  66. };
  67. private shouldInlineParams;
  68. constructor(queryChunks: SQLChunk[]);
  69. append(query: SQL): this;
  70. toQuery(config: BuildQueryConfig): QueryWithTypings;
  71. buildQueryFromSourceParams(chunks: SQLChunk[], _config: BuildQueryConfig): Query;
  72. private mapInlineParam;
  73. getSQL(): SQL;
  74. as(alias: string): SQL.Aliased<T>;
  75. /**
  76. * @deprecated
  77. * Use ``sql<DataType>`query`.as(alias)`` instead.
  78. */
  79. as<TData>(): SQL<TData>;
  80. /**
  81. * @deprecated
  82. * Use ``sql<DataType>`query`.as(alias)`` instead.
  83. */
  84. as<TData>(alias: string): SQL.Aliased<TData>;
  85. mapWith<TDecoder extends DriverValueDecoder<any, any> | DriverValueDecoder<any, any>['mapFromDriverValue']>(decoder: TDecoder): SQL<GetDecoderResult<TDecoder>>;
  86. inlineParams(): this;
  87. /**
  88. * This method is used to conditionally include a part of the query.
  89. *
  90. * @param condition - Condition to check
  91. * @returns itself if the condition is `true`, otherwise `undefined`
  92. */
  93. if(condition: any | undefined): this | undefined;
  94. }
  95. export type GetDecoderResult<T> = T extends Column ? T['_']['data'] : T extends DriverValueDecoder<infer TData, any> | DriverValueDecoder<infer TData, any>['mapFromDriverValue'] ? TData : never;
  96. /**
  97. * Any DB name (table, column, index etc.)
  98. */
  99. export declare class Name implements SQLWrapper {
  100. readonly value: string;
  101. static readonly [entityKind]: string;
  102. protected brand: 'Name';
  103. constructor(value: string);
  104. getSQL(): SQL<unknown>;
  105. }
  106. /**
  107. * Any DB name (table, column, index etc.)
  108. * @deprecated Use `sql.identifier` instead.
  109. */
  110. export declare function name(value: string): Name;
  111. export interface DriverValueDecoder<TData, TDriverParam> {
  112. mapFromDriverValue(value: TDriverParam): TData;
  113. }
  114. export interface DriverValueEncoder<TData, TDriverParam> {
  115. mapToDriverValue(value: TData): TDriverParam | SQL;
  116. }
  117. export declare function isDriverValueEncoder(value: unknown): value is DriverValueEncoder<any, any>;
  118. export declare const noopDecoder: DriverValueDecoder<any, any>;
  119. export declare const noopEncoder: DriverValueEncoder<any, any>;
  120. export interface DriverValueMapper<TData, TDriverParam> extends DriverValueDecoder<TData, TDriverParam>, DriverValueEncoder<TData, TDriverParam> {
  121. }
  122. export declare const noopMapper: DriverValueMapper<any, any>;
  123. /** Parameter value that is optionally bound to an encoder (for example, a column). */
  124. export declare class Param<TDataType = unknown, TDriverParamType = TDataType> implements SQLWrapper {
  125. readonly value: TDataType;
  126. readonly encoder: DriverValueEncoder<TDataType, TDriverParamType>;
  127. static readonly [entityKind]: string;
  128. protected brand: 'BoundParamValue';
  129. /**
  130. * @param value - Parameter value
  131. * @param encoder - Encoder to convert the value to a driver parameter
  132. */
  133. constructor(value: TDataType, encoder?: DriverValueEncoder<TDataType, TDriverParamType>);
  134. getSQL(): SQL<unknown>;
  135. }
  136. /** @deprecated Use `sql.param` instead. */
  137. export declare function param<TData, TDriver>(value: TData, encoder?: DriverValueEncoder<TData, TDriver>): Param<TData, TDriver>;
  138. /**
  139. * Anything that can be passed to the `` sql`...` `` tagged function.
  140. */
  141. export type SQLChunk = StringChunk | SQLChunk[] | SQLWrapper | SQL | Table | View | Subquery | AnyColumn | Param | Name | undefined | FakePrimitiveParam | Placeholder;
  142. export declare function sql<T>(strings: TemplateStringsArray, ...params: any[]): SQL<T>;
  143. export declare namespace sql {
  144. function empty(): SQL;
  145. /** @deprecated - use `sql.join()` */
  146. function fromList(list: SQLChunk[]): SQL;
  147. /**
  148. * Convenience function to create an SQL query from a raw string.
  149. * @param str The raw SQL query string.
  150. */
  151. function raw(str: string): SQL;
  152. /**
  153. * Join a list of SQL chunks with a separator.
  154. * @example
  155. * ```ts
  156. * const query = sql.join([sql`a`, sql`b`, sql`c`]);
  157. * // sql`abc`
  158. * ```
  159. * @example
  160. * ```ts
  161. * const query = sql.join([sql`a`, sql`b`, sql`c`], sql`, `);
  162. * // sql`a, b, c`
  163. * ```
  164. */
  165. function join(chunks: SQLChunk[], separator?: SQLChunk): SQL;
  166. /**
  167. * Create a SQL chunk that represents a DB identifier (table, column, index etc.).
  168. * When used in a query, the identifier will be escaped based on the DB engine.
  169. * For example, in PostgreSQL, identifiers are escaped with double quotes.
  170. *
  171. * **WARNING: This function does not offer any protection against SQL injections, so you must validate any user input beforehand.**
  172. *
  173. * @example ```ts
  174. * const query = sql`SELECT * FROM ${sql.identifier('my-table')}`;
  175. * // 'SELECT * FROM "my-table"'
  176. * ```
  177. */
  178. function identifier(value: string): Name;
  179. function placeholder<TName extends string>(name: TName): Placeholder<TName>;
  180. function param<TData, TDriver>(value: TData, encoder?: DriverValueEncoder<TData, TDriver>): Param<TData, TDriver>;
  181. }
  182. export declare namespace SQL {
  183. class Aliased<T = unknown> implements SQLWrapper {
  184. readonly sql: SQL;
  185. readonly fieldAlias: string;
  186. static readonly [entityKind]: string;
  187. _: {
  188. brand: 'SQL.Aliased';
  189. type: T;
  190. };
  191. constructor(sql: SQL, fieldAlias: string);
  192. getSQL(): SQL;
  193. }
  194. }
  195. export declare class Placeholder<TName extends string = string, TValue = any> implements SQLWrapper {
  196. readonly name: TName;
  197. static readonly [entityKind]: string;
  198. protected: TValue;
  199. constructor(name: TName);
  200. getSQL(): SQL;
  201. }
  202. /** @deprecated Use `sql.placeholder` instead. */
  203. export declare function placeholder<TName extends string>(name: TName): Placeholder<TName>;
  204. export declare function fillPlaceholders(params: unknown[], values: Record<string, unknown>): unknown[];
  205. export type ColumnsSelection = Record<string, unknown>;
  206. export declare abstract class View<TName extends string = string, TExisting extends boolean = boolean, TSelection extends ColumnsSelection = ColumnsSelection> implements SQLWrapper {
  207. static readonly [entityKind]: string;
  208. _: {
  209. brand: 'View';
  210. viewBrand: string;
  211. name: TName;
  212. existing: TExisting;
  213. selectedFields: TSelection;
  214. };
  215. readonly $inferSelect: InferSelectViewModel<View<Assume<TName, string>, TExisting, TSelection>>;
  216. constructor({ name, schema, selectedFields, query }: {
  217. name: TName;
  218. schema: string | undefined;
  219. selectedFields: ColumnsSelection;
  220. query: SQL | undefined;
  221. });
  222. getSQL(): SQL<unknown>;
  223. }
  224. export declare function isView(view: unknown): view is View;
  225. export declare function getViewName<T extends View>(view: T): T['_']['name'];
  226. export type InferSelectViewModel<TView extends View> = Equal<TView['_']['selectedFields'], {
  227. [x: string]: unknown;
  228. }> extends true ? {
  229. [x: string]: unknown;
  230. } : SelectResult<TView['_']['selectedFields'], 'single', Record<TView['_']['name'], 'not-null'>>;