├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── README.md ├── documentation ├── README.md ├── mysql.md ├── pg.md └── sqlite.md ├── package.json ├── pnpm-lock.yaml ├── sql ├── nanoid.sql └── search-path.sql ├── src ├── expressions.ts ├── functions.ts ├── index.ts ├── internals.ts ├── mysql │ ├── functions.ts │ └── index.ts ├── operators.ts ├── pg │ ├── citext │ │ ├── README.md │ │ ├── custom-types.ts │ │ └── index.ts │ ├── constants.ts │ ├── cube │ │ ├── README.md │ │ ├── constants.ts │ │ ├── custom-types.ts │ │ ├── functions.ts │ │ ├── index.ts │ │ └── operators.ts │ ├── custom-types.ts │ ├── functions.ts │ ├── fuzzystrmatch │ │ ├── README.md │ │ ├── functions.ts │ │ └── index.ts │ ├── index.ts │ ├── internals.ts │ ├── operators.ts │ ├── pgcrypto │ │ ├── README.md │ │ ├── functions.ts │ │ └── index.ts │ ├── pgtrgm │ │ ├── README.md │ │ ├── index.ts │ │ └── operators.ts │ ├── postgis │ │ ├── README.md │ │ ├── constants.ts │ │ ├── custom-types.ts │ │ ├── functions.ts │ │ ├── index.ts │ │ └── operators.ts │ ├── utilities.ts │ ├── validation.ts │ └── values.ts ├── sqlite │ ├── functions.ts │ └── index.ts ├── utilities.ts └── values.ts ├── tsconfig.json ├── tsup.config.ts └── typedoc.json /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | .env 5 | .env.* 6 | !.env.example 7 | 8 | # Ignore files for PNPM, NPM and YARN 9 | pnpm-lock.yaml 10 | package-lock.json 11 | yarn.lock 12 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 4 | parser: '@typescript-eslint/parser', 5 | plugins: ['@typescript-eslint', 'eslint-plugin-drizzle'], 6 | parserOptions: { 7 | sourceType: 'module', 8 | ecmaVersion: 2020, 9 | }, 10 | env: { 11 | browser: true, 12 | es2017: true, 13 | node: true, 14 | }, 15 | rules: { 16 | 'curly': ['error', 'all'], 17 | '@typescript-eslint/consistent-type-imports': 'error', 18 | '@typescript-eslint/no-unused-vars': [ 19 | 'error', 20 | { ignoreRestSiblings: true, destructuredArrayIgnorePattern: '^_' }, 21 | ], 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | resolution-mode=highest 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | .env 5 | .env.* 6 | !.env.example 7 | 8 | # Ignore files for PNPM, NPM and YARN 9 | pnpm-lock.yaml 10 | package-lock.json 11 | yarn.lock 12 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "printWidth": 100, 8 | "plugins": [ 9 | "./node_modules/prettier-plugin-jsdoc/dist/index.js" 10 | ], 11 | "pluginSearchDirs": [ 12 | "." 13 | ], 14 | "proseWrap": "always", 15 | "overrides": [ 16 | { 17 | "files": [ 18 | "*.md" 19 | ], 20 | "options": { 21 | "useTabs": false 22 | } 23 | } 24 | ], 25 | "bracketSpacing": true, 26 | "bracketSameLine": false, 27 | "arrowParens": "always", 28 | "svelteIndentScriptAndStyle": true, 29 | "svelteAllowShorthand": true, 30 | "jsdocDescriptionWithDot": true, 31 | "jsdocPreferCodeFences": true, 32 | "jsdocCommentLineStrategy": "multiline", 33 | "tsdoc": true, 34 | "quoteProps": "consistent", 35 | "embeddedLanguageFormatting": "auto", 36 | "htmlWhitespaceSensitivity": "ignore" 37 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnPaste": false, 3 | "editor.formatOnSave": true, 4 | "editor.defaultFormatter": "esbenp.prettier-vscode", 5 | "editor.codeActionsOnSave": { 6 | "source.organizeImports": "explicit", 7 | "source.fixAll": "explicit" 8 | }, 9 | "markdownlint.config": { 10 | "default": true, 11 | "MD033": false 12 | }, 13 | "[sql]": { 14 | "editor.formatOnSave": false, 15 | "editor.formatOnPaste": false, 16 | "editor.formatOnType": false 17 | }, 18 | "typescript.tsdk": "node_modules/typescript/lib", 19 | "typescript.preferences.quoteStyle": "single" 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Drizzle ORM Helpers

2 | 3 |

4 | ⚠️ Use at your own risk ⚠️ 5 |

6 |

7 | 🚧 This package is under construction, expect some things to be broken! 🚧 8 |

9 | 10 |
11 | 12 | This is a collection of unofficial typescript-friendly helpers for use with Drizzle ORM. Provided 13 | items include common SQL/dialect-specific values, functions, operators, and column types. Note that 14 | most the work is currently oriented towards Postgres and that most "solutions" provided by this 15 | package should be seen as provisory, in wait of being replaced by implementations provided 16 | officially and with more stability through Drizzle-ORM package(s). 17 | 18 | ## Documentation 19 | 20 | A crude auto-generated 21 | [**documentation** is available here](https://github.com/iolyd/drizzle-orm-helpers/blob/main/documentation/README.md). 22 | 23 | ## Examples 24 | 25 | ### Aggregating translations 26 | 27 | ```ts 28 | const APP_LANGUAGES = ['fr', 'en', 'es'] as const; 29 | type AppLanguage = (typeof APP_LANGUAGES)[number]; // 'fr' | 'en' | 'es'; 30 | 31 | const languages = pgTable('languages', { 32 | lang: textenum('lang', { enum: APP_LANGUAGES }), 33 | }); 34 | 35 | const projects = pgTable('projects', { 36 | id: text('id') 37 | .default(nanoid({ size: 12 })) 38 | .primaryKey(), 39 | createdById: text('created_by_id').references(() => users.id, { 40 | onDelete: 'cascade', 41 | onUpdate: 'cascade', 42 | }), 43 | }); 44 | 45 | const projectsTranslations = pgTable( 46 | 'projects_t', 47 | { 48 | id: text('id') 49 | .references(() => projects.id, { onDelete: 'cascade', onUpdate: 'cascade' }) 50 | .notNull(), 51 | lang: textenum('lang', { enum: APP_LANGUAGES }) 52 | .references(() => languages.lang, { onDelete: 'cascade', onUpdate: 'cascade' }) 53 | .notNull(), 54 | title: text('title'), 55 | description: text('description'), 56 | }, 57 | (table) => { 58 | return { 59 | pk: primaryKey({ columns: [table.id, table.lang] }), 60 | }; 61 | } 62 | ); 63 | 64 | /** 65 | * Build a json object aggregating translations with languages as keys and joined columns as nested 66 | * properties. 67 | */ 68 | export function aggTranslations(selection: TSelection) { 69 | return jsonObjectAgg(languages.lang, jsonBuildObject(selection)); 70 | } 71 | 72 | /** 73 | * Join translations through the languages table. 74 | */ 75 | export function joinTranslations< 76 | TSelect extends PgSelect, 77 | TTranslations extends 78 | | (AnyTable & LangColumn) 79 | | (Subquery & LangColumn), 80 | >(select: TSelect, translations: TTranslations, on: SQL) { 81 | return select 82 | .leftJoin(languages, $true) 83 | .leftJoin(translations, and(on, eq(languages.lang, translations.lang))); 84 | } 85 | 86 | const projectsWithTranslations = await joinTranslations( 87 | db 88 | .select({ 89 | ...getColumns(projects), 90 | translations: aggTranslations(getColumns(projectsTranslations)), 91 | }) 92 | .from(projects), 93 | projectsTranslations, 94 | eq(projects.id, projectsTranslations.id) 95 | ); 96 | ``` 97 | 98 | Would return aggregated data with expected types as: 99 | 100 | ```json 101 | [ 102 | { 103 | id: string, 104 | created_by_id: string, 105 | translations: { 106 | fr: { 107 | id: string, 108 | lang: string, 109 | title?: string, 110 | description?: string 111 | }, 112 | en: { 113 | id: string, 114 | lang: string, 115 | title?: string, 116 | description?: string 117 | } 118 | es: { 119 | id: string, 120 | lang: string, 121 | title?: string, 122 | description?: string 123 | } 124 | } 125 | }, 126 | //... 127 | ] 128 | ``` 129 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | # src 2 | 3 | ## Table of Contents 4 | 5 | - [Type Aliases](#type-aliases) 6 | - [AnySelect](#anyselect) 7 | - [InferColumnType\](#infercolumntypet) 8 | - [InferColumns\](#infercolumnst) 9 | - [InferData\](#inferdatat) 10 | - [InferNameOrAlias\](#infernameoraliast) 11 | - [Schema](#schema) 12 | - [Select](#select) 13 | - [SubqueryWithSelection\](#subquerywithselectiontselection-tname) 14 | - [WithSubqueryWithSelection\](#withsubquerywithselectiontselection-talias) 15 | - [Variables](#variables) 16 | - [$currentTimestamp](#currenttimestamp) 17 | - [$false](#false) 18 | - [$null](#null) 19 | - [$true](#true) 20 | - [Functions](#functions) 21 | - [$boolean()](#boolean) 22 | - [add()](#add) 23 | - [cases()](#cases) 24 | - [coalesce()](#coalesce) 25 | - [distinct()](#distinct) 26 | - [divide()](#divide) 27 | - [getColumns()](#getcolumns) 28 | - [getNameOrAlias()](#getnameoralias) 29 | - [greatest()](#greatest) 30 | - [least()](#least) 31 | - [multiply()](#multiply) 32 | - [nullIf()](#nullif) 33 | - [paginate()](#paginate) 34 | - [subtract()](#subtract) 35 | 36 | ## Type Aliases 37 | 38 | 39 | 40 | ### AnySelect 41 | 42 | ```ts 43 | type AnySelect: SetOptional; 44 | ``` 45 | 46 | Dialect agnostic AnySelect. 47 | 48 | #### See 49 | 50 | - AnyPgSelect 51 | - AnyMySqlSelect 52 | - AnySQLiteSelect 53 | 54 | --- 55 | 56 | 57 | 58 | ### InferColumnType\ 59 | 60 | ```ts 61 | type InferColumnType: AnyColumn["_"], "data" | "dataType">>; 62 | ``` 63 | 64 | Infer type of table column. 65 | 66 | #### Type parameters 67 | 68 | | Type parameter | 69 | | :------------------------------------------------------------- | 70 | | `T` _extends_ (...`config`: `never`\[]) => `ColumnBuilderBase` | 71 | 72 | --- 73 | 74 | 75 | 76 | ### InferColumns\ 77 | 78 | ```ts 79 | type InferColumns: T extends Table ? T["_"]["columns"] : T extends View | Subquery | WithSubquery | AnySelect ? T["_"]["selectedFields"] : never; 80 | ``` 81 | 82 | Infer table columns or (sub)query fields. 83 | 84 | #### Type parameters 85 | 86 | | Type parameter | 87 | | :------------------------------------ | 88 | | `T` _extends_ | 89 | | \| `Table` | 90 | | \| `View` | 91 | | \| `Subquery` | 92 | | \| `WithSubquery` | 93 | | \| [`AnySelect`](README.md#anyselect) | 94 | 95 | --- 96 | 97 | 98 | 99 | ### InferData\ 100 | 101 | ```ts 102 | type InferData: T extends Table ? InferSelectModel : T extends Column ? T["_"]["notNull"] extends true ? T["_"]["data"] : T["_"]["data"] | null : T extends View | Subquery ? T["_"]["selectedFields"] : T extends SQL ? U : T extends SQL.Aliased ? U : unknown; 103 | ``` 104 | 105 | Infer any SQL wrapper's expected return data type. 106 | 107 | #### Type parameters 108 | 109 | | Type parameter | 110 | | :------------------------- | 111 | | `T` _extends_ `SQLWrapper` | 112 | 113 | --- 114 | 115 | 116 | 117 | ### InferNameOrAlias\ 118 | 119 | ```ts 120 | type InferNameOrAlias: T extends Table | View | Column ? T["_"]["name"] : T extends Subquery | WithSubquery ? T["_"]["alias"] : T extends AnySelect ? T["_"]["tableName"] : T extends SQL.Aliased ? T["fieldAlias"] : T extends Placeholder ? T["name"] : undefined; 121 | ``` 122 | 123 | Infer a table's name or a (sub)query's alias. 124 | 125 | #### Type parameters 126 | 127 | | Type parameter | 128 | | :------------------------- | 129 | | `T` _extends_ `SQLWrapper` | 130 | 131 | --- 132 | 133 | 134 | 135 | ### Schema 136 | 137 | ```ts 138 | type Schema: PgSchema | MySqlSchema; 139 | ``` 140 | 141 | Dialect-agnostic schema. Excludes SQLite. 142 | 143 | --- 144 | 145 | 146 | 147 | ### Select 148 | 149 | ```ts 150 | type Select: SetOptional; 151 | ``` 152 | 153 | Dialect agnostic select. 154 | 155 | #### See 156 | 157 | - PgSelect. 158 | - MySqlSelect 159 | - SQLiteSelect 160 | 161 | --- 162 | 163 | 164 | 165 | ### SubqueryWithSelection\ 166 | 167 | ```ts 168 | type SubqueryWithSelection: MySqlSubqueryWithSelection | PgSubqueryWithSelection | SQLiteSubqueryWithSelection; 169 | ``` 170 | 171 | Dialect-agnostic subquery with selection. 172 | 173 | #### Type parameters 174 | 175 | | Type parameter | 176 | | :---------------------------------------- | 177 | | `TSelection` _extends_ `ColumnsSelection` | 178 | | `TName` _extends_ `string` | 179 | 180 | --- 181 | 182 | 183 | 184 | ### WithSubqueryWithSelection\ 185 | 186 | ```ts 187 | type WithSubqueryWithSelection: PgWithSubqueryWithSelection | SQLiteWithSubqueryWithSelection | MySqlWithSubqueryWithSelection; 188 | ``` 189 | 190 | Dialect-agnostic with subquery with selection. 191 | 192 | #### Type parameters 193 | 194 | | Type parameter | 195 | | :---------------------------------------- | 196 | | `TSelection` _extends_ `ColumnsSelection` | 197 | | `TAlias` _extends_ `string` | 198 | 199 | ## Variables 200 | 201 | 202 | 203 | ### $currentTimestamp 204 | 205 | ```ts 206 | const $currentTimestamp: SQL; 207 | ``` 208 | 209 | #### Example 210 | 211 | ```sql 212 | current_timestamp(); 213 | ``` 214 | 215 | --- 216 | 217 | 218 | 219 | ### $false 220 | 221 | ```ts 222 | const $false: SQL; 223 | ``` 224 | 225 | SQL template false value. 226 | 227 | --- 228 | 229 | 230 | 231 | ### $null 232 | 233 | ```ts 234 | const $null: SQL; 235 | ``` 236 | 237 | SQL template null value. 238 | 239 | --- 240 | 241 | 242 | 243 | ### $true 244 | 245 | ```ts 246 | const $true: SQL; 247 | ``` 248 | 249 | SQL template true value. 250 | 251 | ## Functions 252 | 253 | 254 | 255 | ### $boolean() 256 | 257 | ```ts 258 | function $boolean(value: T): SQL; 259 | ``` 260 | 261 | SQL template boolean value. 262 | 263 | #### Type parameters 264 | 265 | | Type parameter | 266 | | :---------------------- | 267 | | `T` _extends_ `boolean` | 268 | 269 | #### Parameters 270 | 271 | | Parameter | Type | 272 | | :-------- | :--- | 273 | | `value` | `T` | 274 | 275 | #### Returns 276 | 277 | `SQL`\<`T`> 278 | 279 | --- 280 | 281 | 282 | 283 | ### add() 284 | 285 | ```ts 286 | function add(...values: T): SQL : T[number]>; 287 | ``` 288 | 289 | Add values. 290 | 291 | #### Type parameters 292 | 293 | | Type parameter | 294 | | :------------------------------------------ | 295 | | `T` _extends_ (`number` \| `SQLWrapper`)\[] | 296 | 297 | #### Parameters 298 | 299 | | Parameter | Type | 300 | | :---------- | :--- | 301 | | ...`values` | `T` | 302 | 303 | #### Returns 304 | 305 | `SQL`\<`T`\[`number`] _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`any`\[`any`]> : 306 | `T`\[`number`]> 307 | 308 | --- 309 | 310 | 311 | 312 | ### cases() 313 | 314 | ```ts 315 | function cases(conditionals: C, fallback?: F): SQL; 316 | ``` 317 | 318 | Case condition chain. 319 | 320 | #### Type parameters 321 | 322 | | Type parameter | Value | 323 | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------- | 324 | | `C` _extends_ (`undefined` \| \[`SQLWrapper`, `unknown`])\[] | - | 325 | | `F` | - | 326 | | `T` | `NonUndefinable`\<`TupleToUnion`\<`C`>> | 327 | | `R` | `T` _extends_ \[`T0`, `T1`] ? `T0` _extends_ `SQL`\< | 328 | | \| `null` | | 329 | | \| `false` | | 330 | | \| `0` | | 331 | | \| `"0"` | | 332 | | \| `"f"` | | 333 | | \| `"F"`> ? `never` : `T1` _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`T1`\<`T1`>> : `T1` : `never` \| `F` _extends_ `void` ? `never` : `F` _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`F`\<`F`>> : `F` | | 334 | 335 | #### Parameters 336 | 337 | | Parameter | Type | 338 | | :------------- | :--- | 339 | | `conditionals` | `C` | 340 | | `fallback`? | `F` | 341 | 342 | #### Returns 343 | 344 | `SQL`\<`R`> 345 | 346 | #### Examples 347 | 348 | ```ts 349 | cases([[eq(thing, other), 2]], 3); 350 | ``` 351 | 352 | ```sql 353 | CASE 354 | WHEN thing = other THEN 2 355 | ELSE 3 356 | END; 357 | ``` 358 | 359 | #### Todo 360 | 361 | Implement smarter typing to identify confirmable early returns with truthy conditions. 362 | 363 | --- 364 | 365 | 366 | 367 | ### coalesce() 368 | 369 | ```ts 370 | function coalesce(...values: [...T[]]): SQL>; 371 | ``` 372 | 373 | #### Type parameters 374 | 375 | | Type parameter | 376 | | :------------------------- | 377 | | `T` _extends_ `unknown`\[] | 378 | 379 | #### Parameters 380 | 381 | | Parameter | Type | 382 | | :---------- | :---------- | 383 | | ...`values` | \[`...T[]`] | 384 | 385 | #### Returns 386 | 387 | `SQL`\<`CoalesceSQL`\<`T`, `true`, `never`>> 388 | 389 | #### See 390 | 391 | [https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-COALESCE-NVL-IFNULL](https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-COALESCE-NVL-IFNULL) 392 | 393 | --- 394 | 395 | 396 | 397 | ### distinct() 398 | 399 | ```ts 400 | function distinct(statement: T): SQL>; 401 | ``` 402 | 403 | Distinct keyword. 404 | 405 | #### Type parameters 406 | 407 | | Type parameter | 408 | | :------------------------- | 409 | | `T` _extends_ `SQLWrapper` | 410 | 411 | #### Parameters 412 | 413 | | Parameter | Type | 414 | | :---------- | :--- | 415 | | `statement` | `T` | 416 | 417 | #### Returns 418 | 419 | `SQL`\<[`InferData`](README.md#inferdatat)\<`T`>> 420 | 421 | --- 422 | 423 | 424 | 425 | ### divide() 426 | 427 | ```ts 428 | function divide( 429 | ...values: T 430 | ): SQL : T[number]>; 431 | ``` 432 | 433 | Divide values. 434 | 435 | #### Type parameters 436 | 437 | | Type parameter | 438 | | :------------------------------------------ | 439 | | `T` _extends_ (`number` \| `SQLWrapper`)\[] | 440 | 441 | #### Parameters 442 | 443 | | Parameter | Type | 444 | | :---------- | :--- | 445 | | ...`values` | `T` | 446 | 447 | #### Returns 448 | 449 | `SQL`\<`T`\[`number`] _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`any`\[`any`]> : 450 | `T`\[`number`]> 451 | 452 | --- 453 | 454 | 455 | 456 | ### getColumns() 457 | 458 | ```ts 459 | function getColumns(table: T): InferColumns; 460 | ``` 461 | 462 | Should replace `getTableColumns` to allow for more input versatility. 463 | 464 | #### Type parameters 465 | 466 | | Type parameter | 467 | | :---------------------------------------------------------------- | 468 | | `T` _extends_ | 469 | | \| `Table`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> | 470 | | \| `View`\<`string`, `boolean`, `ColumnsSelection`> | 471 | | \| [`AnySelect`](README.md#anyselect) | 472 | | \| `Subquery`\<`string`, `ColumnsSelection`> | 473 | | \| `WithSubquery`\<`string`, `ColumnsSelection`> | 474 | 475 | #### Parameters 476 | 477 | | Parameter | Type | 478 | | :-------- | :--- | 479 | | `table` | `T` | 480 | 481 | #### Returns 482 | 483 | [`InferColumns`](README.md#infercolumnst)\<`T`> 484 | 485 | #### See 486 | 487 | [drizzle-team/drizzle-orm#1789](https://github.com/drizzle-team/drizzle-orm/pull/1789) 488 | 489 | --- 490 | 491 | 492 | 493 | ### getNameOrAlias() 494 | 495 | ```ts 496 | function getNameOrAlias(query: T): InferNameOrAlias; 497 | ``` 498 | 499 | Get a table's name or a (sub)query's alias. 500 | 501 | #### Type parameters 502 | 503 | | Type parameter | 504 | | :------------------------- | 505 | | `T` _extends_ `SQLWrapper` | 506 | 507 | #### Parameters 508 | 509 | | Parameter | Type | 510 | | :-------- | :--- | 511 | | `query` | `T` | 512 | 513 | #### Returns 514 | 515 | [`InferNameOrAlias`](README.md#infernameoraliast)\<`T`> 516 | 517 | --- 518 | 519 | 520 | 521 | ### greatest() 522 | 523 | ```ts 524 | function greatest( 525 | ...values: [...T[]] 526 | ): SQL< 527 | { 528 | [I in string | number | symbol]: T[I] extends SQLWrapper ? InferData : T[I]; 529 | }[number] 530 | >; 531 | ``` 532 | 533 | #### Type parameters 534 | 535 | | Type parameter | 536 | | :------------------------- | 537 | | `T` _extends_ `unknown`\[] | 538 | 539 | #### Parameters 540 | 541 | | Parameter | Type | 542 | | :---------- | :---------- | 543 | | ...`values` | \[`...T[]`] | 544 | 545 | #### Returns 546 | 547 | `SQL`\<\{ \[I in string | number | symbol]: T\[I\] extends SQLWrapper ? InferData\ : 548 | T\[I\] }\[`number`]> 549 | 550 | #### See 551 | 552 | [https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST](https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST) 553 | 554 | --- 555 | 556 | 557 | 558 | ### least() 559 | 560 | ```ts 561 | function least( 562 | ...values: [...T[]] 563 | ): SQL< 564 | { 565 | [I in string | number | symbol]: T[I] extends SQLWrapper ? InferData : T[I]; 566 | }[number] 567 | >; 568 | ``` 569 | 570 | #### Type parameters 571 | 572 | | Type parameter | 573 | | :------------------------- | 574 | | `T` _extends_ `unknown`\[] | 575 | 576 | #### Parameters 577 | 578 | | Parameter | Type | 579 | | :---------- | :---------- | 580 | | ...`values` | \[`...T[]`] | 581 | 582 | #### Returns 583 | 584 | `SQL`\<\{ \[I in string | number | symbol]: T\[I\] extends SQLWrapper ? InferData\ : 585 | T\[I\] }\[`number`]> 586 | 587 | #### See 588 | 589 | [https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST](https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST) 590 | 591 | --- 592 | 593 | 594 | 595 | ### multiply() 596 | 597 | ```ts 598 | function multiply( 599 | ...values: T 600 | ): SQL : T[number]>; 601 | ``` 602 | 603 | Multiply values. 604 | 605 | #### Type parameters 606 | 607 | | Type parameter | 608 | | :------------------------------------------ | 609 | | `T` _extends_ (`number` \| `SQLWrapper`)\[] | 610 | 611 | #### Parameters 612 | 613 | | Parameter | Type | 614 | | :---------- | :--- | 615 | | ...`values` | `T` | 616 | 617 | #### Returns 618 | 619 | `SQL`\<`T`\[`number`] _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`any`\[`any`]> : 620 | `T`\[`number`]> 621 | 622 | --- 623 | 624 | 625 | 626 | ### nullIf() 627 | 628 | ```ts 629 | function nullIf(value: V, condition: C): SQL; 630 | ``` 631 | 632 | Return null if value meets condition. Useful to coalesce to something else. 633 | 634 | #### Type parameters 635 | 636 | | Type parameter | 637 | | :------------------------- | 638 | | `V` _extends_ `SQLWrapper` | 639 | | `C` | 640 | 641 | #### Parameters 642 | 643 | | Parameter | Type | 644 | | :---------- | :--- | 645 | | `value` | `V` | 646 | | `condition` | `C` | 647 | 648 | #### Returns 649 | 650 | `SQL`\<`null` | `V`> 651 | 652 | #### See 653 | 654 | [https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-NULLIF](https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-NULLIF) 655 | 656 | --- 657 | 658 | 659 | 660 | ### paginate() 661 | 662 | ```ts 663 | function paginate(qb: T, __namedParameters: object): PgSelect | MySqlSelect | SQLiteSelect; 664 | ``` 665 | 666 | Paginate a query. 667 | 668 | #### Type parameters 669 | 670 | | Type parameter | 671 | | :----------------------------------------- | 672 | | `T` _extends_ [`Select`](README.md#select) | 673 | 674 | #### Parameters 675 | 676 | | Parameter | Type | 677 | | :------------------------ | :------- | 678 | | `qb` | `T` | 679 | | `__namedParameters` | `object` | 680 | | `__namedParameters.page` | `number` | 681 | | `__namedParameters.size`? | `number` | 682 | 683 | #### Returns 684 | 685 | `PgSelect` | `MySqlSelect` | `SQLiteSelect` 686 | 687 | --- 688 | 689 | 690 | 691 | ### subtract() 692 | 693 | ```ts 694 | function subtract( 695 | ...values: T 696 | ): SQL : T[number]>; 697 | ``` 698 | 699 | Subtract values. 700 | 701 | #### Type parameters 702 | 703 | | Type parameter | 704 | | :------------------------------------------ | 705 | | `T` _extends_ (`number` \| `SQLWrapper`)\[] | 706 | 707 | #### Parameters 708 | 709 | | Parameter | Type | 710 | | :---------- | :--- | 711 | | ...`values` | `T` | 712 | 713 | #### Returns 714 | 715 | `SQL`\<`T`\[`number`] _extends_ `SQLWrapper` ? [`InferData`](README.md#inferdatat)\<`any`\[`any`]> : 716 | `T`\[`number`]> 717 | -------------------------------------------------------------------------------- /documentation/mysql.md: -------------------------------------------------------------------------------- 1 | # src/mysql 2 | 3 | ## Table of Contents 4 | 5 | - [Functions](#functions) 6 | - [random()](#random) 7 | 8 | ## Functions 9 | 10 | 11 | 12 | ### random() 13 | 14 | ```ts 15 | function random(): SQL; 16 | ``` 17 | 18 | MySQL random function. 19 | 20 | #### Returns 21 | 22 | `SQL`\<`number`> 23 | 24 | Random number between 0 and 1. 25 | 26 | #### Example 27 | 28 | ```sql 29 | rand(); 30 | ``` 31 | -------------------------------------------------------------------------------- /documentation/pg.md: -------------------------------------------------------------------------------- 1 | # src/pg 2 | 3 | ## Table of Contents 4 | 5 | - [Type Aliases](#type-aliases) 6 | - [IntervalUnit](#intervalunit) 7 | - [RangeBoundType](#rangeboundtype) 8 | - [RangeValue\](#rangevaluet) 9 | - [Regconfig](#regconfig) 10 | - [RegconfigString](#regconfigstring) 11 | - [Variables](#variables) 12 | - [$empty](#empty) 13 | - [$emptyArray](#emptyarray) 14 | - [$emptyJsonArray](#emptyjsonarray) 15 | - [$emptyJsonObject](#emptyjsonobject) 16 | - [$nullArray](#nullarray) 17 | - [INTERVAL_UNITS](#interval_units) 18 | - [INTERVAL_UNITS_ARR_ORDERED](#interval_units_arr_ordered) 19 | - [RANGE_BOUND_TYPES](#range_bound_types) 20 | - [RANGE_EMPTY](#range_empty) 21 | - [REGCONFIGS](#regconfigs) 22 | - [Functions](#functions) 23 | - [age()](#age) 24 | - [arrayAgg()](#arrayagg) 25 | - [boolAnd()](#booland) 26 | - [boolOr()](#boolor) 27 | - [citext()](#citext) 28 | - [contained()](#contained) 29 | - [contains()](#contains) 30 | - [cube()](#cube) 31 | - [cubeDim()](#cubedim) 32 | - [cubeDistance()](#cubedistance) 33 | - [cubeEnlarge()](#cubeenlarge) 34 | - [cubeInter()](#cubeinter) 35 | - [cubeIsPoint()](#cubeispoint) 36 | - [cubeLowerLeftCoord()](#cubelowerleftcoord) 37 | - [cubeSubset()](#cubesubset) 38 | - [cubeUnion()](#cubeunion) 39 | - [cubeUpperRightCoord()](#cubeupperrightcoord) 40 | - [daitch_mokotoff()](#daitch_mokotoff) 41 | - [daterange()](#daterange) 42 | - [daterangeSchema()](#daterangeschema) 43 | - [difference()](#difference) 44 | - [distance()](#distance) 45 | - [extract()](#extract) 46 | - [generatedTsvector()](#generatedtsvector) 47 | - [geography()](#geography) 48 | - [geometry()](#geometry) 49 | - [getCurrentTsConfig()](#getcurrenttsconfig) 50 | - [intrange()](#intrange) 51 | - [intrangeSchema()](#intrangeschema) 52 | - [isEmpty()](#isempty) 53 | - [jsonAgg()](#jsonagg) 54 | - [jsonAggBuildObject()](#jsonaggbuildobject) 55 | - [jsonBuildObject()](#jsonbuildobject) 56 | - [jsonObjectAgg()](#jsonobjectagg) 57 | - [jsonStripNulls()](#jsonstripnulls) 58 | - [jsonbBuildObject()](#jsonbbuildobject) 59 | - [jsonbObjectAgg()](#jsonbobjectagg) 60 | - [makeCube()](#makecube) 61 | - [nanoid()](#nanoid) 62 | - [now()](#now) 63 | - [numrange()](#numrange) 64 | - [numrangeSchema()](#numrangeschema) 65 | - [overlaps()](#overlaps) 66 | - [random()](#random) 67 | - [regconfig()](#regconfig-1) 68 | - [rowToJson()](#rowtojson) 69 | - [setweight()](#setweight) 70 | - [similar()](#similar) 71 | - [soundex()](#soundex) 72 | - [textenum()](#textenum) 73 | - [toExcluded()](#toexcluded) 74 | - [toInterval()](#tointerval) 75 | - [toJson()](#tojson) 76 | - [toJsonb()](#tojsonb) 77 | - [toRange()](#torange) 78 | - [toTsquery()](#totsquery) 79 | - [toTsvector()](#totsvector) 80 | - [ts()](#ts) 81 | - [tsrange()](#tsrange) 82 | - [tsrangeSchema()](#tsrangeschema) 83 | - [tsvector()](#tsvector) 84 | 85 | ## Type Aliases 86 | 87 | 88 | 89 | ### IntervalUnit 90 | 91 | ```ts 92 | type IntervalUnit: ValueOf; 93 | ``` 94 | 95 | --- 96 | 97 | 98 | 99 | ### RangeBoundType 100 | 101 | ```ts 102 | type RangeBoundType: ValueOf; 103 | ``` 104 | 105 | --- 106 | 107 | 108 | 109 | ### RangeValue\ 110 | 111 | ```ts 112 | type RangeValue: object; 113 | ``` 114 | 115 | #### Type parameters 116 | 117 | | Type parameter | Value | 118 | | :------------- | :----- | 119 | | `T` | `void` | 120 | 121 | #### Type declaration 122 | 123 | | Member | Type | 124 | | :------ | :------------ | 125 | | `lower` | `T` \| `null` | 126 | | `upper` | `T` \| `null` | 127 | 128 | --- 129 | 130 | 131 | 132 | ### Regconfig 133 | 134 | ```ts 135 | type Regconfig: ValueOf; 136 | ``` 137 | 138 | --- 139 | 140 | 141 | 142 | ### RegconfigString 143 | 144 | ```ts 145 | type RegconfigString: Regconfig | string & NonNullable; 146 | ``` 147 | 148 | ## Variables 149 | 150 | 151 | 152 | ### $empty 153 | 154 | ```ts 155 | const $empty: SQL<[] | "'empty'">; 156 | ``` 157 | 158 | Postgres value returned for empty ranges. 159 | 160 | --- 161 | 162 | 163 | 164 | ### $emptyArray 165 | 166 | ```ts 167 | const $emptyArray: SQL<[]>; 168 | ``` 169 | 170 | Empty SQL array (not json typed) 171 | 172 | --- 173 | 174 | 175 | 176 | ### $emptyJsonArray 177 | 178 | ```ts 179 | const $emptyJsonArray: SQL<[never]>; 180 | ``` 181 | 182 | Empty array as SQL json. 183 | 184 | --- 185 | 186 | 187 | 188 | ### $emptyJsonObject 189 | 190 | ```ts 191 | const $emptyJsonObject: SQL; 192 | ``` 193 | 194 | Empty record as SQL json. 195 | 196 | --- 197 | 198 | 199 | 200 | ### $nullArray 201 | 202 | ```ts 203 | const $nullArray: SQL<[null]>; 204 | ``` 205 | 206 | An array with a single null member. Typically returned when aggregation result is empty. 207 | 208 | --- 209 | 210 | 211 | 212 | ### INTERVAL_UNITS 213 | 214 | ```ts 215 | const INTERVAL_UNITS: object; 216 | ``` 217 | 218 | #### Type declaration 219 | 220 | | Member | Type | Value | 221 | | :-------- | :---------- | :-------- | 222 | | `DAYS` | `"days"` | 'days' | 223 | | `HOURS` | `"hours"` | 'hours' | 224 | | `MINUTES` | `"minutes"` | 'minutes' | 225 | | `MONTHS` | `"months"` | 'months' | 226 | | `SECONDS` | `"seconds"` | 'seconds' | 227 | | `WEEKS` | `"weeks"` | 'weeks' | 228 | | `YEARS` | `"years"` | 'years' | 229 | 230 | --- 231 | 232 | 233 | 234 | ### INTERVAL_UNITS_ARR_ORDERED 235 | 236 | ```ts 237 | const INTERVAL_UNITS_ARR_ORDERED: readonly [ 238 | 'years', 239 | 'months', 240 | 'weeks', 241 | 'days', 242 | 'hours', 243 | 'minutes', 244 | 'seconds', 245 | ]; 246 | ``` 247 | 248 | --- 249 | 250 | 251 | 252 | ### RANGE_BOUND_TYPES 253 | 254 | ```ts 255 | const RANGE_BOUND_TYPES: object; 256 | ``` 257 | 258 | #### Type declaration 259 | 260 | | Member | Type | Value | 261 | | :---------- | :------------ | :---------- | 262 | | `EXCLUSIVE` | `"exclusive"` | 'exclusive' | 263 | | `INCLUSIVE` | `"inclusive"` | 'inclusive' | 264 | 265 | --- 266 | 267 | 268 | 269 | ### RANGE_EMPTY 270 | 271 | ```ts 272 | const RANGE_EMPTY: object; 273 | ``` 274 | 275 | Value for app-side representation of empty postgres ranges. 276 | 277 | #### Type declaration 278 | 279 | | Member | Type | Value | 280 | | :------ | :----- | :---- | 281 | | `lower` | `null` | null | 282 | | `upper` | `null` | null | 283 | 284 | --- 285 | 286 | 287 | 288 | ### REGCONFIGS 289 | 290 | ```ts 291 | const REGCONFIGS: object; 292 | ``` 293 | 294 | Postgres regconfig cfgnames. 295 | 296 | #### Example 297 | 298 | ```sql 299 | SELECT json_object_agg(upper(cfgname), cfgname) 300 | FROM pg_catalog.pg_ts_config; 301 | ``` 302 | 303 | #### Type declaration 304 | 305 | | Member | Type | Value | 306 | | :----------- | :------------- | :----------- | 307 | | `ARABIC` | `"arabic"` | 'arabic' | 308 | | `ARMENIAN` | `"armenian"` | 'armenian' | 309 | | `BASQUE` | `"basque"` | 'basque' | 310 | | `CATALAN` | `"catalan"` | 'catalan' | 311 | | `DANISH` | `"danish"` | 'danish' | 312 | | `DUTCH` | `"dutch"` | 'dutch' | 313 | | `ENGLISH` | `"english"` | 'english' | 314 | | `FINNISH` | `"finnish"` | 'finnish' | 315 | | `FRENCH` | `"french"` | 'french' | 316 | | `GERMAN` | `"german"` | 'german' | 317 | | `GREEK` | `"greek"` | 'greek' | 318 | | `HINDI` | `"hindi"` | 'hindi' | 319 | | `HUNGARIAN` | `"hungarian"` | 'hungarian' | 320 | | `INDONESIAN` | `"indonesian"` | 'indonesian' | 321 | | `IRISH` | `"irish"` | 'irish' | 322 | | `ITALIAN` | `"italian"` | 'italian' | 323 | | `LITHUANIAN` | `"lithuanian"` | 'lithuanian' | 324 | | `NEPALI` | `"nepali"` | 'nepali' | 325 | | `NORWEGIAN` | `"norwegian"` | 'norwegian' | 326 | | `PORTUGUESE` | `"portuguese"` | 'portuguese' | 327 | | `ROMANIAN` | `"romanian"` | 'romanian' | 328 | | `RUSSIAN` | `"russian"` | 'russian' | 329 | | `SERBIAN` | `"serbian"` | 'serbian' | 330 | | `SIMPLE` | `"simple"` | 'simple' | 331 | | `SPANISH` | `"spanish"` | 'spanish' | 332 | | `SWEDISH` | `"swedish"` | 'swedish' | 333 | | `TAMIL` | `"tamil"` | 'tamil' | 334 | | `TURKISH` | `"turkish"` | 'turkish' | 335 | | `YIDDISH` | `"yiddish"` | 'yiddish' | 336 | 337 | ## Functions 338 | 339 | 340 | 341 | ### age() 342 | 343 | ```ts 344 | function age(origin: TOrigin, target: TTarget): SQL; 345 | ``` 346 | 347 | Subtract arguments, producing a “symbolic” result that uses years and months, rather than just days. 348 | 349 | #### Type parameters 350 | 351 | | Type parameter | 352 | | :----------------------------------------- | 353 | | `TOrigin` _extends_ `SQLWrapper` \| `Date` | 354 | | `TTarget` _extends_ `SQLWrapper` \| `Date` | 355 | 356 | #### Parameters 357 | 358 | | Parameter | Type | 359 | | :-------- | :-------- | 360 | | `origin` | `TOrigin` | 361 | | `target` | `TTarget` | 362 | 363 | #### Returns 364 | 365 | `SQL`\<`string`> 366 | 367 | #### Example 368 | 369 | ```sql 370 | -- age ( timestamp, timestamp ) → interval 371 | age(timestamp '2001-04-10', timestamp '1957-06-13') → 43 years 9 mons 27 days 372 | ``` 373 | 374 | --- 375 | 376 | 377 | 378 | ### arrayAgg() 379 | 380 | ```ts 381 | function arrayAgg(expression: T): SQL>; 382 | ``` 383 | 384 | Aggregate sql values into an sql array. 385 | 386 | Input values, including nulls, concatenated into an array. 387 | 388 | Input arrays concatenated into array of one higher dimension (inputs must all have same 389 | dimensionality, and cannot be empty or null) 390 | 391 | #### Type parameters 392 | 393 | | Type parameter | 394 | | :------------------------- | 395 | | `T` _extends_ `SQLWrapper` | 396 | 397 | #### Parameters 398 | 399 | | Parameter | Type | 400 | | :----------- | :--- | 401 | | `expression` | `T` | 402 | 403 | #### Returns 404 | 405 | `SQL`\<`null` | [`InferData`](README.md#inferdatat)\<`T`>> 406 | 407 | #### See 408 | 409 | [https://www.postgresql.org/docs/9.5/functions-aggregate.html](https://www.postgresql.org/docs/9.5/functions-aggregate.html) 410 | 411 | #### Todo 412 | 413 | Implement collapsing for null array with notNull option. 414 | 415 | --- 416 | 417 | 418 | 419 | ### boolAnd() 420 | 421 | ```ts 422 | function boolAnd(...expression: SQLWrapper[]): SQL; 423 | ``` 424 | 425 | True if all input values are true, otherwise false. 426 | 427 | #### Parameters 428 | 429 | | Parameter | Type | 430 | | :-------------- | :-------------- | 431 | | ...`expression` | `SQLWrapper`\[] | 432 | 433 | #### Returns 434 | 435 | `SQL`\<`boolean`> 436 | 437 | --- 438 | 439 | 440 | 441 | ### boolOr() 442 | 443 | ```ts 444 | function boolOr(...expression: SQLWrapper[]): SQL; 445 | ``` 446 | 447 | True if at least one input value is true, otherwise false. 448 | 449 | #### Parameters 450 | 451 | | Parameter | Type | 452 | | :-------------- | :-------------- | 453 | | ...`expression` | `SQLWrapper`\[] | 454 | 455 | #### Returns 456 | 457 | `SQL`\<`boolean`> 458 | 459 | --- 460 | 461 | 462 | 463 | ### citext() 464 | 465 | ```ts 466 | function citext(dbName: TName, fieldConfig?: unknown): PgCustomColumnBuilder; 467 | ``` 468 | 469 | Ci-text postgres column type. 470 | 471 | #### Type parameters 472 | 473 | | Type parameter | 474 | | :------------------------- | 475 | | `TName` _extends_ `string` | 476 | 477 | #### Parameters 478 | 479 | | Parameter | Type | 480 | | :------------- | :-------- | 481 | | `dbName` | `TName` | 482 | | `fieldConfig`? | `unknown` | 483 | 484 | #### Returns 485 | 486 | `PgCustomColumnBuilder`\<`object`> 487 | 488 | | Member | Type | 489 | | :------------ | :----------------- | 490 | | `columnType` | `"PgCustomColumn"` | 491 | | `data` | `string` | 492 | | `dataType` | `"custom"` | 493 | | `driverParam` | `unknown` | 494 | | `enumValues` | `undefined` | 495 | | `name` | `TName` | 496 | 497 | #### See 498 | 499 | [https://www.postgresql.org/docs/current/citext.html](https://www.postgresql.org/docs/current/citext.html) 500 | 501 | --- 502 | 503 | 504 | 505 | ### contained() 506 | 507 | ```ts 508 | function contained(left: SQLWrapper, right: unknown): SQL; 509 | ``` 510 | 511 | Is the first cube contained in the second? 512 | 513 | #### Parameters 514 | 515 | | Parameter | Type | 516 | | :-------- | :----------- | 517 | | `left` | `SQLWrapper` | 518 | | `right` | `unknown` | 519 | 520 | #### Returns 521 | 522 | `SQL`\<`unknown`> 523 | 524 | #### Example 525 | 526 | ```sql 527 | cube <@ cube → boolean 528 | ``` 529 | 530 | --- 531 | 532 | 533 | 534 | ### contains() 535 | 536 | ```ts 537 | function contains(left: SQLWrapper, right: unknown): SQL; 538 | ``` 539 | 540 | Does the first cube contain the second? 541 | 542 | #### Parameters 543 | 544 | | Parameter | Type | 545 | | :-------- | :----------- | 546 | | `left` | `SQLWrapper` | 547 | | `right` | `unknown` | 548 | 549 | #### Returns 550 | 551 | `SQL`\<`unknown`> 552 | 553 | #### Example 554 | 555 | ```sql 556 | cube @> cube → boolean 557 | ``` 558 | 559 | --- 560 | 561 | 562 | 563 | ### cube() 564 | 565 | ```ts 566 | function cube(dbName: TName, fieldConfig?: unknown): PgCustomColumnBuilder; 567 | ``` 568 | 569 | Postgres cube column type with customizable amount of dimensions. 570 | 571 | #### Type parameters 572 | 573 | | Type parameter | 574 | | :------------------------- | 575 | | `TName` _extends_ `string` | 576 | 577 | #### Parameters 578 | 579 | | Parameter | Type | 580 | | :------------- | :-------- | 581 | | `dbName` | `TName` | 582 | | `fieldConfig`? | `unknown` | 583 | 584 | #### Returns 585 | 586 | `PgCustomColumnBuilder`\<`object`> 587 | 588 | | Member | Type | 589 | | :------------ | :----------------------------------------- | 590 | | `columnType` | `"PgCustomColumn"` | 591 | | `data` | `number`\[] \| \[`number`\[], `number`\[]] | 592 | | `dataType` | `"custom"` | 593 | | `driverParam` | `number`\[] \| \[`number`\[], `number`\[]] | 594 | | `enumValues` | `undefined` | 595 | | `name` | `TName` | 596 | 597 | #### See 598 | 599 | [https://www.postgresql.org/docs/current/cube.html](https://www.postgresql.org/docs/current/cube.html) 600 | 601 | --- 602 | 603 | 604 | 605 | ### cubeDim() 606 | 607 | ```ts 608 | function cubeDim(cube: SQLWrapper): SQL; 609 | ``` 610 | 611 | Returns the number of dimensions of the cube. 612 | 613 | #### Parameters 614 | 615 | | Parameter | Type | 616 | | :-------- | :----------- | 617 | | `cube` | `SQLWrapper` | 618 | 619 | #### Returns 620 | 621 | `SQL`\<`number`> 622 | 623 | #### Example 624 | 625 | ```sql 626 | --cube_dim ( cube ) → integer 627 | cube_dim('(1,2),(3,4)') → 2 628 | ``` 629 | 630 | --- 631 | 632 | 633 | 634 | ### cubeDistance() 635 | 636 | ```ts 637 | function cubeDistance(...cubes: [SQLWrapper, SQLWrapper]): SQL; 638 | ``` 639 | 640 | Returns the distance between two cubes. If both cubes are points, this is the normal distance 641 | function. 642 | 643 | #### Parameters 644 | 645 | | Parameter | Type | 646 | | :--------- | :---------------------------- | 647 | | ...`cubes` | \[`SQLWrapper`, `SQLWrapper`] | 648 | 649 | #### Returns 650 | 651 | `SQL`\<`number`> 652 | 653 | #### Example 654 | 655 | ```sql 656 | -- cube_distance ( cube, cube ) → float8 657 | cube_distance('(1,2)', '(3,4)') → 2.8284271247461903 658 | ``` 659 | 660 | --- 661 | 662 | 663 | 664 | ### cubeEnlarge() 665 | 666 | ```ts 667 | function cubeEnlarge(): void; 668 | ``` 669 | 670 | Increases the size of the cube by the specified radius r in at least n dimensions. If the radius is 671 | negative the cube is shrunk instead. All defined dimensions are changed by the radius r. Lower-left 672 | coordinates are decreased by r and upper-right coordinates are increased by r. If a lower-left 673 | coordinate is increased to more than the corresponding upper-right coordinate (this can only happen 674 | when r \< 0) than both coordinates are set to their average. If n is greater than the number of 675 | defined dimensions and the cube is being enlarged (r > 0), then extra dimensions are added to make n 676 | altogether; 0 is used as the initial value for the extra coordinates. This function is useful for 677 | creating bounding boxes around a point for searching for nearby points. 678 | 679 | #### Returns 680 | 681 | `void` 682 | 683 | #### Example 684 | 685 | ```sql 686 | -- cube_enlarge ( c cube, r double, n integer ) → cube 687 | cube_enlarge('(1,2),(3,4)', 0.5, 3) → (0.5, 1.5, -0.5),(3.5, 4.5, 0.5) 688 | ``` 689 | 690 | --- 691 | 692 | 693 | 694 | ### cubeInter() 695 | 696 | ```ts 697 | function cubeInter(): void; 698 | ``` 699 | 700 | Produces the intersection of two cubes. 701 | 702 | #### Returns 703 | 704 | `void` 705 | 706 | #### Example 707 | 708 | ```sql 709 | -- cube_inter ( cube, cube ) → cube 710 | cube_inter('(1,2)', '(3,4)') → (3, 4),(1, 2) 711 | ``` 712 | 713 | --- 714 | 715 | 716 | 717 | ### cubeIsPoint() 718 | 719 | ```ts 720 | function cubeIsPoint(cube: SQLWrapper): SQL; 721 | ``` 722 | 723 | Returns true if the cube is a point, that is, the two defining corners are the same. 724 | 725 | #### Parameters 726 | 727 | | Parameter | Type | 728 | | :-------- | :----------- | 729 | | `cube` | `SQLWrapper` | 730 | 731 | #### Returns 732 | 733 | `SQL`\<`boolean`> 734 | 735 | #### Example 736 | 737 | ```sql 738 | -- cube_is_point ( cube ) → boolean 739 | cube_is_point(cube(1,1)) → t 740 | ``` 741 | 742 | --- 743 | 744 | 745 | 746 | ### cubeLowerLeftCoord() 747 | 748 | ```ts 749 | function cubeLowerLeftCoord(): void; 750 | ``` 751 | 752 | Returns the n-th coordinate value for the lower left corner of the cube. 753 | 754 | #### Returns 755 | 756 | `void` 757 | 758 | #### Example 759 | 760 | ```sql 761 | -- cube_ll_coord ( cube, integer ) → float8 762 | cube_ll_coord('(1,2),(3,4)', 2) → 2 763 | ``` 764 | 765 | --- 766 | 767 | 768 | 769 | ### cubeSubset() 770 | 771 | ```ts 772 | function cubeSubset(): void; 773 | ``` 774 | 775 | Makes a new cube from an existing cube, using a list of dimension indexes from an array. Can be used 776 | to extract the endpoints of a single dimension, or to drop dimensions, or to reorder them as 777 | desired. 778 | 779 | #### Returns 780 | 781 | `void` 782 | 783 | #### Example 784 | 785 | ```sql 786 | cube_subset ( cube, integer[] ) → cube 787 | cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) → (3),(7) 788 | cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) → (5, 3, 1, 1),(8, 7, 6, 6) 789 | ``` 790 | 791 | --- 792 | 793 | 794 | 795 | ### cubeUnion() 796 | 797 | ```ts 798 | function cubeUnion(): void; 799 | ``` 800 | 801 | Produces the union of two cubes. 802 | 803 | #### Returns 804 | 805 | `void` 806 | 807 | #### Example 808 | 809 | ```sql 810 | -- cube_union ( cube, cube ) → cube 811 | cube_union('(1,2)', '(3,4)') → (1, 2),(3, 4) 812 | ``` 813 | 814 | --- 815 | 816 | 817 | 818 | ### cubeUpperRightCoord() 819 | 820 | ```ts 821 | function cubeUpperRightCoord(): void; 822 | ``` 823 | 824 | ``` 825 | Returns the n-th coordinate value for the upper right corner of the cube. 826 | ``` 827 | 828 | #### Returns 829 | 830 | `void` 831 | 832 | #### Example 833 | 834 | ```sql 835 | -- cube_ur_coord ( cube, integer ) → float8 836 | cube_ur_coord('(1,2),(3,4)', 2) → 4 837 | ``` 838 | 839 | --- 840 | 841 | 842 | 843 | ### daitch_mokotoff() 844 | 845 | ```ts 846 | function daitch_mokotoff(source: string | SQLWrapper): SQL; 847 | ``` 848 | 849 | #### Parameters 850 | 851 | | Parameter | Type | 852 | | :-------- | :----------------------- | 853 | | `source` | `string` \| `SQLWrapper` | 854 | 855 | #### Returns 856 | 857 | `SQL`\<`string`\[]> 858 | 859 | #### See 860 | 861 | [https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF](https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF) 862 | 863 | --- 864 | 865 | 866 | 867 | ### daterange() 868 | 869 | ```ts 870 | function daterange( 871 | name: TName, 872 | config?: TConfig 873 | ): PgCustomColumnBuilder; 874 | ``` 875 | 876 | Implements postgres date range. 877 | 878 | #### Type parameters 879 | 880 | | Type parameter | Value | 881 | | :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | 882 | | `TName` _extends_ `string` | - | 883 | | `TConfig` _extends_ `object` | - | 884 | | `TData` | `TConfig`\[`"mode"`] _extends_ `"string"` ? [`RangeValue`](src/pg.md#rangevaluet)\<`string`> : [`RangeValue`](src/pg.md#rangevaluet)\<`number` \| `Date`> | 885 | 886 | #### Parameters 887 | 888 | | Parameter | Type | 889 | | :-------- | :-------- | 890 | | `name` | `TName` | 891 | | `config`? | `TConfig` | 892 | 893 | #### Returns 894 | 895 | `PgCustomColumnBuilder`\<`object`> 896 | 897 | | Member | Type | 898 | | :------------ | :----------------- | 899 | | `columnType` | `"PgCustomColumn"` | 900 | | `data` | `TData` | 901 | | `dataType` | `"custom"` | 902 | | `driverParam` | `string` | 903 | | `enumValues` | `undefined` | 904 | | `name` | `TName` | 905 | 906 | #### See 907 | 908 | - [https://orm.drizzle.team/docs/custom-types](https://orm.drizzle.team/docs/custom-types) Timestamp 909 | for reference. 910 | - [https://www.postgresql.org/docs/current/rangetypes.html](https://www.postgresql.org/docs/current/rangetypes.html) 911 | 912 | --- 913 | 914 | 915 | 916 | ### daterangeSchema() 917 | 918 | ```ts 919 | function daterangeSchema( 920 | __namedParameters: object 921 | ): ZodObject< 922 | object, 923 | 'strip', 924 | ZodTypeAny, 925 | { [k in 'lower' | 'upper']: addQuestionMarks, any>[k] }, 926 | object 927 | >; 928 | ``` 929 | 930 | #### Type parameters 931 | 932 | | Type parameter | Value | 933 | | :--------------------------------------- | :----------------------------------------------------------- | 934 | | `TMode` _extends_ `"string"` \| `"date"` | - | 935 | | `TData` | `TMode` _extends_ `"string"` ? `string` : `number` \| `Date` | 936 | 937 | #### Parameters 938 | 939 | | Parameter | Type | 940 | | :------------------------ | :------- | 941 | | `__namedParameters` | `object` | 942 | | `__namedParameters.max`? | `Date` | 943 | | `__namedParameters.min`? | `Date` | 944 | | `__namedParameters.mode`? | `TMode` | 945 | 946 | #### Returns 947 | 948 | `ZodObject`\<`object`, `"strip"`, `ZodTypeAny`, \{ \[k in "lower" | "upper"]: 949 | addQuestionMarks\, any>\[k] }, `object`> 950 | 951 | | Member | Type | Value | 952 | | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------- | 953 | | `lower` | `ZodEffects`\<`ZodNullable`\<`ZodDate`>, `TData`, `null` \| `Date`> \| `ZodEffects`\<`ZodNullable`\<`ZodUnion`\<\[`ZodDate`, `ZodNumber`]>>, `TData`, `null` \| `number` \| `Date`> | lowerSchema | 954 | | `upper` | `ZodEffects`\<`ZodNullable`\<`ZodDate`>, `TData`, `null` \| `Date`> \| `ZodEffects`\<`ZodNullable`\<`ZodUnion`\<\[`ZodDate`, `ZodNumber`]>>, `TData`, `null` \| `number` \| `Date`> | upperSchema | 955 | 956 | --- 957 | 958 | 959 | 960 | ### difference() 961 | 962 | ```ts 963 | function difference(...texts: [string | SQLWrapper, string | SQLWrapper]): SQL; 964 | ``` 965 | 966 | #### Parameters 967 | 968 | | Parameter | Type | 969 | | :--------- | :---------------------------------------------------- | 970 | | ...`texts` | \[`string` \| `SQLWrapper`, `string` \| `SQLWrapper`] | 971 | 972 | #### Returns 973 | 974 | `SQL`\<`number`> 975 | 976 | #### See 977 | 978 | [https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF](https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF) 979 | 980 | --- 981 | 982 | 983 | 984 | ### distance() 985 | 986 | ```ts 987 | function distance(left: SQLWrapper, right: unknown, __namedParameters: object): SQL; 988 | ``` 989 | 990 | Computes the distance between two cubes. 991 | 992 | #### Parameters 993 | 994 | | Parameter | Type | 995 | | :------------------------ | :------------- | 996 | | `left` | `SQLWrapper` | 997 | | `right` | `unknown` | 998 | | `__namedParameters` | `object` | 999 | | `__namedParameters.type`? | `DistanceType` | 1000 | 1001 | #### Returns 1002 | 1003 | `SQL`\<`unknown`> 1004 | 1005 | #### Examples 1006 | 1007 | ```sql 1008 | -- Computes the Euclidean distance between the two cubes. 1009 | cube <-> cube → float8 1010 | ``` 1011 | 1012 | ```sql 1013 | -- Computes the taxicab (L-1 metric) distance between the two cubes. 1014 | cube <#> cube → float8 1015 | ``` 1016 | 1017 | ```sql 1018 | -- Computes the Chebyshev (L-inf metric) distance between the two cubes. 1019 | cube <=> cube → float8 1020 | ``` 1021 | 1022 | --- 1023 | 1024 | 1025 | 1026 | ### extract() 1027 | 1028 | ```ts 1029 | function extract(left: SQLWrapper, right: unknown): SQL; 1030 | ``` 1031 | 1032 | Extracts the n-th coordinate of the cube (counting from 1). 1033 | 1034 | #### Parameters 1035 | 1036 | | Parameter | Type | 1037 | | :-------- | :----------- | 1038 | | `left` | `SQLWrapper` | 1039 | | `right` | `unknown` | 1040 | 1041 | #### Returns 1042 | 1043 | `SQL`\<`unknown`> 1044 | 1045 | #### Examples 1046 | 1047 | ```sql 1048 | cube -> integer → float8 1049 | ``` 1050 | 1051 | Extracts the n-th coordinate of the cube, counting in the following way: n = 2 \* k - 1 means lower 1052 | bound of k-th dimension, n = 2 \* k means upper bound of k-th dimension. Negative n denotes the 1053 | inverse value of the corresponding positive coordinate. This operator is designed for KNN-GiST 1054 | support. 1055 | 1056 | ```sql 1057 | cube ~> integer → float8 1058 | ``` 1059 | 1060 | --- 1061 | 1062 | 1063 | 1064 | ### generatedTsvector() 1065 | 1066 | ```ts 1067 | function generatedTsvector( 1068 | dbName: TName, 1069 | fieldConfig: object 1070 | ): PgCustomColumnBuilder; 1071 | ``` 1072 | 1073 | Tsvector type for generated columns used notably for fuzzy string search. 1074 | 1075 | #### Type parameters 1076 | 1077 | | Type parameter | 1078 | | :------------------------- | 1079 | | `TName` _extends_ `string` | 1080 | 1081 | #### Parameters 1082 | 1083 | | Parameter | Type | 1084 | | :---------------------- | :----------------------- | 1085 | | `dbName` | `TName` | 1086 | | `fieldConfig` | `object` | 1087 | | `fieldConfig.language` | `string` \| `SQLWrapper` | 1088 | | `fieldConfig.sources` | `string`\[] | 1089 | | `fieldConfig.weighted`? | `boolean` | 1090 | 1091 | #### Returns 1092 | 1093 | `PgCustomColumnBuilder`\<`object`> 1094 | 1095 | | Member | Type | 1096 | | :------------ | :----------------- | 1097 | | `columnType` | `"PgCustomColumn"` | 1098 | | `data` | `string` | 1099 | | `dataType` | `"custom"` | 1100 | | `driverParam` | `unknown` | 1101 | | `enumValues` | `undefined` | 1102 | | `name` | `TName` | 1103 | 1104 | #### See 1105 | 1106 | [drizzle-team/drizzle-orm#247](https://github.com/drizzle-team/drizzle-orm/issues/247) 1107 | 1108 | #### Todo 1109 | 1110 | Implementation isn't clean. Figure out a better way to map the language name and column references, 1111 | or stay up to date on support for `generatedAs()`. 1112 | 1113 | --- 1114 | 1115 | 1116 | 1117 | ### geography() 1118 | 1119 | ```ts 1120 | function geography( 1121 | name: TName, 1122 | config?: object 1123 | ): PgCustomColumnBuilder; 1124 | ``` 1125 | 1126 | PostGIS column type for generic or specific geographies. 1127 | 1128 | **⚠️ Warning ⚠️** 1129 | 1130 | Uses a nasty trick to get the data back as properly formatted GeoJSON rather than WKT. Expect things 1131 | to break. 1132 | 1133 | #### Type parameters 1134 | 1135 | | Type parameter | 1136 | | :------------------------- | 1137 | | `TName` _extends_ `string` | 1138 | | `TGeography` _extends_ | 1139 | | \| `"Point"` | 1140 | | \| `"MultiPoint"` | 1141 | | \| `"LineString"` | 1142 | | \| `"MultiLineString"` | 1143 | | \| `"Polygon"` | 1144 | | \| `"MultiPolygon"` | 1145 | | \| `"GeometryCollection"` | 1146 | | `TZ` _extends_ `boolean` | 1147 | | `TM` _extends_ `boolean` | 1148 | | `TSrid` _extends_ `Srid` | 1149 | 1150 | #### Parameters 1151 | 1152 | | Parameter | Type | 1153 | | :------------- | :----------- | 1154 | | `name` | `TName` | 1155 | | `config`? | `object` | 1156 | | `config.m`? | `TM` | 1157 | | `config.srid`? | `TSrid` | 1158 | | `config.type`? | `TGeography` | 1159 | | `config.z`? | `TZ` | 1160 | 1161 | #### Returns 1162 | 1163 | `PgCustomColumnBuilder`\<`object`> 1164 | 1165 | | Member | Type | 1166 | | :--------------------------------------------------------- | :------------------------------------------- | 1167 | | `columnType` | `"PgCustomColumn"` | 1168 | | `data` | | 1169 | | \| `Extract`\<`Point`, `object`> | | 1170 | | \| `Extract`\<`MultiPoint`, `object`> | | 1171 | | \| `Extract`\<`LineString`, `object`> | | 1172 | | \| `Extract`\<`MultiLineString`, `object`> | | 1173 | | \| `Extract`\<`Polygon`, `object`> | | 1174 | | \| `Extract`\<`MultiPolygon`, `object`> | | 1175 | | \| `Extract`\<`GeometryCollection`\<`Geometry`>, `object`> | | 1176 | | `dataType` | `"custom"` | 1177 | | `driverParam` | `string` | 1178 | | `enumValues` | `undefined` | 1179 | | `name` | \`st_asgeojson"("$\{TName}") as "$\{TName}\` | 1180 | 1181 | #### See 1182 | 1183 | Unstable until better support for custom type custom select is available (e.g. 1184 | [drizzle-team/drizzle-orm#1423](https://github.com/drizzle-team/drizzle-orm/pull/1423)) 1185 | 1186 | --- 1187 | 1188 | 1189 | 1190 | ### geometry() 1191 | 1192 | ```ts 1193 | function geometry( 1194 | name: TName, 1195 | config?: object 1196 | ): PgCustomColumnBuilder; 1197 | ``` 1198 | 1199 | - PostGIS column type for generic or specific geometries. 1200 | 1201 | **⚠️ Warning ⚠️** 1202 | 1203 | Uses a nasty trick to get the data back as properly formatted GeoJSON rather than WKT. Expect things 1204 | to break. 1205 | 1206 | #### Type parameters 1207 | 1208 | | Type parameter | 1209 | | :------------------------- | 1210 | | `TName` _extends_ `string` | 1211 | | `TGeometry` _extends_ | 1212 | | \| `"Point"` | 1213 | | \| `"MultiPoint"` | 1214 | | \| `"LineString"` | 1215 | | \| `"MultiLineString"` | 1216 | | \| `"Polygon"` | 1217 | | \| `"MultiPolygon"` | 1218 | | \| `"GeometryCollection"` | 1219 | | `TZ` _extends_ `boolean` | 1220 | | `TM` _extends_ `boolean` | 1221 | | `TSrid` _extends_ `Srid` | 1222 | 1223 | #### Parameters 1224 | 1225 | | Parameter | Type | 1226 | | :------------- | :---------- | 1227 | | `name` | `TName` | 1228 | | `config`? | `object` | 1229 | | `config.m`? | `TM` | 1230 | | `config.srid`? | `TSrid` | 1231 | | `config.type`? | `TGeometry` | 1232 | | `config.z`? | `TZ` | 1233 | 1234 | #### Returns 1235 | 1236 | `PgCustomColumnBuilder`\<`object`> 1237 | 1238 | | Member | Type | 1239 | | :--------------------------------------------------------- | :------------------------------------------- | 1240 | | `columnType` | `"PgCustomColumn"` | 1241 | | `data` | | 1242 | | \| `Extract`\<`Point`, `object`> | | 1243 | | \| `Extract`\<`MultiPoint`, `object`> | | 1244 | | \| `Extract`\<`LineString`, `object`> | | 1245 | | \| `Extract`\<`MultiLineString`, `object`> | | 1246 | | \| `Extract`\<`Polygon`, `object`> | | 1247 | | \| `Extract`\<`MultiPolygon`, `object`> | | 1248 | | \| `Extract`\<`GeometryCollection`\<`Geometry`>, `object`> | | 1249 | | `dataType` | `"custom"` | 1250 | | `driverParam` | `string` | 1251 | | `enumValues` | `undefined` | 1252 | | `name` | \`st_asgeojson"("$\{TName}") as "$\{TName}\` | 1253 | 1254 | #### See 1255 | 1256 | Unstable until better support for custom type custom select is available (e.g. 1257 | [drizzle-team/drizzle-orm#1423](https://github.com/drizzle-team/drizzle-orm/pull/1423)) 1258 | 1259 | --- 1260 | 1261 | 1262 | 1263 | ### getCurrentTsConfig() 1264 | 1265 | ```ts 1266 | function getCurrentTsConfig(): SQL; 1267 | ``` 1268 | 1269 | Get the database's currently set regconfig for text-search functionalities. 1270 | 1271 | ```sql 1272 | get_current_ts_config(); 1273 | ``` 1274 | 1275 | #### Returns 1276 | 1277 | `SQL`\<[`RegconfigString`](src/pg.md#regconfigstring)> 1278 | 1279 | --- 1280 | 1281 | 1282 | 1283 | ### intrange() 1284 | 1285 | ```ts 1286 | function intrange(name: TName, config?: TConfig): PgCustomColumnBuilder; 1287 | ``` 1288 | 1289 | Implements postgres int4range and int8range types. 1290 | 1291 | #### Type parameters 1292 | 1293 | | Type parameter | 1294 | | :--------------------------- | 1295 | | `TName` _extends_ `string` | 1296 | | `TConfig` _extends_ `object` | 1297 | 1298 | #### Parameters 1299 | 1300 | | Parameter | Type | 1301 | | :-------- | :-------- | 1302 | | `name` | `TName` | 1303 | | `config`? | `TConfig` | 1304 | 1305 | #### Returns 1306 | 1307 | `PgCustomColumnBuilder`\<`object`> 1308 | 1309 | | Member | Type | 1310 | | :------------ | :----------------------------------------------- | 1311 | | `columnType` | `"PgCustomColumn"` | 1312 | | `data` | [`RangeValue`](src/pg.md#rangevaluet)\<`number`> | 1313 | | `dataType` | `"custom"` | 1314 | | `driverParam` | `string` | 1315 | | `enumValues` | `undefined` | 1316 | | `name` | `TName` | 1317 | 1318 | #### See 1319 | 1320 | [https://www.postgresql.org/docs/current/rangetypes.html](https://www.postgresql.org/docs/current/rangetypes.html) 1321 | 1322 | --- 1323 | 1324 | 1325 | 1326 | ### intrangeSchema() 1327 | 1328 | ```ts 1329 | function intrangeSchema( 1330 | __namedParameters: object 1331 | ): ZodObject; 1332 | ``` 1333 | 1334 | #### Parameters 1335 | 1336 | | Parameter | Type | 1337 | | :----------------------- | :------- | 1338 | | `__namedParameters` | `object` | 1339 | | `__namedParameters.max`? | `number` | 1340 | | `__namedParameters.min`? | `number` | 1341 | 1342 | #### Returns 1343 | 1344 | `ZodObject`\<`object`, `"strip"`, `ZodTypeAny`, `object`, `object`> 1345 | 1346 | | Member | Type | Value | 1347 | | :------ | :-------------------------- | :---------- | 1348 | | `lower` | `ZodNullable`\<`ZodNumber`> | lowerSchema | 1349 | | `upper` | `ZodNullable`\<`ZodNumber`> | upperSchema | 1350 | 1351 | --- 1352 | 1353 | 1354 | 1355 | ### isEmpty() 1356 | 1357 | ```ts 1358 | function isEmpty(range: T): SQL; 1359 | ``` 1360 | 1361 | #### Type parameters 1362 | 1363 | | Type parameter | 1364 | | :---------------------- | 1365 | | `T` _extends_ `unknown` | 1366 | 1367 | #### Parameters 1368 | 1369 | | Parameter | Type | 1370 | | :-------- | :--- | 1371 | | `range` | `T` | 1372 | 1373 | #### Returns 1374 | 1375 | `SQL`\<`boolean`> 1376 | 1377 | --- 1378 | 1379 | 1380 | 1381 | ### jsonAgg() 1382 | 1383 | ```ts 1384 | function jsonAgg( 1385 | selection: T, 1386 | __namedParameters: object 1387 | ): SQL>[] : InferData[] | [null]>; 1388 | ``` 1389 | 1390 | Aggregates values, including nulls, as a JSON array. 1391 | 1392 | #### Type parameters 1393 | 1394 | | Type parameter | Value | 1395 | | :------------------------- | :----- | 1396 | | `T` _extends_ `SQLWrapper` | - | 1397 | | `N` _extends_ `boolean` | `true` | 1398 | 1399 | #### Parameters 1400 | 1401 | | Parameter | Type | 1402 | | :--------------------------- | :------- | 1403 | | `selection` | `T` | 1404 | | `__namedParameters` | `object` | 1405 | | `__namedParameters.notNull`? | `N` | 1406 | 1407 | #### Returns 1408 | 1409 | `SQL`\<`N` _extends_ `true` ? `NonNullable`\<[`InferData`](README.md#inferdatat)\<`T`>>\[] : 1410 | [`InferData`](README.md#inferdatat)\<`T`>\[] | \[`null`]> 1411 | 1412 | #### See 1413 | 1414 | [https://www.postgresql.org/docs/9.5/functions-aggregate.html](https://www.postgresql.org/docs/9.5/functions-aggregate.html) 1415 | 1416 | --- 1417 | 1418 | 1419 | 1420 | ### jsonAggBuildObject() 1421 | 1422 | ```ts 1423 | function jsonAggBuildObject( 1424 | shape: T, 1425 | __namedParameters: object 1426 | ): SQL<{ [K in string | number | symbol]: T[K] extends SQLWrapper ? InferData : T[K] }[]>; 1427 | ``` 1428 | 1429 | Aggregate sql values into an array of json objects using a combination of `json_agg` and 1430 | `jsonb_build_object`. Jsonb object building is used in lieu of json to allow use of distinct. 1431 | 1432 | #### Type parameters 1433 | 1434 | | Type parameter | 1435 | | :------------------------------- | 1436 | | `T` _extends_ `ColumnsSelection` | 1437 | 1438 | #### Parameters 1439 | 1440 | | Parameter | Type | 1441 | | :---------------------------- | :-------- | 1442 | | `shape` | `T` | 1443 | | `__namedParameters` | `object` | 1444 | | `__namedParameters.distinct`? | `boolean` | 1445 | 1446 | #### Returns 1447 | 1448 | `SQL`\<\{ \[K in string | number | symbol]: T\[K] extends SQLWrapper ? InferData\ : T\[K] 1449 | }\[]> 1450 | 1451 | --- 1452 | 1453 | 1454 | 1455 | ### jsonBuildObject() 1456 | 1457 | ```ts 1458 | function jsonBuildObject( 1459 | shape: T 1460 | ): SQL<{ [K in string | number | symbol]: T[K] extends SQLWrapper ? InferData : T[K] }>; 1461 | ``` 1462 | 1463 | Build objects using \`json_build_object(k1, v1, ...kn, vn). Since it is a json method, it should 1464 | return an object with unwrapped value types instead of SQL wrapped types. 1465 | 1466 | #### Type parameters 1467 | 1468 | | Type parameter | 1469 | | :------------------------------- | 1470 | | `T` _extends_ `ColumnsSelection` | 1471 | 1472 | #### Parameters 1473 | 1474 | | Parameter | Type | 1475 | | :-------- | :--- | 1476 | | `shape` | `T` | 1477 | 1478 | #### Returns 1479 | 1480 | `SQL`\<\{ \[K in string | number | symbol]: T\[K] extends SQLWrapper ? InferData\ : T\[K] 1481 | }> 1482 | 1483 | --- 1484 | 1485 | 1486 | 1487 | ### jsonObjectAgg() 1488 | 1489 | ```ts 1490 | function jsonObjectAgg(name: K, value: V): SQL>; 1491 | ``` 1492 | 1493 | Aggregates name/value pairs as a JSON object; values can be null, but not names. 1494 | 1495 | Build object using `json_object_agg`. Since it is a json method, it should return an unwrapped type 1496 | instead of an SQL wrapped type. 1497 | 1498 | #### Type parameters 1499 | 1500 | | Type parameter | Value | 1501 | | :---------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 1502 | | `K` _extends_ `AnyColumn` | - | 1503 | | `V` _extends_ `SQL`\<`unknown`> \| `Aliased`\<`unknown`> \| `AnyTable`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> | - | 1504 | | `TK` _extends_ `string` \| `number` | `null` _extends_ [`InferData`](README.md#inferdatat)\<`K`> ? `never` : [`InferData`](README.md#inferdatat)\<`K`> _extends_ `string` \| `number` ? [`InferData`](README.md#inferdatat)\<[`InferData`](README.md#inferdatat)\<`K`>> : `never` | 1505 | | `TV` | `V` _extends_ `AnyTable`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> ? \{ \[K in string]: \{ \[Key in string as Key]: V\<(...)>\["\_"]\["columns"]\[Key]\["\_"]\["notNull"] extends true ? V\<(...)>\["\_"]\["columns"]\[Key]\["\_"]\["data"] : null \| (...)\[(...)]\["columns"]\[Key]\["\_"]\["data"] }\[K] } : `V` _extends_ `SQL`\<`unknown`> ? [`InferData`](README.md#inferdatat)\<`V`\<`V`>> : `never` | 1506 | 1507 | #### Parameters 1508 | 1509 | | Parameter | Type | 1510 | | :-------- | :--- | 1511 | | `name` | `K` | 1512 | | `value` | `V` | 1513 | 1514 | #### Returns 1515 | 1516 | `SQL`\<`Record`\<`TK`, `TV`>> 1517 | 1518 | #### Example 1519 | 1520 | ```sql 1521 | json_object_agg(...) 1522 | ``` 1523 | 1524 | #### See 1525 | 1526 | [https://www.postgresql.org/docs/9.5/functions-aggregate.html](https://www.postgresql.org/docs/9.5/functions-aggregate.html) 1527 | 1528 | --- 1529 | 1530 | 1531 | 1532 | ### jsonStripNulls() 1533 | 1534 | ```ts 1535 | function jsonStripNulls( 1536 | json: T 1537 | ): SQL< 1538 | SetNonNullable< 1539 | T extends SQLWrapper ? InferData> : T, 1540 | keyof T extends SQLWrapper ? InferData> : T 1541 | > 1542 | >; 1543 | ``` 1544 | 1545 | SQL json_strip_nulls. 1546 | 1547 | #### Type parameters 1548 | 1549 | | Type parameter | 1550 | | :------------- | 1551 | | `T` | 1552 | 1553 | #### Parameters 1554 | 1555 | | Parameter | Type | 1556 | | :-------- | :--- | 1557 | | `json` | `T` | 1558 | 1559 | #### Returns 1560 | 1561 | `SQL`\<`SetNonNullable`\<`T` _extends_ `SQLWrapper` ? 1562 | [`InferData`](README.md#inferdatat)\<`T`\<`T`>> : `T`, keyof `T` _extends_ `SQLWrapper` ? 1563 | [`InferData`](README.md#inferdatat)\<`T`\<`T`>> : `T`>> 1564 | 1565 | --- 1566 | 1567 | 1568 | 1569 | ### jsonbBuildObject() 1570 | 1571 | ```ts 1572 | function jsonbBuildObject( 1573 | shape: T 1574 | ): SQL<{ [K in string | number | symbol]: T[K] extends SQLWrapper ? InferData : T[K] }>; 1575 | ``` 1576 | 1577 | Build objects using \`jsonb_build_object(k1, v1, ...kn, vn). Since it is a jsonb method, it should 1578 | return an object with unwrapped value types instead of SQL wrapped types. 1579 | 1580 | #### Type parameters 1581 | 1582 | | Type parameter | 1583 | | :------------------------------- | 1584 | | `T` _extends_ `ColumnsSelection` | 1585 | 1586 | #### Parameters 1587 | 1588 | | Parameter | Type | 1589 | | :-------- | :--- | 1590 | | `shape` | `T` | 1591 | 1592 | #### Returns 1593 | 1594 | `SQL`\<\{ \[K in string | number | symbol]: T\[K] extends SQLWrapper ? InferData\ : T\[K] 1595 | }> 1596 | 1597 | --- 1598 | 1599 | 1600 | 1601 | ### jsonbObjectAgg() 1602 | 1603 | ```ts 1604 | function jsonbObjectAgg(name: K, value: V): SQL>; 1605 | ``` 1606 | 1607 | Aggregates name/value pairs as a JSON object; values can be null, but not names. 1608 | 1609 | #### Type parameters 1610 | 1611 | | Type parameter | Value | 1612 | | :---------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 1613 | | `K` _extends_ `AnyColumn` | - | 1614 | | `V` _extends_ `SQL`\<`unknown`> \| `Aliased`\<`unknown`> \| `AnyTable`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> | - | 1615 | | `TK` _extends_ `string` \| `number` | `null` _extends_ [`InferData`](README.md#inferdatat)\<`K`> ? `never` : [`InferData`](README.md#inferdatat)\<`K`> _extends_ `string` \| `number` ? [`InferData`](README.md#inferdatat)\<[`InferData`](README.md#inferdatat)\<`K`>> : `never` | 1616 | | `TV` | `V` _extends_ `AnyTable`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> ? \{ \[K in string]: \{ \[Key in string as Key]: V\<(...)>\["\_"]\["columns"]\[Key]\["\_"]\["notNull"] extends true ? V\<(...)>\["\_"]\["columns"]\[Key]\["\_"]\["data"] : null \| (...)\[(...)]\["columns"]\[Key]\["\_"]\["data"] }\[K] } : `V` _extends_ `SQL`\<`unknown`> ? [`InferData`](README.md#inferdatat)\<`V`\<`V`>> : `never` | 1617 | 1618 | #### Parameters 1619 | 1620 | | Parameter | Type | 1621 | | :-------- | :--- | 1622 | | `name` | `K` | 1623 | | `value` | `V` | 1624 | 1625 | #### Returns 1626 | 1627 | `SQL`\<`Record`\<`TK`, `TV`>> 1628 | 1629 | #### Example 1630 | 1631 | ```sql 1632 | jsonb_object_agg(...) 1633 | ``` 1634 | 1635 | #### See 1636 | 1637 | [https://www.postgresql.org/docs/9.5/functions-aggregate.html](https://www.postgresql.org/docs/9.5/functions-aggregate.html) 1638 | 1639 | --- 1640 | 1641 | 1642 | 1643 | ### makeCube() 1644 | 1645 | ```ts 1646 | function makeCube(...args: T): SQL; 1647 | ``` 1648 | 1649 | Makes a one dimensional cube with both coordinates the same. 1650 | 1651 | #### Type parameters 1652 | 1653 | | Type parameter | 1654 | | :------------------------------------- | 1655 | | `T` _extends_ | 1656 | | \| `number`\[] | 1657 | | \| \[`number`\[], `number`\[]] | 1658 | | \| \[`number`] | 1659 | | \| \[`number`, `number`] | 1660 | | \| \[`SQLWrapper`, `number`] | 1661 | | \| \[`SQLWrapper`, `number`, `number`] | 1662 | 1663 | #### Parameters 1664 | 1665 | | Parameter | Type | 1666 | | :-------- | :--- | 1667 | | ...`args` | `T` | 1668 | 1669 | #### Returns 1670 | 1671 | `SQL`\<`number`\[]> 1672 | 1673 | #### Examples 1674 | 1675 | ```sql 1676 | -- cube ( float8 ) → cube 1677 | cube(1) → (1) 1678 | ``` 1679 | 1680 | Makes a one dimensional cube. 1681 | 1682 | ```sql 1683 | -- cube ( float8, float8 ) → cube 1684 | cube(1, 2) → (1),(2) 1685 | ``` 1686 | 1687 | Makes a zero-volume cube using the coordinates defined by the array. 1688 | 1689 | ```sql 1690 | -- cube ( float8[] ) → cube 1691 | cube(ARRAY[1,2,3]) → (1, 2, 3) 1692 | ``` 1693 | 1694 | Makes a cube with upper right and lower left coordinates as defined by the two arrays, which must be 1695 | of the same length. 1696 | 1697 | ```sql 1698 | -- cube ( float8[], float8[] ) → cube 1699 | cube(ARRAY[1,2], ARRAY[3,4]) → (1, 2),(3, 4) 1700 | ``` 1701 | 1702 | Makes a new cube by adding a dimension on to an existing cube, with the same values for both 1703 | endpoints of the new coordinate. This is useful for building cubes piece by piece from calculated 1704 | values. 1705 | 1706 | ```sql 1707 | -- cube ( cube, float8 ) → cube 1708 | cube('(1,2),(3,4)'::cube, 5) → (1, 2, 5),(3, 4, 5) 1709 | ``` 1710 | 1711 | Makes a new cube by adding a dimension on to an existing cube. This is useful for building cubes 1712 | piece by piece from calculated values. 1713 | 1714 | ```sql 1715 | --cube ( cube, float8, float8 ) → cube 1716 | cube('(1,2),(3,4)'::cube, 5, 6) → (1, 2, 5),(3, 4, 6) 1717 | ``` 1718 | 1719 | --- 1720 | 1721 | 1722 | 1723 | ### nanoid() 1724 | 1725 | ```ts 1726 | function nanoid(__namedParameters: (object & object) | object): SQL; 1727 | ``` 1728 | 1729 | Generate a nanoid using a postgres implementation of the nanoid function. 1730 | 1731 | #### Parameters 1732 | 1733 | | Parameter | Type | 1734 | | :------------------ | :------------------------------ | 1735 | | `__namedParameters` | `object` & `object` \| `object` | 1736 | 1737 | #### Returns 1738 | 1739 | `SQL`\<`string`> 1740 | 1741 | #### See 1742 | 1743 | - [Postgres implementation of the nanoid generator](https://github.com/iolyd/drizzle-orm-helpers/blob/main/sql/nanoid.sql) 1744 | - [https://discord.com/channels/1043890932593987624/1093946807911989369/1100459226087825571](https://discord.com/channels/1043890932593987624/1093946807911989369/1100459226087825571) 1745 | 1746 | #### Todo 1747 | 1748 | Stay up to date when default values will accept 'sql' without having to pass param to sql.raw() 1749 | 1750 | --- 1751 | 1752 | 1753 | 1754 | ### now() 1755 | 1756 | ```ts 1757 | function now(): SQL; 1758 | ``` 1759 | 1760 | Get the current time (dynamically). 1761 | 1762 | #### Returns 1763 | 1764 | `SQL`\<`Date`> 1765 | 1766 | #### Example 1767 | 1768 | ```sql 1769 | now(); 1770 | ``` 1771 | 1772 | --- 1773 | 1774 | 1775 | 1776 | ### numrange() 1777 | 1778 | ```ts 1779 | function numrange(name: TName, config?: TConfig): PgCustomColumnBuilder; 1780 | ``` 1781 | 1782 | Implements postgres numrange type. 1783 | 1784 | #### Type parameters 1785 | 1786 | | Type parameter | 1787 | | :--------------------------- | 1788 | | `TName` _extends_ `string` | 1789 | | `TConfig` _extends_ `object` | 1790 | 1791 | #### Parameters 1792 | 1793 | | Parameter | Type | 1794 | | :-------- | :-------- | 1795 | | `name` | `TName` | 1796 | | `config`? | `TConfig` | 1797 | 1798 | #### Returns 1799 | 1800 | `PgCustomColumnBuilder`\<`object`> 1801 | 1802 | | Member | Type | 1803 | | :------------ | :----------------------------------------------- | 1804 | | `columnType` | `"PgCustomColumn"` | 1805 | | `data` | [`RangeValue`](src/pg.md#rangevaluet)\<`number`> | 1806 | | `dataType` | `"custom"` | 1807 | | `driverParam` | `string` | 1808 | | `enumValues` | `undefined` | 1809 | | `name` | `TName` | 1810 | 1811 | #### See 1812 | 1813 | [https://www.postgresql.org/docs/current/rangetypes.html](https://www.postgresql.org/docs/current/rangetypes.html) 1814 | 1815 | --- 1816 | 1817 | 1818 | 1819 | ### numrangeSchema() 1820 | 1821 | ```ts 1822 | function numrangeSchema( 1823 | __namedParameters: object 1824 | ): ZodObject; 1825 | ``` 1826 | 1827 | #### Parameters 1828 | 1829 | | Parameter | Type | 1830 | | :----------------------- | :------- | 1831 | | `__namedParameters` | `object` | 1832 | | `__namedParameters.max`? | `number` | 1833 | | `__namedParameters.min`? | `number` | 1834 | 1835 | #### Returns 1836 | 1837 | `ZodObject`\<`object`, `"strip"`, `ZodTypeAny`, `object`, `object`> 1838 | 1839 | | Member | Type | Value | 1840 | | :------ | :-------------------------- | :---------- | 1841 | | `lower` | `ZodNullable`\<`ZodNumber`> | lowerSchema | 1842 | | `upper` | `ZodNullable`\<`ZodNumber`> | upperSchema | 1843 | 1844 | --- 1845 | 1846 | 1847 | 1848 | ### overlaps() 1849 | 1850 | ```ts 1851 | function overlaps(left: SQLWrapper, right: unknown): SQL; 1852 | ``` 1853 | 1854 | Do the cubes overlap? 1855 | 1856 | #### Parameters 1857 | 1858 | | Parameter | Type | 1859 | | :-------- | :----------- | 1860 | | `left` | `SQLWrapper` | 1861 | | `right` | `unknown` | 1862 | 1863 | #### Returns 1864 | 1865 | `SQL`\<`unknown`> 1866 | 1867 | #### Example 1868 | 1869 | ```sql 1870 | cube && cube → boolean 1871 | ``` 1872 | 1873 | --- 1874 | 1875 | 1876 | 1877 | ### random() 1878 | 1879 | ```ts 1880 | function random(): SQL; 1881 | ``` 1882 | 1883 | Postgres random function. 1884 | 1885 | #### Returns 1886 | 1887 | `SQL`\<`number`> 1888 | 1889 | Random number between 0 and 1. 1890 | 1891 | #### Example 1892 | 1893 | ```sql 1894 | random(); 1895 | ``` 1896 | 1897 | --- 1898 | 1899 | 1900 | 1901 | ### regconfig() 1902 | 1903 | ```ts 1904 | function regconfig(dbName: TName, fieldConfig?: unknown): PgCustomColumnBuilder; 1905 | ``` 1906 | 1907 | Implements Postgres regconfig. Useful for text search language config storage. 1908 | 1909 | #### Type parameters 1910 | 1911 | | Type parameter | 1912 | | :------------------------- | 1913 | | `TName` _extends_ `string` | 1914 | 1915 | #### Parameters 1916 | 1917 | | Parameter | Type | 1918 | | :------------- | :-------- | 1919 | | `dbName` | `TName` | 1920 | | `fieldConfig`? | `unknown` | 1921 | 1922 | #### Returns 1923 | 1924 | `PgCustomColumnBuilder`\<`object`> 1925 | 1926 | | Member | Type | 1927 | | :------------ | :--------------------------------- | 1928 | | `columnType` | `"PgCustomColumn"` | 1929 | | `data` | [`Regconfig`](src/pg.md#regconfig) | 1930 | | `dataType` | `"custom"` | 1931 | | `driverParam` | `unknown` | 1932 | | `enumValues` | `undefined` | 1933 | | `name` | `TName` | 1934 | 1935 | #### See 1936 | 1937 | [https://www.postgresql.org/docs/current/textsearch-controls.html](https://www.postgresql.org/docs/current/textsearch-controls.html) 1938 | 1939 | --- 1940 | 1941 | 1942 | 1943 | ### rowToJson() 1944 | 1945 | ```ts 1946 | function rowToJson(row: T): SQL>; 1947 | ``` 1948 | 1949 | Since it is a json method, it should return an unwrapped (raw) type instead of an SQL wrapped type. 1950 | 1951 | #### Type parameters 1952 | 1953 | | Type parameter | 1954 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 1955 | | `T` _extends_ `Table`\<`TableConfig`\<`Column`\<`any`, `object`, `object`>>> \| `View`\<`string`, `boolean`, `ColumnsSelection`> \| `Subquery`\<`string`, `Record`\<`string`, `unknown`>> | 1956 | 1957 | #### Parameters 1958 | 1959 | | Parameter | Type | 1960 | | :-------- | :--- | 1961 | | `row` | `T` | 1962 | 1963 | #### Returns 1964 | 1965 | `SQL`\<[`InferData`](README.md#inferdatat)\<`T`>> 1966 | 1967 | --- 1968 | 1969 | 1970 | 1971 | ### setweight() 1972 | 1973 | ```ts 1974 | function setweight(tsvector: SQLWrapper, weight: string | number): SQL; 1975 | ``` 1976 | 1977 | The function setweight can be used to label the entries of a tsvector with a given weight, where a 1978 | weight is one of the letters A, B, C, or D. This is typically used to mark entries coming from 1979 | different parts of a document, such as title versus body. Later, this information can be used for 1980 | ranking of search results. 1981 | 1982 | Because to_tsvector(NULL) will return NULL, it is recommended to use coalesce whenever a field might 1983 | be null. 1984 | 1985 | #### Parameters 1986 | 1987 | | Parameter | Type | 1988 | | :--------- | :------------------- | 1989 | | `tsvector` | `SQLWrapper` | 1990 | | `weight` | `string` \| `number` | 1991 | 1992 | #### Returns 1993 | 1994 | `SQL`\<`string`> 1995 | 1996 | --- 1997 | 1998 | 1999 | 2000 | ### similar() 2001 | 2002 | ```ts 2003 | function similar(): void; 2004 | ``` 2005 | 2006 | #### Returns 2007 | 2008 | `void` 2009 | 2010 | --- 2011 | 2012 | 2013 | 2014 | ### soundex() 2015 | 2016 | ```ts 2017 | function soundex(text: string | SQLWrapper): SQL; 2018 | ``` 2019 | 2020 | #### Parameters 2021 | 2022 | | Parameter | Type | 2023 | | :-------- | :----------------------- | 2024 | | `text` | `string` \| `SQLWrapper` | 2025 | 2026 | #### Returns 2027 | 2028 | `SQL`\<`string`> 2029 | 2030 | #### See 2031 | 2032 | [https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-SOUNDEX](https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-SOUNDEX) 2033 | 2034 | --- 2035 | 2036 | 2037 | 2038 | ### textenum() 2039 | 2040 | ```ts 2041 | function textenum( 2042 | name: TName, 2043 | config: TConfig 2044 | ): PgCustomColumnBuilder; 2045 | ``` 2046 | 2047 | Text-based enum with runtime check and type inferrence. In other words, similar to drizzle's own 2048 | `text` column with `config.enum` but this time with runtime peace-of mind. 2049 | 2050 | If you simply want a union-typed text without runtime safety of values, use drizzle's own `text` 2051 | with the `config.enum` configuration. 2052 | 2053 | #### Type parameters 2054 | 2055 | | Type parameter | 2056 | | :---------------------------------------------------- | 2057 | | `TName` _extends_ `string` | 2058 | | `TEnum` _extends_ `string`\[] \| readonly `string`\[] | 2059 | | `TConfig` _extends_ `object` | 2060 | 2061 | #### Parameters 2062 | 2063 | | Parameter | Type | 2064 | | :-------- | :-------- | 2065 | | `name` | `TName` | 2066 | | `config` | `TConfig` | 2067 | 2068 | #### Returns 2069 | 2070 | `PgCustomColumnBuilder`\<`object`> 2071 | 2072 | | Member | Type | 2073 | | :------------ | :------------------------------ | 2074 | | `columnType` | `"PgCustomColumn"` | 2075 | | `data` | `TConfig`\[`"enum"`]\[`number`] | 2076 | | `dataType` | `"custom"` | 2077 | | `driverParam` | `string` | 2078 | | `enumValues` | `undefined` | 2079 | | `name` | `TName` | 2080 | 2081 | #### See 2082 | 2083 | [https://orm.drizzle.team/docs/column-types/pg#text](https://orm.drizzle.team/docs/column-types/pg#text) 2084 | 2085 | --- 2086 | 2087 | 2088 | 2089 | ### toExcluded() 2090 | 2091 | ```ts 2092 | function toExcluded(columns: T): { [K in string | number | symbol]: SQL> }; 2093 | ``` 2094 | 2095 | Get excluded column values in conflict cases. Useful for onConflictDoUpdate's set. 2096 | 2097 | #### Type parameters 2098 | 2099 | | Type parameter | 2100 | | :--------------------------------------------- | 2101 | | `T` _extends_ `Record`\<`string`, `AnyColumn`> | 2102 | 2103 | #### Parameters 2104 | 2105 | | Parameter | Type | Description | 2106 | | :-------- | :--- | :------------------------------------------------------------- | 2107 | | `columns` | `T` | Record of columns to get from the conflict's `excluded` table. | 2108 | 2109 | #### Returns 2110 | 2111 | \{ \[K in string | number | symbol]: SQL\> } 2112 | 2113 | --- 2114 | 2115 | 2116 | 2117 | ### toInterval() 2118 | 2119 | ```ts 2120 | function toInterval(value: T): SQL; 2121 | ``` 2122 | 2123 | Create an interval value by passing a value deconstructed into time units. 2124 | 2125 | #### Type parameters 2126 | 2127 | | Type parameter | 2128 | | :-------------------------------------------------------------------------------------- | 2129 | | `T` _extends_ `Partial`\<`Record`\<[`IntervalUnit`](src/pg.md#intervalunit), `number`>> | 2130 | 2131 | #### Parameters 2132 | 2133 | | Parameter | Type | 2134 | | :-------- | :--- | 2135 | | `value` | `T` | 2136 | 2137 | #### Returns 2138 | 2139 | `SQL`\<`string`> 2140 | 2141 | --- 2142 | 2143 | 2144 | 2145 | ### toJson() 2146 | 2147 | ```ts 2148 | function toJson(anyelement: T): SQL>; 2149 | ``` 2150 | 2151 | #### Type parameters 2152 | 2153 | | Type parameter | 2154 | | :------------------------- | 2155 | | `T` _extends_ `SQLWrapper` | 2156 | 2157 | #### Parameters 2158 | 2159 | | Parameter | Type | 2160 | | :----------- | :--- | 2161 | | `anyelement` | `T` | 2162 | 2163 | #### Returns 2164 | 2165 | `SQL`\<[`InferData`](README.md#inferdatat)\<`T`>> 2166 | 2167 | #### See 2168 | 2169 | [https://www.postgresql.org/docs/9.5/functions-json.html#FUNCTIONS-JSON-CREATION-TABLE](https://www.postgresql.org/docs/9.5/functions-json.html#FUNCTIONS-JSON-CREATION-TABLE) 2170 | 2171 | --- 2172 | 2173 | 2174 | 2175 | ### toJsonb() 2176 | 2177 | ```ts 2178 | function toJsonb(anyelement: T): SQL>; 2179 | ``` 2180 | 2181 | #### Type parameters 2182 | 2183 | | Type parameter | 2184 | | :------------------------- | 2185 | | `T` _extends_ `SQLWrapper` | 2186 | 2187 | #### Parameters 2188 | 2189 | | Parameter | Type | 2190 | | :----------- | :--- | 2191 | | `anyelement` | `T` | 2192 | 2193 | #### Returns 2194 | 2195 | `SQL`\<[`InferData`](README.md#inferdatat)\<`T`>> 2196 | 2197 | --- 2198 | 2199 | 2200 | 2201 | ### toRange() 2202 | 2203 | ```ts 2204 | function toRange(tuple: T, __namedParameters: object): SQL; 2205 | ``` 2206 | 2207 | Using canonical form of included lower bound and excluded upper bound. See 2208 | [https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE). 2209 | 2210 | #### Type parameters 2211 | 2212 | | Type parameter | 2213 | | :------------------------------------------------------------------------------------------------------------------- | 2214 | | `T` _extends_ \[`undefined` \| `number`, `undefined` \| `number`] \| \[`undefined` \| `Date`, `undefined` \| `Date`] | 2215 | 2216 | #### Parameters 2217 | 2218 | | Parameter | Type | 2219 | | :------------------------------ | :------------------------------------------- | 2220 | | `tuple` | `T` | 2221 | | `__namedParameters` | `object` | 2222 | | `__namedParameters.lowerBound`? | [`RangeBoundType`](src/pg.md#rangeboundtype) | 2223 | | `__namedParameters.upperBound`? | [`RangeBoundType`](src/pg.md#rangeboundtype) | 2224 | 2225 | #### Returns 2226 | 2227 | `SQL`\<`T`> 2228 | 2229 | --- 2230 | 2231 | 2232 | 2233 | ### toTsquery() 2234 | 2235 | ```ts 2236 | function toTsquery(text: unknown, text: object): SQL; 2237 | ``` 2238 | 2239 | #### Parameters 2240 | 2241 | | Parameter | Type | Description | 2242 | | :---------------- | :------------------------------------------------------------- | :----------------------------------------------- | 2243 | | `text` | `unknown` | Source text to convert into a text search query. | 2244 | | `text` | `object` | Source text to convert into a text search query. | 2245 | | `text.plain`? | `boolean` | - | 2246 | | `text.regconfig`? | `SQLWrapper` \| [`RegconfigString`](src/pg.md#regconfigstring) | - | 2247 | 2248 | #### Returns 2249 | 2250 | `SQL`\<`string`> 2251 | 2252 | --- 2253 | 2254 | 2255 | 2256 | ### toTsvector() 2257 | 2258 | ```ts 2259 | function toTsvector(text: unknown, text: object): SQL; 2260 | ``` 2261 | 2262 | #### Parameters 2263 | 2264 | | Parameter | Type | Description | 2265 | | :---------------- | :------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | 2266 | | `text` | `unknown` |

Source text to convert into a text search vector.

to_tsvector();

--or;

plainto_tsvector();

| 2267 | | `text` | `object` |

Source text to convert into a text search vector.

to_tsvector();

--or;

plainto_tsvector();

| 2268 | | `text.regconfig`? | `SQLWrapper` \| [`RegconfigString`](src/pg.md#regconfigstring) | - | 2269 | 2270 | #### Returns 2271 | 2272 | `SQL`\<`string`> 2273 | 2274 | --- 2275 | 2276 |
2277 | 2278 | ### ts() 2279 | 2280 | ```ts 2281 | function ts(vector: SQLWrapper, querytext: SQLWrapper): SQL; 2282 | ``` 2283 | 2284 | Test a text search query against a ts_vector value. 2285 | 2286 | #### Parameters 2287 | 2288 | | Parameter | Type | 2289 | | :---------- | :----------- | 2290 | | `vector` | `SQLWrapper` | 2291 | | `querytext` | `SQLWrapper` | 2292 | 2293 | #### Returns 2294 | 2295 | `SQL`\<`unknown`> 2296 | 2297 | --- 2298 | 2299 | 2300 | 2301 | ### tsrange() 2302 | 2303 | ```ts 2304 | function tsrange( 2305 | name: TName, 2306 | config?: TConfig 2307 | ): PgCustomColumnBuilder; 2308 | ``` 2309 | 2310 | Implements Postgres timestamp range. 2311 | 2312 | #### Type parameters 2313 | 2314 | | Type parameter | Value | 2315 | | :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | 2316 | | `TName` _extends_ `string` | - | 2317 | | `TConfig` _extends_ `object` | - | 2318 | | `TData` | `TConfig`\[`"mode"`] _extends_ `"string"` ? [`RangeValue`](src/pg.md#rangevaluet)\<`string`> : [`RangeValue`](src/pg.md#rangevaluet)\<`number` \| `Date`> | 2319 | 2320 | #### Parameters 2321 | 2322 | | Parameter | Type | 2323 | | :-------- | :-------- | 2324 | | `name` | `TName` | 2325 | | `config`? | `TConfig` | 2326 | 2327 | #### Returns 2328 | 2329 | `PgCustomColumnBuilder`\<`object`> 2330 | 2331 | | Member | Type | 2332 | | :------------ | :----------------- | 2333 | | `columnType` | `"PgCustomColumn"` | 2334 | | `data` | `TData` | 2335 | | `dataType` | `"custom"` | 2336 | | `driverParam` | `string` | 2337 | | `enumValues` | `undefined` | 2338 | | `name` | `TName` | 2339 | 2340 | #### See 2341 | 2342 | - [https://www.postgresql.org/docs/current/rangetypes.html](https://www.postgresql.org/docs/current/rangetypes.html) 2343 | - [https://github.com/bendrucker/postgres-date](https://github.com/bendrucker/postgres-date) 2344 | 2345 | --- 2346 | 2347 | 2348 | 2349 | ### tsrangeSchema() 2350 | 2351 | ```ts 2352 | function tsrangeSchema( 2353 | __namedParameters: object 2354 | ): ZodObject< 2355 | object, 2356 | 'strip', 2357 | ZodTypeAny, 2358 | { [k in 'lower' | 'upper']: addQuestionMarks, any>[k] }, 2359 | object 2360 | >; 2361 | ``` 2362 | 2363 | Because of typescript's peculiar handling of Inifinity/-Infinity, ranges without limit need to 2364 | consider number members that indicate infinite bounds. 2365 | 2366 | #### Type parameters 2367 | 2368 | | Type parameter | Value | 2369 | | :--------------------------------------- | :----------------------------------------------------------- | 2370 | | `TMode` _extends_ `"string"` \| `"date"` | - | 2371 | | `TData` | `TMode` _extends_ `"string"` ? `string` : `number` \| `Date` | 2372 | 2373 | #### Parameters 2374 | 2375 | | Parameter | Type | 2376 | | :-------------------------------- | :-------- | 2377 | | `__namedParameters` | `object` | 2378 | | `__namedParameters.max`? | `Date` | 2379 | | `__namedParameters.min`? | `Date` | 2380 | | `__namedParameters.mode`? | `TMode` | 2381 | | `__namedParameters.withTimezone`? | `boolean` | 2382 | 2383 | #### Returns 2384 | 2385 | `ZodObject`\<`object`, `"strip"`, `ZodTypeAny`, \{ \[k in "lower" | "upper"]: 2386 | addQuestionMarks\, any>\[k] }, `object`> 2387 | 2388 | | Member | Type | Value | 2389 | | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------- | 2390 | | `lower` | `ZodEffects`\<`ZodNullable`\<`ZodDate`>, `TData`, `null` \| `Date`> \| `ZodEffects`\<`ZodNullable`\<`ZodUnion`\<\[`ZodDate`, `ZodNumber`]>>, `TData`, `null` \| `number` \| `Date`> | lowerSchema | 2391 | | `upper` | `ZodEffects`\<`ZodNullable`\<`ZodDate`>, `TData`, `null` \| `Date`> \| `ZodEffects`\<`ZodNullable`\<`ZodUnion`\<\[`ZodDate`, `ZodNumber`]>>, `TData`, `null` \| `number` \| `Date`> | upperSchema | 2392 | 2393 | --- 2394 | 2395 | 2396 | 2397 | ### tsvector() 2398 | 2399 | ```ts 2400 | function tsvector(dbName: TName, fieldConfig?: unknown): PgCustomColumnBuilder; 2401 | ``` 2402 | 2403 | Postgres text-search vector. 2404 | 2405 | #### Type parameters 2406 | 2407 | | Type parameter | 2408 | | :------------------------- | 2409 | | `TName` _extends_ `string` | 2410 | 2411 | #### Parameters 2412 | 2413 | | Parameter | Type | 2414 | | :------------- | :-------- | 2415 | | `dbName` | `TName` | 2416 | | `fieldConfig`? | `unknown` | 2417 | 2418 | #### Returns 2419 | 2420 | `PgCustomColumnBuilder`\<`object`> 2421 | 2422 | | Member | Type | 2423 | | :------------ | :----------------- | 2424 | | `columnType` | `"PgCustomColumn"` | 2425 | | `data` | `string` | 2426 | | `dataType` | `"custom"` | 2427 | | `driverParam` | `unknown` | 2428 | | `enumValues` | `undefined` | 2429 | | `name` | `TName` | 2430 | -------------------------------------------------------------------------------- /documentation/sqlite.md: -------------------------------------------------------------------------------- 1 | # src/sqlite 2 | 3 | ## Table of Contents 4 | 5 | - [Functions](#functions) 6 | - [random()](#random) 7 | 8 | ## Functions 9 | 10 | 11 | 12 | ### random() 13 | 14 | ```ts 15 | function random(): SQL; 16 | ``` 17 | 18 | SQLite random function. 19 | 20 | #### Returns 21 | 22 | `SQL`\<`number`> 23 | 24 | Random random integer between -9223372036854775808 and +9223372036854775807. 25 | 26 | #### Example 27 | 28 | ```sql 29 | random(); 30 | ``` 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Emmanuel Beaudry Marchand", 3 | "description": "A collection a tiny helpers for Drizzle ORM.", 4 | "license": "MIT", 5 | "type": "module", 6 | "name": "drizzle-orm-helpers", 7 | "version": "0.7.6", 8 | "files": [ 9 | "dist", 10 | "package.json", 11 | "README.md", 12 | "documentation.md" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/iolyd/drizzle-orm-helpers.git" 17 | }, 18 | "exports": { 19 | "./package.json": "./package.json", 20 | ".": { 21 | "types": "./dist/index.d.ts", 22 | "import": "./dist/index.js", 23 | "require": "./dist/index.cjs" 24 | }, 25 | "./pg": { 26 | "types": "./dist/pg/index.d.ts", 27 | "import": "./dist/pg/index.js", 28 | "require": "./dist/pg/index.cjs" 29 | }, 30 | "./mysql": { 31 | "types": "./dist/mysql/index.d.ts", 32 | "import": "./dist/mysql/index.js", 33 | "require": "./dist/mysql/index.cjs" 34 | }, 35 | "./sqlite": { 36 | "types": "./dist/sqlite/index.d.ts", 37 | "import": "./dist/sqlite/index.js", 38 | "require": "./dist/sqlite/index.cjs" 39 | } 40 | }, 41 | "devDependencies": { 42 | "@types/geojson": "^7946.0.14", 43 | "@typescript-eslint/eslint-plugin": "^7.12.0", 44 | "@typescript-eslint/parser": "^7.12.0", 45 | "drizzle-orm": "^0.31.2", 46 | "eslint": "^9.4.0", 47 | "eslint-config-prettier": "^9.1.0", 48 | "eslint-plugin-drizzle": "^0.2.3", 49 | "prettier": "^3.3.1", 50 | "prettier-plugin-jsdoc": "^1.3.0", 51 | "remark-github": "^12.0.0", 52 | "remark-toc": "^9.0.0", 53 | "tsup": "^8.1.0", 54 | "tsx": "^4.15.1", 55 | "type-fest": "^4.20.0", 56 | "typedoc": "^0.25.13", 57 | "typedoc-plugin-markdown": "4.0.3", 58 | "typedoc-plugin-remark": "1.0.1", 59 | "typescript": "^5.4.5", 60 | "unified-prettier": "^2.0.1", 61 | "zod": "^3.23.8" 62 | }, 63 | "peerDependencies": { 64 | "drizzle-orm": ">=0.31.2", 65 | "zod": ">=3.23.8" 66 | }, 67 | "peerDependenciesMeta": { 68 | "zod": { 69 | "optional": true 70 | } 71 | }, 72 | "dependencies": { 73 | "postgres-date": "^2.1.0", 74 | "postgres-range": "^1.1.4" 75 | }, 76 | "scripts": { 77 | "doc": "pnpm typedoc && mv documentation/src/* documentation/ && rm -rf documentation/src", 78 | "prepublishOnly": "pnpm tsup" 79 | } 80 | } -------------------------------------------------------------------------------- /sql/nanoid.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Code taken from: https://github.com/viascom/nanoid-postgres/blob/main/nanoid.sql 3 | * as proposed in: https://community.neon.tech/t/extension-request-nanoid/1092/2 4 | * 5 | * - 6 | * 7 | * Copyright 2023 Viascom Ltd liab. Co 8 | * 9 | * Licensed to the Apache Software Foundation (ASF) under one 10 | * or more contributor license agreements. See the NOTICE file 11 | * distributed with this work for additional information 12 | * regarding copyright ownership. The ASF licenses this file 13 | * to you under the Apache License, Version 2.0 (the 14 | * "License"); you may not use this file except in compliance 15 | * with the License. You may obtain a copy of the License at 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, 20 | * software distributed under the License is distributed on an 21 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 | * KIND, either express or implied. See the License for the 23 | * specific language governing permissions and limitations 24 | * under the License. 25 | */ 26 | 27 | CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions; 28 | 29 | -- The `nanoid()` function generates a compact, URL-friendly unique identifier. 30 | -- Based on the given size and alphabet, it creates a randomized string that's ideal for 31 | -- use-cases requiring small, unpredictable IDs (e.g., URL shorteners, generated file names, etc.). 32 | -- While it comes with a default configuration, the function is designed to be flexible, 33 | -- allowing for customization to meet specific needs. 34 | DROP FUNCTION IF EXISTS nanoid(int, text, float); 35 | CREATE OR REPLACE FUNCTION nanoid( 36 | size int DEFAULT 21, -- The number of symbols in the NanoId String. Must be greater than 0. 37 | alphabet text DEFAULT '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', -- The symbols used in the NanoId String. Must contain between 1 and 255 symbols. 38 | additionalBytesFactor float DEFAULT 1.6 -- The additional bytes factor used for calculating the step size. Must be equal or greater then 1. 39 | ) 40 | RETURNS text -- A randomly generated NanoId String 41 | LANGUAGE plpgsql 42 | VOLATILE 43 | LEAKPROOF 44 | PARALLEL SAFE 45 | AS 46 | $$ 47 | DECLARE 48 | alphabetArray text[]; 49 | alphabetLength int := 64; 50 | mask int := 63; 51 | step int := 34; 52 | BEGIN 53 | IF size IS NULL OR size < 1 THEN 54 | RAISE EXCEPTION 'The size must be defined and greater than 0!'; 55 | END IF; 56 | 57 | IF alphabet IS NULL OR length(alphabet) = 0 OR length(alphabet) > 255 THEN 58 | RAISE EXCEPTION 'The alphabet can''t be undefined, zero or bigger than 255 symbols!'; 59 | END IF; 60 | 61 | IF additionalBytesFactor IS NULL OR additionalBytesFactor < 1 THEN 62 | RAISE EXCEPTION 'The additional bytes factor can''t be less than 1!'; 63 | END IF; 64 | 65 | alphabetArray := regexp_split_to_array(alphabet, ''); 66 | alphabetLength := array_length(alphabetArray, 1); 67 | mask := (2 << cast(floor(log(alphabetLength - 1) / log(2)) as int)) - 1; 68 | step := cast(ceil(additionalBytesFactor * mask * size / alphabetLength) AS int); 69 | 70 | IF step > 1024 THEN 71 | step := 1024; -- The step size % can''t be bigger then 1024! 72 | END IF; 73 | 74 | RETURN nanoid_optimized(size, alphabet, mask, step); 75 | END 76 | $$; 77 | 78 | -- Generates an optimized random string of a specified size using the given alphabet, mask, and step. 79 | -- This optimized version is designed for higher performance and lower memory overhead. 80 | -- No checks are performed! Use it only if you really know what you are doing. 81 | DROP FUNCTION IF EXISTS nanoid_optimized(int, text, int, int); 82 | CREATE OR REPLACE FUNCTION nanoid_optimized( 83 | size int, -- The desired length of the generated string. 84 | alphabet text, -- The set of characters to choose from for generating the string. 85 | mask int, -- The mask used for mapping random bytes to alphabet indices. Should be `(2^n) - 1` where `n` is a power of 2 less than or equal to the alphabet size. 86 | step int -- The number of random bytes to generate in each iteration. A larger value may speed up the function but increase memory usage. 87 | ) 88 | RETURNS text -- A randomly generated NanoId String 89 | LANGUAGE plpgsql 90 | VOLATILE 91 | LEAKPROOF 92 | PARALLEL SAFE 93 | AS 94 | $$ 95 | DECLARE 96 | idBuilder text := ''; 97 | counter int := 0; 98 | bytes bytea; 99 | alphabetIndex int; 100 | alphabetArray text[]; 101 | alphabetLength int := 64; 102 | BEGIN 103 | alphabetArray := regexp_split_to_array(alphabet, ''); 104 | alphabetLength := array_length(alphabetArray, 1); 105 | 106 | LOOP 107 | bytes := gen_random_bytes(step); 108 | FOR counter IN 0..step - 1 109 | LOOP 110 | alphabetIndex := (get_byte(bytes, counter) & mask) + 1; 111 | IF alphabetIndex <= alphabetLength THEN 112 | idBuilder := idBuilder || alphabetArray[alphabetIndex]; 113 | IF length(idBuilder) = size THEN 114 | RETURN idBuilder; 115 | END IF; 116 | END IF; 117 | END LOOP; 118 | END LOOP; 119 | END 120 | $$; -------------------------------------------------------------------------------- /sql/search-path.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Without proper search_path configuration, Postgres has trouble finding 3 | * functions and column types enabled through extensions installed 4 | * in a different schema (typically "extensions"). 5 | * 6 | * This ensures we don't have to constantly prefix column types or functions 7 | * with the extensions schema name. 8 | */ 9 | 10 | -- Manual approach 11 | SHOW search_path; 12 | SELECT current_database(); 13 | -- Paste values and run 14 | ALTER DATABASE [database name] 15 | SET search_path = [...search path], extensions; 16 | SHOW search_path; 17 | 18 | -- Automatic approach 19 | DO $$ 20 | BEGIN 21 | EXECUTE 'ALTER DATABASE ' || current_database() || ' SET SEARCH_PATH = ' || current_setting('search_path') || ',extensions'; 22 | END $$; -------------------------------------------------------------------------------- /src/expressions.ts: -------------------------------------------------------------------------------- 1 | import type { SQL, SQLWrapper } from 'drizzle-orm'; 2 | import { StringChunk, bindIfParam, sql } from 'drizzle-orm'; 3 | import type { TupleToUnion } from 'type-fest'; 4 | import { type InferData } from '.'; 5 | import type { NonUndefinable } from './internals'; 6 | 7 | /** 8 | * Distinct keyword. 9 | */ 10 | export function distinct(statement: T) { 11 | return sql>`distinct ${statement}`; 12 | } 13 | 14 | /** 15 | * Case condition chain. 16 | * 17 | * @example 18 | * 19 | * ```ts 20 | * cases([[eq(thing, other), 2]], 3); 21 | * ``` 22 | * 23 | * @example 24 | * 25 | * ```sql 26 | * CASE 27 | * WHEN thing = other THEN 2 28 | * ELSE 3 29 | * END; 30 | * ``` 31 | * 32 | * @todo Implement smarter typing to identify confirmable early returns with truthy conditions. 33 | */ 34 | export function cases< 35 | const C extends ([SQLWrapper, unknown] | undefined)[], 36 | const F, 37 | T = NonUndefinable>, 38 | R = 39 | | (T extends [infer T0, infer T1] 40 | ? T0 extends SQL 41 | ? never 42 | : T1 extends SQLWrapper 43 | ? InferData 44 | : T1 45 | : never) 46 | | (F extends void ? never : F extends SQLWrapper ? InferData : F), 47 | >(conditionals: C, fallback?: F) { 48 | const chunks = conditionals.reduce( 49 | (acc, curr) => { 50 | if (curr) { 51 | acc.push(sql`when ${curr[0]} then ${bindIfParam(curr[1], curr[0])}`); 52 | } 53 | return acc; 54 | }, 55 | []>[] 56 | ); 57 | if (fallback) { 58 | chunks.push(sql`else ${fallback}`); 59 | } 60 | return sql.join( 61 | [new StringChunk('(case'), ...chunks, new StringChunk(')')], 62 | new StringChunk(' ') 63 | ) as SQL; 64 | } 65 | -------------------------------------------------------------------------------- /src/functions.ts: -------------------------------------------------------------------------------- 1 | import type { SQL, SQLWrapper } from 'drizzle-orm'; 2 | import { StringChunk, sql } from 'drizzle-orm'; 3 | import type { InferData } from '.'; 4 | 5 | type RemoveNull = T extends null ? never : T; 6 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 7 | type CoalesceSQL = T extends [ 8 | infer H, 9 | ...infer T, 10 | ] 11 | ? CoalesceSQL< 12 | T, 13 | H extends SQL | SQL.Aliased ? (null extends InferData ? true : false) : never, 14 | R | RemoveNull : never> 15 | > 16 | : N extends true 17 | ? R | null 18 | : R; 19 | /** 20 | * @see https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-COALESCE-NVL-IFNULL 21 | */ 22 | export function coalesce(...values: [...T]) { 23 | return sql>`coalesce(${sql.join( 24 | values.map((v) => sql`${v}`), 25 | sql`,` 26 | )})`; 27 | } 28 | 29 | /** 30 | * Return null if value meets condition. Useful to coalesce to something else. 31 | * 32 | * @see https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-NULLIF 33 | */ 34 | export function nullIf(value: V, condition: C) { 35 | return sql`nullif(${value}, ${condition})`; 36 | } 37 | 38 | /** 39 | * @see https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST 40 | */ 41 | export function greatest(...values: [...T]) { 42 | return sql.join([ 43 | new StringChunk('greatest('), 44 | sql.join( 45 | values.map((v) => sql`${v}`), 46 | new StringChunk(', ') 47 | ), 48 | new StringChunk(')'), 49 | ]) as SQL<{ [I in keyof T]: T[I] extends SQLWrapper ? InferData : T[I] }[number]>; 50 | } 51 | 52 | /** 53 | * @see https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST 54 | */ 55 | export function least(...values: [...T]) { 56 | return sql.join([ 57 | new StringChunk('least('), 58 | sql.join( 59 | values.map((v) => sql`${v}`), 60 | new StringChunk(', ') 61 | ), 62 | new StringChunk(')'), 63 | ]) as SQL<{ [I in keyof T]: T[I] extends SQLWrapper ? InferData : T[I] }[number]>; 64 | } 65 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './expressions'; 2 | export * from './functions'; 3 | export * from './operators'; 4 | export * from './utilities'; 5 | export * from './values'; 6 | -------------------------------------------------------------------------------- /src/internals.ts: -------------------------------------------------------------------------------- 1 | import { PgDialect } from 'drizzle-orm/pg-core'; 2 | 3 | export const PG_DIALECT = new PgDialect(); 4 | 5 | export type NonUndefinable = T extends undefined ? never : T; 6 | -------------------------------------------------------------------------------- /src/mysql/functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'drizzle-orm'; 2 | 3 | /** 4 | * MySQL random function. 5 | * 6 | * @example 7 | * 8 | * ```sql 9 | * rand(); 10 | * ``` 11 | * 12 | * @returns Random number between 0 and 1. 13 | */ 14 | export function random() { 15 | return sql`rand()`; 16 | } 17 | -------------------------------------------------------------------------------- /src/mysql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './functions'; 2 | -------------------------------------------------------------------------------- /src/operators.ts: -------------------------------------------------------------------------------- 1 | import { SQL, StringChunk, sql, type SQLWrapper } from 'drizzle-orm'; 2 | import type { InferData } from '.'; 3 | 4 | /** 5 | * Add values. 6 | */ 7 | export function add(...values: T) { 8 | const additions = sql.join(values, new StringChunk(' + ')); 9 | return new SQL([new StringChunk('('), additions, new StringChunk(')')]) as SQL< 10 | T[number] extends SQLWrapper ? InferData : T[number] 11 | >; 12 | } 13 | 14 | /** 15 | * Subtract values. 16 | */ 17 | export function subtract(...values: T) { 18 | const subtractions = sql.join(values, new StringChunk(' - ')); 19 | return new SQL([new StringChunk('('), subtractions, new StringChunk(')')]) as SQL< 20 | T[number] extends SQLWrapper ? InferData : T[number] 21 | >; 22 | } 23 | 24 | /** 25 | * Divide values. 26 | */ 27 | export function divide(...values: T) { 28 | const divisions = sql.join(values, new StringChunk(' / ')); 29 | return new SQL([new StringChunk('('), divisions, new StringChunk(')')]) as SQL< 30 | T[number] extends SQLWrapper ? InferData : T[number] 31 | >; 32 | } 33 | 34 | /** 35 | * Multiply values. 36 | */ 37 | export function multiply(...values: T) { 38 | const multiplications = sql.join(values, new StringChunk(' * ')); 39 | return new SQL([new StringChunk('('), multiplications, new StringChunk(')')]) as SQL< 40 | T[number] extends SQLWrapper ? InferData : T[number] 41 | >; 42 | } 43 | -------------------------------------------------------------------------------- /src/pg/citext/README.md: -------------------------------------------------------------------------------- 1 | # Citext module 2 | 3 | 4 | 5 | ```sql 6 | create extension citext /* with schema [your extensions schema] */; 7 | ``` 8 | -------------------------------------------------------------------------------- /src/pg/citext/custom-types.ts: -------------------------------------------------------------------------------- 1 | import { customType } from 'drizzle-orm/pg-core'; 2 | 3 | /** 4 | * Ci-text postgres column type. 5 | * 6 | * @see https://www.postgresql.org/docs/current/citext.html 7 | */ 8 | export const citext = customType<{ data: string }>({ 9 | dataType() { 10 | return `citext`; 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /src/pg/citext/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-types'; 2 | -------------------------------------------------------------------------------- /src/pg/constants.ts: -------------------------------------------------------------------------------- 1 | import type { ValueOf } from 'type-fest'; 2 | import type { RangeValue } from '.'; 3 | 4 | /** 5 | * Postgres regconfig cfgnames. 6 | * 7 | * @example 8 | * 9 | * ```sql 10 | * SELECT json_object_agg(upper(cfgname), cfgname) 11 | * FROM pg_catalog.pg_ts_config; 12 | * ``` 13 | */ 14 | export const REGCONFIGS = { 15 | SIMPLE: 'simple', 16 | ARABIC: 'arabic', 17 | ARMENIAN: 'armenian', 18 | BASQUE: 'basque', 19 | CATALAN: 'catalan', 20 | DANISH: 'danish', 21 | DUTCH: 'dutch', 22 | ENGLISH: 'english', 23 | FINNISH: 'finnish', 24 | FRENCH: 'french', 25 | GERMAN: 'german', 26 | GREEK: 'greek', 27 | HINDI: 'hindi', 28 | HUNGARIAN: 'hungarian', 29 | INDONESIAN: 'indonesian', 30 | IRISH: 'irish', 31 | ITALIAN: 'italian', 32 | LITHUANIAN: 'lithuanian', 33 | NEPALI: 'nepali', 34 | NORWEGIAN: 'norwegian', 35 | PORTUGUESE: 'portuguese', 36 | ROMANIAN: 'romanian', 37 | RUSSIAN: 'russian', 38 | SERBIAN: 'serbian', 39 | SPANISH: 'spanish', 40 | SWEDISH: 'swedish', 41 | TAMIL: 'tamil', 42 | TURKISH: 'turkish', 43 | YIDDISH: 'yiddish', 44 | } as const; 45 | 46 | export type Regconfig = ValueOf; 47 | 48 | export type RegconfigString = Regconfig | (string & NonNullable); 49 | 50 | export const RANGE_BOUND_TYPES = { 51 | INCLUSIVE: 'inclusive', 52 | EXCLUSIVE: 'exclusive', 53 | } as const; 54 | 55 | export type RangeBoundType = ValueOf; 56 | 57 | /** 58 | * Value for app-side representation of empty postgres ranges. 59 | */ 60 | export const RANGE_EMPTY = { lower: null, upper: null } satisfies RangeValue; 61 | 62 | export const INTERVAL_UNITS = { 63 | YEARS: 'years', 64 | MONTHS: 'months', 65 | WEEKS: 'weeks', 66 | DAYS: 'days', 67 | HOURS: 'hours', 68 | MINUTES: 'minutes', 69 | SECONDS: 'seconds', 70 | } as const; 71 | 72 | export type IntervalUnit = ValueOf; 73 | 74 | export const INTERVAL_UNITS_ARR_ORDERED = [ 75 | INTERVAL_UNITS.YEARS, 76 | INTERVAL_UNITS.MONTHS, 77 | INTERVAL_UNITS.WEEKS, 78 | INTERVAL_UNITS.DAYS, 79 | INTERVAL_UNITS.HOURS, 80 | INTERVAL_UNITS.MINUTES, 81 | INTERVAL_UNITS.SECONDS, 82 | ] as const; 83 | -------------------------------------------------------------------------------- /src/pg/cube/README.md: -------------------------------------------------------------------------------- 1 | # Cube extension 2 | 3 | 4 | 5 | ```sql 6 | create extension cube /* with schema [your extensions schema] */; 7 | ``` 8 | -------------------------------------------------------------------------------- /src/pg/cube/constants.ts: -------------------------------------------------------------------------------- 1 | import type { ValueOf } from 'type-fest'; 2 | 3 | export const DISTANCE_TYPES = { 4 | EUCLIDIAN: 'euclidian', 5 | TAXICAB: 'taxicab', 6 | CHEBYSHEV: 'chebyshev', 7 | } as const; 8 | export type DistanceType = ValueOf; 9 | 10 | export const DISTANCE_TYPES_OPERATORS = { 11 | [DISTANCE_TYPES.EUCLIDIAN]: '<->', 12 | [DISTANCE_TYPES.TAXICAB]: '<#>', 13 | [DISTANCE_TYPES.CHEBYSHEV]: '<=>', 14 | } as const satisfies Record; 15 | -------------------------------------------------------------------------------- /src/pg/cube/custom-types.ts: -------------------------------------------------------------------------------- 1 | import { customType } from 'drizzle-orm/pg-core'; 2 | 3 | /** 4 | * Postgres cube column type with customizable amount of dimensions. 5 | * 6 | * @see https://www.postgresql.org/docs/current/cube.html 7 | */ 8 | export const cube = customType<{ 9 | data: number[] | [number[], number[]]; 10 | driverData: number[] | [number[], number[]]; 11 | }>({ 12 | dataType() { 13 | return `cube`; 14 | }, 15 | fromDriver(value) { 16 | return value; 17 | }, 18 | toDriver(value) { 19 | return value; 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /src/pg/cube/functions.ts: -------------------------------------------------------------------------------- 1 | // https://www.postgresql.org/docs/current/cube.html#CUBE-FUNCTIONS-TABLE 2 | 3 | import type { SQLWrapper } from 'drizzle-orm'; 4 | import { StringChunk, sql } from 'drizzle-orm'; 5 | 6 | /** 7 | * Makes a one dimensional cube with both coordinates the same. 8 | * 9 | * @example 10 | * 11 | * ```sql 12 | * -- cube ( float8 ) → cube 13 | * cube(1) → (1) 14 | * ``` 15 | * 16 | * Makes a one dimensional cube. 17 | * 18 | * @example 19 | * 20 | * ```sql 21 | * -- cube ( float8, float8 ) → cube 22 | * cube(1, 2) → (1),(2) 23 | * ``` 24 | * 25 | * Makes a zero-volume cube using the coordinates defined by the array. 26 | * 27 | * @example 28 | * 29 | * ```sql 30 | * -- cube ( float8[] ) → cube 31 | * cube(ARRAY[1,2,3]) → (1, 2, 3) 32 | * ``` 33 | * 34 | * Makes a cube with upper right and lower left coordinates as defined by the two arrays, which must 35 | * be of the same length. 36 | * 37 | * @example 38 | * 39 | * ```sql 40 | * -- cube ( float8[], float8[] ) → cube 41 | * cube(ARRAY[1,2], ARRAY[3,4]) → (1, 2),(3, 4) 42 | * ``` 43 | * 44 | * Makes a new cube by adding a dimension on to an existing cube, with the same values for both 45 | * endpoints of the new coordinate. This is useful for building cubes piece by piece from calculated 46 | * values. 47 | * 48 | * @example 49 | * 50 | * ```sql 51 | * -- cube ( cube, float8 ) → cube 52 | * cube('(1,2),(3,4)'::cube, 5) → (1, 2, 5),(3, 4, 5) 53 | * ``` 54 | * 55 | * Makes a new cube by adding a dimension on to an existing cube. This is useful for building cubes 56 | * piece by piece from calculated values. 57 | * 58 | * @example 59 | * 60 | * ```sql 61 | * --cube ( cube, float8, float8 ) → cube 62 | * cube('(1,2),(3,4)'::cube, 5, 6) → (1, 2, 5),(3, 4, 6) 63 | * ``` 64 | */ 65 | export function makeCube< 66 | T extends 67 | | [number] 68 | | [number, number] 69 | | number[] 70 | | [number[], number[]] 71 | | [SQLWrapper, number] 72 | | [SQLWrapper, number, number], 73 | >(...args: T) { 74 | const params = sql.join( 75 | args.map((c) => sql`${c}`), 76 | new StringChunk(',') 77 | ); 78 | return sql`cube(${params})`; 79 | } 80 | 81 | /** 82 | * Returns the number of dimensions of the cube. 83 | * 84 | * @example 85 | * 86 | * ```sql 87 | * --cube_dim ( cube ) → integer 88 | * cube_dim('(1,2),(3,4)') → 2 89 | * ``` 90 | */ 91 | export function cubeDim(cube: SQLWrapper) { 92 | return sql`cube_dim(${cube})`.mapWith(Number); 93 | } 94 | 95 | /** 96 | * Returns the n-th coordinate value for the lower left corner of the cube. 97 | * 98 | * @example 99 | * 100 | * ```sql 101 | * -- cube_ll_coord ( cube, integer ) → float8 102 | * cube_ll_coord('(1,2),(3,4)', 2) → 2 103 | * ``` 104 | */ 105 | export function cubeLowerLeftCoord() {} 106 | 107 | /** 108 | * ``` 109 | * Returns the n-th coordinate value for the upper right corner of the cube. 110 | * ``` 111 | * 112 | * @example 113 | * 114 | * ```sql 115 | * -- cube_ur_coord ( cube, integer ) → float8 116 | * cube_ur_coord('(1,2),(3,4)', 2) → 4 117 | * ``` 118 | */ 119 | export function cubeUpperRightCoord() {} 120 | 121 | /** 122 | * Returns true if the cube is a point, that is, the two defining corners are the same. 123 | * 124 | * @example 125 | * 126 | * ```sql 127 | * -- cube_is_point ( cube ) → boolean 128 | * cube_is_point(cube(1,1)) → t 129 | * ``` 130 | */ 131 | export function cubeIsPoint(cube: SQLWrapper) { 132 | return sql`cube_is_point(${cube})`.mapWith(Boolean); 133 | } 134 | 135 | /** 136 | * Returns the distance between two cubes. If both cubes are points, this is the normal distance 137 | * function. 138 | * 139 | * @example 140 | * 141 | * ```sql 142 | * -- cube_distance ( cube, cube ) → float8 143 | * cube_distance('(1,2)', '(3,4)') → 2.8284271247461903 144 | * ``` 145 | */ 146 | export function cubeDistance(...cubes: [SQLWrapper, SQLWrapper]) { 147 | const params = sql.join(cubes, new StringChunk(',')); 148 | return sql`cube_distance(${params})`.mapWith(Number); 149 | } 150 | 151 | /** 152 | * Makes a new cube from an existing cube, using a list of dimension indexes from an array. Can be 153 | * used to extract the endpoints of a single dimension, or to drop dimensions, or to reorder them as 154 | * desired. 155 | * 156 | * @example 157 | * 158 | * ```sql 159 | * cube_subset ( cube, integer[] ) → cube 160 | * cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) → (3),(7) 161 | * cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) → (5, 3, 1, 1),(8, 7, 6, 6) 162 | * ``` 163 | */ 164 | export function cubeSubset() {} 165 | 166 | /** 167 | * Produces the union of two cubes. 168 | * 169 | * @example 170 | * 171 | * ```sql 172 | * -- cube_union ( cube, cube ) → cube 173 | * cube_union('(1,2)', '(3,4)') → (1, 2),(3, 4) 174 | * ``` 175 | */ 176 | export function cubeUnion() {} 177 | 178 | /** 179 | * Produces the intersection of two cubes. 180 | * 181 | * @example 182 | * 183 | * ```sql 184 | * -- cube_inter ( cube, cube ) → cube 185 | * cube_inter('(1,2)', '(3,4)') → (3, 4),(1, 2) 186 | * ``` 187 | */ 188 | export function cubeInter() {} 189 | 190 | /** 191 | * Increases the size of the cube by the specified radius r in at least n dimensions. If the radius 192 | * is negative the cube is shrunk instead. All defined dimensions are changed by the radius r. 193 | * Lower-left coordinates are decreased by r and upper-right coordinates are increased by r. If a 194 | * lower-left coordinate is increased to more than the corresponding upper-right coordinate (this 195 | * can only happen when r < 0) than both coordinates are set to their average. If n is greater than 196 | * the number of defined dimensions and the cube is being enlarged (r > 0), then extra dimensions 197 | * are added to make n altogether; 0 is used as the initial value for the extra coordinates. This 198 | * function is useful for creating bounding boxes around a point for searching for nearby points. 199 | * 200 | * @example 201 | * 202 | * ```sql 203 | * -- cube_enlarge ( c cube, r double, n integer ) → cube 204 | * cube_enlarge('(1,2),(3,4)', 0.5, 3) → (0.5, 1.5, -0.5),(3.5, 4.5, 0.5) 205 | * ``` 206 | */ 207 | export function cubeEnlarge() {} 208 | -------------------------------------------------------------------------------- /src/pg/cube/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-types'; 2 | export * from './functions'; 3 | export * from './operators'; 4 | -------------------------------------------------------------------------------- /src/pg/cube/operators.ts: -------------------------------------------------------------------------------- 1 | // https://www.postgresql.org/docs/current/cube.html#CUBE-OPERATORS-TABLE 2 | 3 | import type { SQLWrapper } from 'drizzle-orm'; 4 | import { bindIfParam, sql } from 'drizzle-orm'; 5 | import type { DistanceType } from './constants'; 6 | import { DISTANCE_TYPES, DISTANCE_TYPES_OPERATORS } from './constants'; 7 | 8 | /** 9 | * Do the cubes overlap? 10 | * 11 | * @example 12 | * 13 | * ```sql 14 | * cube && cube → boolean 15 | * ``` 16 | */ 17 | export function overlaps(left: SQLWrapper, right: unknown) { 18 | return sql`${left} && ${bindIfParam(right, left)}`; 19 | } 20 | 21 | /** 22 | * Does the first cube contain the second? 23 | * 24 | * @example 25 | * 26 | * ```sql 27 | * cube @> cube → boolean 28 | * ``` 29 | */ 30 | export function contains(left: SQLWrapper, right: unknown) { 31 | return sql`${left} @> ${bindIfParam(right, left)}`; 32 | } 33 | 34 | /** 35 | * Is the first cube contained in the second? 36 | * 37 | * @example 38 | * 39 | * ```sql 40 | * cube <@ cube → boolean 41 | * ``` 42 | */ 43 | export function contained(left: SQLWrapper, right: unknown) { 44 | return sql`${left} <@ ${bindIfParam(right, left)}`; 45 | } 46 | 47 | /** 48 | * Extracts the n-th coordinate of the cube (counting from 1). 49 | * 50 | * @example 51 | * 52 | * ```sql 53 | * cube -> integer → float8 54 | * ``` 55 | * 56 | * Extracts the n-th coordinate of the cube, counting in the following way: n = 2 * k - 1 means 57 | * lower bound of k-th dimension, n = 2 * k means upper bound of k-th dimension. Negative n denotes 58 | * the inverse value of the corresponding positive coordinate. This operator is designed for 59 | * KNN-GiST support. 60 | * 61 | * @example 62 | * 63 | * ```sql 64 | * cube ~> integer → float8 65 | * ``` 66 | */ 67 | export function extract(left: SQLWrapper, right: unknown) { 68 | return sql`${left} -> ${bindIfParam(right, left)}`; 69 | } 70 | 71 | /** 72 | * Computes the distance between two cubes. 73 | * 74 | * @example 75 | * 76 | * ```sql 77 | * -- Computes the Euclidean distance between the two cubes. 78 | * cube <-> cube → float8 79 | * ``` 80 | * 81 | * @example 82 | * 83 | * ```sql 84 | * -- Computes the taxicab (L-1 metric) distance between the two cubes. 85 | * cube <#> cube → float8 86 | * ``` 87 | * 88 | * @example 89 | * 90 | * ```sql 91 | * -- Computes the Chebyshev (L-inf metric) distance between the two cubes. 92 | * cube <=> cube → float8 93 | * ``` 94 | */ 95 | export function distance( 96 | left: SQLWrapper, 97 | right: unknown, 98 | { type = DISTANCE_TYPES.EUCLIDIAN }: { type?: DistanceType } = {} 99 | ) { 100 | return sql`${left} ${DISTANCE_TYPES_OPERATORS[type]} ${bindIfParam(right, left)}`; 101 | } 102 | -------------------------------------------------------------------------------- /src/pg/custom-types.ts: -------------------------------------------------------------------------------- 1 | import { customType } from 'drizzle-orm/pg-core'; 2 | import parseDate from 'postgres-date'; 3 | import * as range from 'postgres-range'; 4 | import { RANGE_EMPTY, type RangeValue } from '.'; 5 | import type { RangeBoundType, Regconfig } from './constants'; 6 | import { RANGE_BOUND_BRACKETS } from './internals'; 7 | 8 | /** 9 | * Text-based enum with runtime check and type inferrence. In other words, similar to drizzle's own 10 | * `text` column with `config.enum` but this time with runtime peace-of mind. 11 | * 12 | * If you simply want a union-typed text without runtime safety of values, use drizzle's own `text` 13 | * with the `config.enum` configuration. 14 | * 15 | * @see https://orm.drizzle.team/docs/column-types/pg#text 16 | */ 17 | export function textenum< 18 | TName extends string, 19 | const TEnum extends string[] | Readonly, 20 | TConfig extends { 21 | enum: TEnum; 22 | fallback: TConfig['enum'][number] | Error | ((value: string) => TConfig['enum'][number]); 23 | }, 24 | >(name: TName, config: TConfig) { 25 | function isEnumMember(value: unknown): value is TEnum[number] { 26 | return config.enum.includes(value as TEnum[number]); 27 | } 28 | return customType<{ 29 | data: TConfig['enum'][number]; 30 | driverData: string; 31 | config: TConfig; 32 | }>({ 33 | dataType() { 34 | return 'text'; 35 | }, 36 | fromDriver(value) { 37 | if (isEnumMember(value)) { 38 | return value; 39 | } 40 | if (config.fallback instanceof Error) { 41 | throw config.fallback; 42 | } 43 | if (typeof config.fallback === 'function') { 44 | return config.fallback(value); 45 | } 46 | return config.fallback; 47 | }, 48 | toDriver(value) { 49 | if (isEnumMember(value)) { 50 | return value; 51 | } 52 | if (config.fallback instanceof Error) { 53 | throw config.fallback; 54 | } 55 | if (typeof config.fallback === 'function') { 56 | return config.fallback(value); 57 | } 58 | return config.fallback; 59 | }, 60 | })(name, config); 61 | } 62 | 63 | /** 64 | * Implements Postgres regconfig. Useful for text search language config storage. 65 | * 66 | * @see https://www.postgresql.org/docs/current/textsearch-controls.html 67 | */ 68 | export const regconfig = customType<{ data: Regconfig }>({ 69 | dataType() { 70 | return 'regconfig'; 71 | }, 72 | toDriver(value) { 73 | return `${value}`; 74 | }, 75 | }); 76 | 77 | /** 78 | * Postgres text-search vector. 79 | */ 80 | export const tsvector = customType<{ data: string }>({ 81 | dataType() { 82 | return 'tsvector'; 83 | }, 84 | }); 85 | 86 | /** 87 | * Implements Postgres timestamp range. 88 | * 89 | * @see https://www.postgresql.org/docs/current/rangetypes.html 90 | * @see https://github.com/bendrucker/postgres-date 91 | */ 92 | export function tsrange< 93 | TName extends string, 94 | TConfig extends { 95 | withTimezone?: boolean; 96 | mode?: 'date' | 'string'; 97 | lowerBound?: RangeBoundType; 98 | upperBound?: RangeBoundType; 99 | }, 100 | TData = TConfig['mode'] extends 'string' ? RangeValue : RangeValue, 101 | >(name: TName, config?: TConfig) { 102 | return customType<{ 103 | data: TData; 104 | driverData: string; 105 | config: TConfig; 106 | }>({ 107 | dataType(config) { 108 | const tz = config?.withTimezone ? 'tz' : ''; 109 | return `ts${tz}range`; 110 | }, 111 | fromDriver(value) { 112 | const parsed = range.parse(value, (value) => { 113 | if (config?.mode === 'string') { 114 | return value; 115 | } 116 | return parseDate(value); 117 | }); 118 | if (parsed.isEmpty()) { 119 | return RANGE_EMPTY as TData; 120 | } 121 | return { lower: parsed.lower, upper: parsed.upper } as TData; 122 | }, 123 | toDriver(value) { 124 | if (value === null || typeof value !== 'object' || !('lower' in value && 'upper' in value)) { 125 | throw new Error( 126 | 'Value passed to driver for range should be an object with lower and upper properties.' 127 | ); 128 | } 129 | const lower = value.lower instanceof Date ? value.lower.toISOString() : value.lower ?? ''; 130 | const upper = value.upper instanceof Date ? value.upper.toISOString() : value.upper ?? ''; 131 | // Using canonical form of included lower bound and excluded upper bound. 132 | // See https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE 133 | const lb = RANGE_BOUND_BRACKETS.LOWER[config?.lowerBound ?? 'inclusive']; 134 | const ub = RANGE_BOUND_BRACKETS.UPPER[config?.upperBound ?? 'exclusive']; 135 | return `${lb}${lower},${upper}${ub}`; 136 | }, 137 | })(name, config); 138 | } 139 | 140 | /** 141 | * Implements postgres date range. 142 | * 143 | * @see https://orm.drizzle.team/docs/custom-types Timestamp for reference. 144 | * @see https://www.postgresql.org/docs/current/rangetypes.html 145 | */ 146 | export function daterange< 147 | TName extends string, 148 | TConfig extends { 149 | mode?: 'date' | 'string'; 150 | lowerBound?: RangeBoundType; 151 | upperBound?: RangeBoundType; 152 | }, 153 | TData = TConfig['mode'] extends 'string' ? RangeValue : RangeValue, 154 | >(name: TName, config?: TConfig) { 155 | return customType<{ 156 | data: TData; 157 | driverData: string; 158 | config: TConfig; 159 | }>({ 160 | dataType() { 161 | return 'daterange'; 162 | }, 163 | fromDriver(value) { 164 | const parsed = range.parse(value, (value) => { 165 | if (config?.mode === 'string') { 166 | return value; 167 | } 168 | return parseDate(value); 169 | }); 170 | if (parsed.isEmpty()) { 171 | return RANGE_EMPTY as TData; 172 | } 173 | return { lower: parsed.lower, upper: parsed.upper } as TData; 174 | }, 175 | toDriver(value) { 176 | if (value === null || typeof value !== 'object' || !('lower' in value && 'upper' in value)) { 177 | throw new Error( 178 | 'Value passed to driver for range should be an object with lower and upper properties.' 179 | ); 180 | } 181 | const lower = value.lower instanceof Date ? value.lower.toISOString() : value.lower ?? ''; 182 | const upper = value.upper instanceof Date ? value.upper.toISOString() : value.upper ?? ''; 183 | // Using canonical form of included lower bound and excluded upper bound. 184 | // See https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE 185 | const lb = RANGE_BOUND_BRACKETS.LOWER[config?.lowerBound ?? 'inclusive']; 186 | const ub = RANGE_BOUND_BRACKETS.UPPER[config?.upperBound ?? 'exclusive']; 187 | return `${lb}${lower},${upper}${ub}`; 188 | }, 189 | })(name, config); 190 | } 191 | 192 | /** 193 | * Implements postgres int4range and int8range types. 194 | * 195 | * @param config.size Size of integers, where `4` corresponds to `int4range` and `8`corresponds to a 196 | * bigint range (int8range). 197 | * @see https://www.postgresql.org/docs/current/rangetypes.html 198 | */ 199 | export function intrange< 200 | TName extends string, 201 | TConfig extends { 202 | size?: 4 | 8; 203 | lowerBound?: RangeBoundType; 204 | upperBound?: RangeBoundType; 205 | }, 206 | >(name: TName, config?: TConfig) { 207 | return customType<{ 208 | data: RangeValue; 209 | driverData: string; 210 | config: TConfig; 211 | }>({ 212 | dataType(config) { 213 | const size = config?.size ?? 4; 214 | return `int${size}range`; 215 | }, 216 | fromDriver(value) { 217 | const parsed = range.parse(value, (value) => { 218 | return parseInt(value, 10); 219 | }); 220 | if (parsed.isEmpty()) { 221 | return RANGE_EMPTY; 222 | } 223 | return { lower: parsed.lower, upper: parsed.upper }; 224 | }, 225 | toDriver(value) { 226 | // Using canonical form of included lower bound and excluded upper bound. 227 | // See https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE 228 | const lb = RANGE_BOUND_BRACKETS.LOWER[config?.lowerBound ?? 'inclusive']; 229 | const ub = RANGE_BOUND_BRACKETS.UPPER[config?.upperBound ?? 'exclusive']; 230 | return `${lb}${value.lower ?? ''},${value.upper ?? ''}${ub}`; 231 | }, 232 | })(name, config); 233 | } 234 | 235 | /** 236 | * Implements postgres numrange type. 237 | * 238 | * @see https://www.postgresql.org/docs/current/rangetypes.html 239 | */ 240 | export function numrange< 241 | TName extends string, 242 | TConfig extends { 243 | lowerBound?: RangeBoundType; 244 | upperBound?: RangeBoundType; 245 | }, 246 | >(name: TName, config?: TConfig) { 247 | return customType<{ 248 | data: RangeValue; 249 | driverData: string; 250 | config: TConfig; 251 | }>({ 252 | dataType() { 253 | return 'numrange'; 254 | }, 255 | fromDriver(value) { 256 | const parsed = range.parse(value, (value) => { 257 | return parseFloat(value); 258 | }); 259 | if (parsed.isEmpty()) { 260 | return RANGE_EMPTY; 261 | } 262 | return { lower: parsed.lower, upper: parsed.upper }; 263 | }, 264 | toDriver(value) { 265 | // Using canonical form of included lower bound and excluded upper bound. 266 | // See https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE 267 | const lb = RANGE_BOUND_BRACKETS.LOWER[config?.lowerBound ?? 'inclusive']; 268 | const ub = RANGE_BOUND_BRACKETS.UPPER[config?.upperBound ?? 'exclusive']; 269 | return `${lb}${value.lower ?? ''},${value.upper ?? ''}${ub}`; 270 | }, 271 | })(name, config); 272 | } 273 | -------------------------------------------------------------------------------- /src/pg/functions.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AnyColumn, 3 | AnyTable, 4 | ColumnsSelection, 5 | InferSelectModel, 6 | SQLChunk, 7 | SQLWrapper, 8 | Subquery, 9 | Table, 10 | TableConfig, 11 | View, 12 | } from 'drizzle-orm'; 13 | import { SQL, StringChunk, bindIfParam, isSQLWrapper, sql } from 'drizzle-orm'; 14 | import type { SetNonNullable } from 'type-fest'; 15 | import { type InferData } from '..'; 16 | import type { RegconfigString } from './constants'; 17 | 18 | /** 19 | * Postgres random function. 20 | * 21 | * @example 22 | * 23 | * ```sql 24 | * random(); 25 | * ``` 26 | * 27 | * @returns Random number between 0 and 1. 28 | */ 29 | export function random() { 30 | return sql`random()`; 31 | } 32 | 33 | /** 34 | * Get the current time (dynamically). 35 | * 36 | * @example 37 | * 38 | * ```sql 39 | * now(); 40 | * ``` 41 | */ 42 | export function now() { 43 | return sql`now()`; 44 | } 45 | 46 | /** 47 | * True if all input values are true, otherwise false. 48 | */ 49 | export function boolAnd(...expression: SQLWrapper[]) { 50 | return sql`bool_and(${sql.join(expression, new StringChunk(', '))})`; 51 | } 52 | 53 | /** 54 | * True if at least one input value is true, otherwise false. 55 | */ 56 | export function boolOr(...expression: SQLWrapper[]) { 57 | return sql`bool_or(${sql.join(expression, new StringChunk(', '))})`; 58 | } 59 | 60 | /** 61 | * SQL json_strip_nulls. 62 | */ 63 | export function jsonStripNulls(json: T) { 64 | return sql : T>>`json_strip_nulls(${json})`; 65 | } 66 | 67 | /** 68 | * Aggregate sql values into an sql array. 69 | * 70 | * Input values, including nulls, concatenated into an array. 71 | * 72 | * Input arrays concatenated into array of one higher dimension (inputs must all have same 73 | * dimensionality, and cannot be empty or null) 74 | * 75 | * @see https://www.postgresql.org/docs/9.5/functions-aggregate.html 76 | * 77 | * @todo Implement collapsing for null array with notNull option. 78 | */ 79 | export function arrayAgg< 80 | T extends SQLWrapper, 81 | // N extends boolean = true 82 | >( 83 | expression: T 84 | // { notNull = true as N }: { notNull?: N } = {} 85 | ) { 86 | return sql | null>`array_agg(${expression})`; 87 | } 88 | 89 | /** 90 | * @see https://www.postgresql.org/docs/9.5/functions-json.html#FUNCTIONS-JSON-CREATION-TABLE 91 | */ 92 | export function toJson(anyelement: T) { 93 | return sql>`to_json(${anyelement})`; 94 | } 95 | 96 | export function toJsonb(anyelement: T) { 97 | return sql>`to_jsonb(${anyelement})`; 98 | } 99 | 100 | /** 101 | * Since it is a json method, it should return an unwrapped (raw) type instead of an SQL wrapped 102 | * type. 103 | */ 104 | export function rowToJson(row: T) { 105 | return sql>`row_to_json(${row})`; 106 | } 107 | 108 | /** 109 | * Build objects using `json_build_object(k1, v1, ...kn, vn). Since it is a json method, it should 110 | * return an object with unwrapped value types instead of SQL wrapped types. 111 | */ 112 | export function jsonBuildObject(shape: T) { 113 | const chunks: SQL[] = []; 114 | Object.entries(shape).forEach(([key, value]) => { 115 | if (chunks.length > 0) { 116 | chunks.push(sql.raw(`,`)); 117 | } 118 | chunks.push(sql.raw(`'${key}',`)); 119 | chunks.push(sql`${value}`); 120 | }); 121 | return sql<{ 122 | [K in keyof T]: T[K] extends SQLWrapper ? InferData : T[K]; 123 | }>`json_build_object(${sql.join(chunks)})`; 124 | } 125 | 126 | /** 127 | * Build objects using `jsonb_build_object(k1, v1, ...kn, vn). Since it is a jsonb method, it should 128 | * return an object with unwrapped value types instead of SQL wrapped types. 129 | */ 130 | export function jsonbBuildObject(shape: T) { 131 | const chunks: SQLChunk[] = []; 132 | Object.entries(shape).forEach(([key, value]) => { 133 | if (chunks.length > 0) { 134 | chunks.push(sql.raw(`,`)); 135 | } 136 | chunks.push(sql.raw(`'${key}',`)); 137 | chunks.push(sql`${value}`); 138 | }); 139 | return sql<{ 140 | [K in keyof T]: T[K] extends SQLWrapper ? InferData : T[K]; 141 | }>`jsonb_build_object(${sql.join(chunks)})`; 142 | } 143 | 144 | /** 145 | * Aggregate sql values into an array of json objects using a combination of `json_agg` and 146 | * `jsonb_build_object`. Jsonb object building is used in lieu of json to allow use of distinct. 147 | */ 148 | export function jsonAggBuildObject( 149 | shape: T, 150 | { 151 | distinct = true, 152 | // notNull, 153 | }: { 154 | distinct?: boolean; 155 | // notNull?: boolean; 156 | } = {} 157 | ) { 158 | return sql< 159 | { 160 | [K in keyof T]: T[K] extends SQLWrapper ? InferData : T[K]; 161 | }[] 162 | >`coalesce(json_agg(${sql.raw(distinct ? 'distinct' : '')} ${jsonbBuildObject(shape)}), '${sql`[]`}')`; 163 | } 164 | 165 | /** 166 | * Aggregates name/value pairs as a JSON object; values can be null, but not names. 167 | * 168 | * Build object using `json_object_agg`. Since it is a json method, it should return an unwrapped 169 | * type instead of an SQL wrapped type. 170 | * 171 | * @example 172 | * 173 | * ```sql 174 | * json_object_agg(...) 175 | * ``` 176 | * 177 | * @see https://www.postgresql.org/docs/9.5/functions-aggregate.html 178 | */ 179 | export function jsonObjectAgg< 180 | K extends AnyColumn, 181 | V extends SQL | SQL.Aliased | AnyTable, 182 | TK extends string | number = null extends InferData 183 | ? never 184 | : InferData extends string | number 185 | ? InferData 186 | : never, 187 | TV = V extends AnyTable ? InferSelectModel : V extends SQL ? InferData : never, 188 | >(name: K, value: V) { 189 | return sql>`json_object_agg(${name}, ${value})`; 190 | } 191 | 192 | /** 193 | * Aggregates name/value pairs as a JSON object; values can be null, but not names. 194 | * 195 | * @example 196 | * 197 | * ```sql 198 | * jsonb_object_agg(...) 199 | * ``` 200 | * 201 | * @see https://www.postgresql.org/docs/9.5/functions-aggregate.html 202 | */ 203 | export function jsonbObjectAgg< 204 | K extends AnyColumn, 205 | V extends SQL | SQL.Aliased | AnyTable, 206 | TK extends string | number = null extends InferData 207 | ? never 208 | : InferData extends string | number 209 | ? InferData 210 | : never, 211 | TV = V extends AnyTable ? InferSelectModel : V extends SQL ? InferData : never, 212 | >(name: K, value: V) { 213 | return sql>`jsonb_object_agg(${name}, ${value})`; 214 | } 215 | 216 | /** 217 | * Aggregates values, including nulls, as a JSON array. 218 | * 219 | * @see https://www.postgresql.org/docs/9.5/functions-aggregate.html 220 | */ 221 | export function jsonAgg( 222 | selection: T, 223 | { notNull = true as N }: { notNull?: N } = {} 224 | ): SQL>[] : InferData[] | [null]> { 225 | if (notNull) { 226 | return sql`coalesce(json_agg(${selection}) filter (where ${selection} is not null), '[]')`; 227 | } 228 | return sql`json_agg(${selection})`; 229 | } 230 | 231 | /** 232 | * Get the database's currently set regconfig for text-search functionalities. 233 | * 234 | * ```sql 235 | * get_current_ts_config(); 236 | * ``` 237 | */ 238 | export function getCurrentTsConfig() { 239 | return sql`get_current_ts_config()`; 240 | } 241 | 242 | /** 243 | * @param regconfig Laguage configuration to use when converting source text to text search vector. 244 | * @param text Source text to convert into a text search vector. 245 | * 246 | * ```sql 247 | * to_tsvector(); 248 | * --or; 249 | * plainto_tsvector(); 250 | * ``` 251 | */ 252 | export function toTsvector( 253 | text: unknown, 254 | { regconfig }: { regconfig?: RegconfigString | SQLWrapper } = {} 255 | ) { 256 | if (regconfig) { 257 | const value = isSQLWrapper(regconfig) ? bindIfParam(text, regconfig) : text; 258 | return sql`to_tsvector(${regconfig}, ${value})`.mapWith(String); 259 | } 260 | return sql`to_tsvector(${text})`.mapWith(String); 261 | } 262 | 263 | /** 264 | * @param regconfig Language config for the text search query. 265 | * @param text Source text to convert into a text search query. 266 | * @param config.plain Specifies if the source text should be compared as a plain (case insensitive) 267 | * query. 268 | * 269 | * ```sql 270 | * to_tsvector(); 271 | * ``` 272 | */ 273 | export function toTsquery( 274 | text: unknown, 275 | { 276 | plain = false, 277 | regconfig, 278 | }: { 279 | plain?: boolean; 280 | regconfig?: SQLWrapper | RegconfigString; 281 | } = {} 282 | ) { 283 | const start = new StringChunk(plain ? 'plainto_tsquery(' : 'to_tsquery('); 284 | const end = new StringChunk(')'); 285 | const chunks: SQLChunk[] = []; 286 | if (regconfig) { 287 | chunks.push(sql`${regconfig},`); 288 | } 289 | chunks.push(isSQLWrapper(regconfig) ? sql`${bindIfParam(text, regconfig)}` : sql`${text}`); 290 | return new SQL([start, sql.join(chunks, new StringChunk(' ')), end]).mapWith(String); 291 | } 292 | 293 | /** 294 | * The function setweight can be used to label the entries of a tsvector with a given weight, where 295 | * a weight is one of the letters A, B, C, or D. This is typically used to mark entries coming from 296 | * different parts of a document, such as title versus body. Later, this information can be used for 297 | * ranking of search results. 298 | * 299 | * Because to_tsvector(NULL) will return NULL, it is recommended to use coalesce whenever a field 300 | * might be null. 301 | */ 302 | export function setweight(tsvector: SQLWrapper, weight: string | number) { 303 | const char = typeof weight === 'string' ? weight : String.fromCharCode(weight + 65); 304 | return sql`setweight(${tsvector}, ${char})`.mapWith(String); 305 | } 306 | 307 | /** 308 | * Subtract arguments, producing a “symbolic” result that uses years and months, rather than just 309 | * days. 310 | * 311 | * @example 312 | * 313 | * ```sql 314 | * -- age ( timestamp, timestamp ) → interval 315 | * age(timestamp '2001-04-10', timestamp '1957-06-13') → 43 years 9 mons 27 days 316 | * ``` 317 | */ 318 | export function age( 319 | origin: TOrigin, 320 | target: TTarget 321 | ) { 322 | return sql`age(${origin},${target})`.mapWith(String); 323 | } 324 | 325 | export function isEmpty(range: T) { 326 | return sql`isempty(${range})`.mapWith(Boolean); 327 | } 328 | -------------------------------------------------------------------------------- /src/pg/fuzzystrmatch/README.md: -------------------------------------------------------------------------------- 1 | # Fuzzystrmatch extension 2 | 3 | 4 | 5 | ```sql 6 | create extension fuzzystrmatch /* with schema [your extensions schema] */; 7 | ``` 8 | -------------------------------------------------------------------------------- /src/pg/fuzzystrmatch/functions.ts: -------------------------------------------------------------------------------- 1 | import type { SQLWrapper } from 'drizzle-orm'; 2 | import { sql } from 'drizzle-orm'; 3 | 4 | /** 5 | * @see https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-SOUNDEX 6 | */ 7 | export function soundex(text: string | SQLWrapper) { 8 | return sql`soundex(${text})`.mapWith(String); 9 | } 10 | 11 | /** 12 | * @see https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF 13 | */ 14 | export function difference(...texts: [string | SQLWrapper, string | SQLWrapper]) { 15 | return sql`difference(${texts[0]}, ${texts[1]})`.mapWith(Number); 16 | } 17 | 18 | /** 19 | * @see https://www.postgresql.org/docs/current/fuzzystrmatch.html#FUZZYSTRMATCH-DAITCH-MOKOTOFF 20 | */ 21 | export function daitch_mokotoff(source: SQLWrapper | string) { 22 | return sql`daitch_mokotoff(${source})`; 23 | } 24 | -------------------------------------------------------------------------------- /src/pg/fuzzystrmatch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './functions'; 2 | -------------------------------------------------------------------------------- /src/pg/index.ts: -------------------------------------------------------------------------------- 1 | export * from './citext'; 2 | export * from './cube'; 3 | export * from './fuzzystrmatch'; 4 | export * from './pgcrypto'; 5 | export * from './pgtrgm'; 6 | export * from './postgis'; 7 | 8 | export * from './constants'; 9 | export * from './custom-types'; 10 | export * from './functions'; 11 | export * from './operators'; 12 | export * from './utilities'; 13 | export * from './validation'; 14 | export * from './values'; 15 | -------------------------------------------------------------------------------- /src/pg/internals.ts: -------------------------------------------------------------------------------- 1 | import { RANGE_BOUND_TYPES, type RangeBoundType } from '.'; 2 | 3 | export const RANGE_BOUND_BRACKETS = { 4 | LOWER: { 5 | [RANGE_BOUND_TYPES.INCLUSIVE]: '[', 6 | [RANGE_BOUND_TYPES.EXCLUSIVE]: '(', 7 | }, 8 | UPPER: { 9 | [RANGE_BOUND_TYPES.INCLUSIVE]: ']', 10 | [RANGE_BOUND_TYPES.EXCLUSIVE]: ')', 11 | }, 12 | } satisfies Record<'UPPER' | 'LOWER', Record>; 13 | -------------------------------------------------------------------------------- /src/pg/operators.ts: -------------------------------------------------------------------------------- 1 | import type { SQLWrapper } from 'drizzle-orm'; 2 | import { bindIfParam, sql } from 'drizzle-orm'; 3 | 4 | /** 5 | * Test a text search query against a ts_vector value. 6 | */ 7 | export function ts(vector: SQLWrapper, querytext: SQLWrapper) { 8 | return sql`${vector} @@ ${bindIfParam(querytext, vector)}`; 9 | } 10 | -------------------------------------------------------------------------------- /src/pg/pgcrypto/README.md: -------------------------------------------------------------------------------- 1 | # Pgcrypto extension and utils 2 | 3 | ```sql 4 | create extension pgcrypto /* with schema [your extensions schema] */; 5 | ``` 6 | -------------------------------------------------------------------------------- /src/pg/pgcrypto/functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'drizzle-orm'; 2 | 3 | /** 4 | * Generate a nanoid using a postgres implementation of the nanoid function. 5 | * 6 | * @param config.optimized Should the postgres extension use optimization. 7 | * @param config.size The length of the nanoid generated. If explicit nullish is passed, will 8 | * default to the Postgres function's default size. 9 | * @param config.alphabet The set of characters to pick randomly from. Defaults to 10 | * '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. If explicit nullish is 11 | * passed, will default to the Postgres function's default alphabet. 12 | * @param config.additionalBytesFactor 13 | * @param config.mask 14 | * @param config.step 15 | * @see {@link https://github.com/iolyd/drizzle-orm-helpers/blob/main/sql/nanoid.sql Postgres implementation of the nanoid generator} 16 | * @see https://discord.com/channels/1043890932593987624/1093946807911989369/1100459226087825571 17 | * @todo Stay up to date when default values will accept 'sql' without having to pass param to 18 | * sql.raw() 19 | */ 20 | export function nanoid({ 21 | optimized, 22 | size, 23 | alphabet, 24 | additionalBytesFactor, 25 | mask, 26 | step, 27 | }: { 28 | size?: number; 29 | alphabet?: string; 30 | } & ( 31 | | { 32 | optimized?: false; 33 | additionalBytesFactor?: number; 34 | mask?: never; 35 | step?: never; 36 | } 37 | | { 38 | optimized: true; 39 | additionalBytesFactor?: never; 40 | mask?: number; 41 | step?: number; 42 | } 43 | ) = {}) { 44 | const params: string[] = []; 45 | if (size) { 46 | params.push(`size => ${size}`); 47 | } 48 | if (alphabet) { 49 | params.push(`alphabet => '${alphabet}'`); 50 | } 51 | if (additionalBytesFactor) { 52 | params.push(`additionalBytesFactor => ${additionalBytesFactor}`); 53 | } 54 | if (mask) { 55 | params.push(`mask => ${mask}`); 56 | } 57 | if (step) { 58 | params.push(`step => ${step}`); 59 | } 60 | const fname = optimized ? 'nanoid_optimized' : 'nanoid'; 61 | // return new SQL([ 62 | // new StringChunk(`${getSchemaPrefix.call(this)}${fname}(`), 63 | // sql.join(chunks, new StringChunk(', ')), 64 | // new StringChunk(')'), 65 | // ]).mapWith(String); 66 | return sql.raw(`${fname}(${params.join(',')})`).mapWith(String); 67 | } 68 | -------------------------------------------------------------------------------- /src/pg/pgcrypto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './functions'; 2 | -------------------------------------------------------------------------------- /src/pg/pgtrgm/README.md: -------------------------------------------------------------------------------- 1 | # Pg_trgm extension and utils 2 | 3 | 4 | 5 | ```sql 6 | create extension pg_trgm /* with schema [your extensions schema] */; 7 | ``` 8 | -------------------------------------------------------------------------------- /src/pg/pgtrgm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './operators'; 2 | -------------------------------------------------------------------------------- /src/pg/pgtrgm/operators.ts: -------------------------------------------------------------------------------- 1 | // text % text → boolean 2 | // Returns true if its arguments have a similarity that is greater than the current similarity threshold set by pg_trgm.similarity_threshold. 3 | export function similar() {} 4 | 5 | // text <% text → boolean 6 | // Returns true if the similarity between the trigram set in the first argument and a continuous extent of an ordered trigram set in the second argument is greater than the current word similarity threshold set by pg_trgm.word_similarity_threshold parameter. 7 | 8 | // text %> text → boolean 9 | // Commutator of the <% operator. 10 | 11 | // text <<% text → boolean 12 | // Returns true if its second argument has a continuous extent of an ordered trigram set that matches word boundaries, and its similarity to the trigram set of the first argument is greater than the current strict word similarity threshold set by the pg_trgm.strict_word_similarity_threshold parameter. 13 | 14 | // text %>> text → boolean 15 | // Commutator of the <<% operator. 16 | 17 | // text <-> text → real 18 | // Returns the “distance” between the arguments, that is one minus the similarity() value. 19 | 20 | // text <<-> text → real 21 | // Returns the “distance” between the arguments, that is one minus the word_similarity() value. 22 | 23 | // text <->> text → real 24 | // Commutator of the <<-> operator. 25 | 26 | // text <<<-> text → real 27 | // Returns the “distance” between the arguments, that is one minus the strict_word_similarity() value. 28 | 29 | // text <->>> text → real 30 | // Commutator of the <<<-> operator. 31 | -------------------------------------------------------------------------------- /src/pg/postgis/README.md: -------------------------------------------------------------------------------- 1 | # PostGIS extension 2 | 3 | 4 | 5 | ```sql 6 | create extension postgis /* with schema [your extensions schema] */; 7 | ``` 8 | -------------------------------------------------------------------------------- /src/pg/postgis/constants.ts: -------------------------------------------------------------------------------- 1 | import type { ValueOf } from 'type-fest'; 2 | 3 | /** 4 | * Common coordinate projection systems and their Spatial Reference System ID (EPSG). 5 | * 6 | * @example 7 | * 8 | * ```sql 9 | * SELECT * FROM extensions.spatial_ref_sys; 10 | * ``` 11 | * 12 | * @todo Add more aliased systems. 13 | */ 14 | export const SRIDS = { 15 | /** 16 | * Lat/Lon globe-based coordinate system. Uses degrees to represent spheroid position. 17 | */ 18 | WGS84: 4326, 19 | /** 20 | * Lat/Lon flat-map coordinates in meters. Generally the default system used for web apps. 21 | */ 22 | WEB_MERCATOR: 3857, 23 | } as const; 24 | export type Srid = ValueOf | `${ValueOf}`; 25 | -------------------------------------------------------------------------------- /src/pg/postgis/custom-types.ts: -------------------------------------------------------------------------------- 1 | import { customType } from 'drizzle-orm/pg-core'; 2 | import type { GeoJsonGeometryTypes, Geometry } from 'geojson'; 3 | import { SRIDS, type Srid } from './constants'; 4 | 5 | /** 6 | * PostGIS column type for generic or specific geographies. 7 | * 8 | * **⚠️ Warning ⚠️** 9 | * 10 | * Uses a nasty trick to get the data back as properly formatted GeoJSON rather than WKT. Expect 11 | * things to break. 12 | * 13 | * @see Unstable until better support for custom type custom select is available (e.g. https://github.com/drizzle-team/drizzle-orm/pull/1423) 14 | */ 15 | export function geography< 16 | TName extends string, 17 | TGeography extends GeoJsonGeometryTypes, 18 | TZ extends boolean, 19 | TM extends boolean, 20 | TSrid extends Srid, 21 | >(name: TName, config?: { type?: TGeography; z?: TZ; m?: TM; srid?: TSrid }) { 22 | const z = config?.z ? 'Z' : ''; 23 | const m = config?.m ? 'M' : ''; 24 | const srid = config?.srid ? `,${config.srid}` : ''; 25 | const basetype = config?.type ? config.type : z || m || srid ? 'Geography' : ''; 26 | const type = `${basetype}${z}${m}`; 27 | return customType<{ 28 | data: Extract; 29 | driverData: string; 30 | config: typeof config; 31 | }>({ 32 | dataType() { 33 | const paren = type ? `(${type}${srid})` : ''; 34 | return `geography${paren}`; 35 | }, 36 | toDriver(value) { 37 | return `st_transform(st_geomfromgeojson(${JSON.stringify(value)}),${srid ?? SRIDS.WEB_MERCATOR})::geography`; 38 | }, 39 | fromDriver(value) { 40 | try { 41 | const parsed = JSON.parse(value); 42 | if (config?.type && parsed.type !== config.type) { 43 | throw new Error(`Expected geography type ${config.type}, got ${parsed.type}`); 44 | } 45 | return parsed; 46 | } catch (err) { 47 | throw new Error(`Failed to parse geography`, { 48 | cause: err, 49 | }); 50 | } 51 | }, 52 | })(`st_asgeojson"("${name}") as "${name}`, config); 53 | } 54 | 55 | /** 56 | * - PostGIS column type for generic or specific geometries. 57 | * 58 | * **⚠️ Warning ⚠️** 59 | * 60 | * Uses a nasty trick to get the data back as properly formatted GeoJSON rather than WKT. Expect 61 | * things to break. 62 | * 63 | * @see Unstable until better support for custom type custom select is available (e.g. https://github.com/drizzle-team/drizzle-orm/pull/1423) 64 | */ 65 | export function geometry< 66 | TName extends string, 67 | TGeometry extends GeoJsonGeometryTypes, 68 | TZ extends boolean, 69 | TM extends boolean, 70 | TSrid extends Srid, 71 | >(name: TName, config?: { type?: TGeometry; z?: TZ; m?: TM; srid?: TSrid }) { 72 | const z = config?.z ? 'Z' : ''; 73 | const m = config?.m ? 'M' : ''; 74 | const srid = config?.srid ? `,${config.srid}` : ''; 75 | const basetype = config?.type ? config.type : z || m || srid ? 'Geography' : ''; 76 | const type = `${basetype}${z}${m}`; 77 | return customType<{ 78 | data: Extract; 79 | driverData: string; 80 | config: typeof config; 81 | }>({ 82 | dataType() { 83 | const paren = type ? `(${type}${srid})` : ''; 84 | return `geometry${paren}`; 85 | }, 86 | toDriver(value) { 87 | return `st_transform(st_geomfromgeojson(${JSON.stringify(value)}),${srid ?? SRIDS.WEB_MERCATOR})::geometry`; 88 | }, 89 | fromDriver(value) { 90 | try { 91 | const parsed = JSON.parse(value); 92 | if (config?.type && parsed.type !== config.type) { 93 | throw new Error(`Expected geometry type ${config.type}, got ${parsed.type}`); 94 | } 95 | return parsed; 96 | } catch (err) { 97 | throw new Error(`Failed to parse geometry`, { 98 | cause: err, 99 | }); 100 | } 101 | }, 102 | })(`st_asgeojson"("${name}") as "${name}`, config); 103 | } 104 | -------------------------------------------------------------------------------- /src/pg/postgis/functions.ts: -------------------------------------------------------------------------------- 1 | import { StringChunk, isSQLWrapper, sql, type SQLWrapper } from 'drizzle-orm'; 2 | import type { Geometry } from 'geojson'; 3 | 4 | /** 5 | * @example 6 | * 7 | * ```sql 8 | * st_astext(geometry or geography); 9 | * ``` 10 | */ 11 | export function stAstext(geo: SQLWrapper) { 12 | return sql`st_astext(${geo})`; 13 | } 14 | 15 | /** 16 | * @example 17 | * 18 | * ```sql 19 | * ST_AsGeoJSON(geom or geog) 20 | * ``` 21 | * 22 | * @see https://postgis.net/docs/ST_AsGeoJSON.html 23 | */ 24 | export function stAsGeoJSON(geo: SQLWrapper) { 25 | return sql`st_asgeojson(${geo})`; 26 | } 27 | 28 | /** 29 | * @example 30 | * 31 | * ```sql 32 | * ST_GeomFromGeoJSON(geojson); 33 | * ``` 34 | */ 35 | export function stGeomFromGeoJSON(geojson: SQLWrapper | Geometry) { 36 | const param = isSQLWrapper(geojson) ? geojson : JSON.stringify(geojson); 37 | return sql`st_geomfromgeojson(${param})::geography`.mapWith(String); 38 | } 39 | 40 | /** 41 | * @example 42 | * 43 | * ```sql 44 | * st_point(long, lat); 45 | * ``` 46 | */ 47 | export function stPoint( 48 | longitude: SQLWrapper | string | number, 49 | lattitude: SQLWrapper | string | number 50 | ) { 51 | return sql`st_point(${longitude}, ${lattitude})`; 52 | } 53 | 54 | /** 55 | * @example 56 | * 57 | * ```sql 58 | * st_distance(point, point); 59 | * ``` 60 | */ 61 | export function stDistance( 62 | ...points: [SQLWrapper | string | number, SQLWrapper | string | number] 63 | ) { 64 | const chunks = sql.join(points, new StringChunk(',')); 65 | return sql`st_distance(${chunks})`; 66 | } 67 | -------------------------------------------------------------------------------- /src/pg/postgis/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-types'; 2 | -------------------------------------------------------------------------------- /src/pg/postgis/operators.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emmnull/drizzle-orm-helpers/035ffd5af68ebc2773011445cf3a2c753c55a3fb/src/pg/postgis/operators.ts -------------------------------------------------------------------------------- /src/pg/utilities.ts: -------------------------------------------------------------------------------- 1 | import { SQL, StringChunk, isSQLWrapper, sql, type AnyColumn, type SQLWrapper } from 'drizzle-orm'; 2 | import { customType } from 'drizzle-orm/pg-core'; 3 | import { INTERVAL_UNITS_ARR_ORDERED, type IntervalUnit, type RangeBoundType } from '.'; 4 | import type { InferData } from '..'; 5 | import { PG_DIALECT } from '../internals'; 6 | import { RANGE_BOUND_BRACKETS } from './internals'; 7 | 8 | export type RangeValue = { upper: T | null; lower: T | null }; 9 | 10 | /** 11 | * Get excluded column values in conflict cases. Useful for onConflictDoUpdate's set. 12 | * 13 | * @param columns Record of columns to get from the conflict's `excluded` table. 14 | */ 15 | export function toExcluded>(columns: T) { 16 | return (Object.keys(columns) as (keyof T)[]).reduce( 17 | (acc, curr) => { 18 | acc[curr] = sql.raw(`excluded.${columns[curr].name}`) as SQL>; 19 | return acc; 20 | }, 21 | <{ [K in keyof T]: SQL> }>{} 22 | ); 23 | } 24 | 25 | /** 26 | * Tsvector type for generated columns used notably for fuzzy string search. 27 | * 28 | * @param config.sources Array of source columns to generate the ts vector from. 29 | * @param config.langauge Regconfig column or sql value (conditional values, or other) to use for 30 | * the vector, used for stemming. (regconfig cfgname). 31 | * @param config.weighted If true, concatenated sources will be weighted by their order. 32 | * @see https://github.com/drizzle-team/drizzle-orm/issues/247 33 | * @todo Implementation isn't clean. Figure out a better way to map the language name and column 34 | * references, or stay up to date on support for `generatedAs()`. 35 | */ 36 | export const generatedTsvector = customType<{ 37 | data: string; 38 | configRequired: true; 39 | config: { 40 | sources: string[]; 41 | language: string | SQLWrapper; 42 | weighted?: boolean; 43 | }; 44 | }>({ 45 | dataType(config) { 46 | const cfgname = isSQLWrapper(config.language) 47 | ? PG_DIALECT.sqlToQuery(config.language.getSQL().inlineParams()).sql 48 | : config.language; 49 | if (config.weighted) { 50 | const weighted = config.sources.map((input, index) => { 51 | const weight = String.fromCharCode(index + 65); 52 | return `setweight(to_tsvector(${cfgname}, coalesce(${input}, '')), '${weight}')`; 53 | }); 54 | return `tsvector generated always as (${weighted.join(' || ')}) stored`; 55 | } else { 56 | const source = config.sources.join(" || ' ' || "); 57 | return `tsvector generated always as (to_tsvector(${config.language}, ${source})) stored`; 58 | } 59 | }, 60 | }); 61 | 62 | /** 63 | * Create an interval value by passing a value deconstructed into time units. 64 | */ 65 | export function toInterval>>(value: T) { 66 | const units = INTERVAL_UNITS_ARR_ORDERED.reduce( 67 | (acc, curr) => { 68 | if (value[curr] != null) { 69 | acc.push(new SQL([sql`${value[curr]}`, new StringChunk(` ${curr}`)])); 70 | } 71 | return acc; 72 | }, 73 | [] 74 | ); 75 | return new SQL([ 76 | new StringChunk("(interval '"), 77 | sql.join(units, new StringChunk(' ')), 78 | new StringChunk("')"), 79 | ]).mapWith(String); 80 | } 81 | 82 | /** 83 | * Using canonical form of included lower bound and excluded upper bound. See 84 | * https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-DISCRETE. 85 | */ 86 | export function toRange< 87 | const T extends [number | undefined, number | undefined] | [Date | undefined, Date | undefined], 88 | >( 89 | tuple: T, 90 | { 91 | lowerBound = 'inclusive', 92 | upperBound = 'exclusive', 93 | }: { lowerBound?: RangeBoundType; upperBound?: RangeBoundType } = {} 94 | ) { 95 | const lb = RANGE_BOUND_BRACKETS.LOWER[lowerBound]; 96 | const ub = RANGE_BOUND_BRACKETS.UPPER[upperBound]; 97 | return sql`${lb}${tuple[0]},${tuple[1]}${ub}`; 98 | } 99 | -------------------------------------------------------------------------------- /src/pg/validation.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | export function intrangeSchema({ 4 | min, 5 | max, 6 | }: { 7 | min?: number; 8 | max?: number; 9 | } = {}) { 10 | const baseSchema = z.number().int(); 11 | const lowerSchema = (min ? baseSchema.min(min) : baseSchema).nullable(); 12 | const upperSchema = (max ? baseSchema.max(max) : baseSchema).nullable(); 13 | return z.object({ 14 | lower: lowerSchema, 15 | upper: upperSchema, 16 | }); 17 | } 18 | 19 | export function numrangeSchema({ 20 | min, 21 | max, 22 | }: { 23 | min?: number; 24 | max?: number; 25 | } = {}) { 26 | const lowerSchema = (min ? z.number().min(min) : z.number()).nullable(); 27 | const upperSchema = (max ? z.number().max(max) : z.number()).nullable(); 28 | return z.object({ 29 | lower: lowerSchema, 30 | upper: upperSchema, 31 | }); 32 | } 33 | 34 | function dateToString(date: Date, withTimezone?: boolean) { 35 | if (withTimezone) { 36 | return date.toISOString(); 37 | } 38 | const tzOffset = date.getTimezoneOffset() * 6_000; 39 | return new Date(date.valueOf() - tzOffset).toISOString().slice(0, -1); 40 | } 41 | 42 | /** 43 | * Because of typescript's peculiar handling of Inifinity/-Infinity, ranges without limit need to 44 | * consider number members that indicate infinite bounds. 45 | */ 46 | export function tsrangeSchema< 47 | TMode extends 'date' | 'string', 48 | TData = TMode extends 'string' ? string : Date | number, 49 | >({ 50 | min, 51 | max, 52 | withTimezone, 53 | mode, 54 | }: { 55 | min?: Date; 56 | max?: Date; 57 | withTimezone?: boolean; 58 | mode?: TMode; 59 | } = {}) { 60 | const baseSchema = z.date({ coerce: mode === 'string' }); 61 | const infinitySchema = z.number({ coerce: mode === 'string' }); 62 | function toMode(d: number | Date | null): TData { 63 | if (mode === 'string' && d !== null) { 64 | if (d instanceof Date) { 65 | return dateToString(d, withTimezone) as TData; 66 | } 67 | if (d === -Infinity) { 68 | return '-infinity' as TData; 69 | } 70 | if (d === Infinity) { 71 | return 'infinity' as TData; 72 | } 73 | return d.toString() as TData; 74 | } 75 | return d as TData; 76 | } 77 | const lowerSchema = (min ? baseSchema.min(min) : baseSchema.or(infinitySchema)) 78 | .nullable() 79 | .transform(toMode); 80 | const upperSchema = (max ? baseSchema.max(max) : baseSchema.or(infinitySchema)) 81 | .nullable() 82 | .transform(toMode); 83 | return z.object({ 84 | lower: lowerSchema, 85 | upper: upperSchema, 86 | }); 87 | } 88 | 89 | export function daterangeSchema< 90 | TMode extends 'string' | 'date', 91 | TData = TMode extends 'string' ? string : Date | number, 92 | >({ 93 | min, 94 | max, 95 | mode, 96 | }: { 97 | min?: Date; 98 | max?: Date; 99 | mode?: TMode; 100 | } = {}) { 101 | const baseSchema = z.date({ coerce: mode === 'string' }); 102 | const infinitySchema = z.number({ coerce: mode === 'string' }); 103 | function toMode(d: number | Date | null): TData { 104 | if (mode === 'string' && d !== null) { 105 | if (d instanceof Date) { 106 | return dateToString(d) as TData; 107 | } 108 | if (d === -Infinity) { 109 | return '-infinity' as TData; 110 | } 111 | if (d === Infinity) { 112 | return 'infinity' as TData; 113 | } 114 | return d.toString() as TData; 115 | } 116 | return d as TData; 117 | } 118 | const lowerSchema = (min ? baseSchema.min(min) : baseSchema.or(infinitySchema)) 119 | .nullable() 120 | .transform(toMode); 121 | const upperSchema = (max ? baseSchema.max(max) : baseSchema.or(infinitySchema)) 122 | .nullable() 123 | .transform(toMode); 124 | return z.object({ 125 | lower: lowerSchema, 126 | upper: upperSchema, 127 | }); 128 | } 129 | -------------------------------------------------------------------------------- /src/pg/values.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'drizzle-orm'; 2 | 3 | /** 4 | * Empty record as SQL json. 5 | */ 6 | export const $emptyJsonObject = sql`'{}'::json`; 7 | 8 | /** 9 | * Empty array as SQL json. 10 | */ 11 | export const $emptyJsonArray = sql<[never]>`'[]'::json`; 12 | 13 | /** 14 | * Empty SQL array (not json typed) 15 | */ 16 | export const $emptyArray = sql<[]>`'{}'`; 17 | 18 | /** 19 | * An array with a single null member. Typically returned when aggregation result is empty. 20 | */ 21 | export const $nullArray = sql<[null]>`'{null}'`; 22 | 23 | /** 24 | * Postgres value returned for empty ranges. 25 | */ 26 | export const $empty = sql<"'empty'" | []>`'empty'`; 27 | -------------------------------------------------------------------------------- /src/sqlite/functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'drizzle-orm'; 2 | 3 | /** 4 | * SQLite random function. 5 | * 6 | * @example 7 | * 8 | * ```sql 9 | * random(); 10 | * ``` 11 | * 12 | * @returns Random random integer between -9223372036854775808 and +9223372036854775807. 13 | */ 14 | export function random() { 15 | return sql`random()`; 16 | } 17 | -------------------------------------------------------------------------------- /src/sqlite/index.ts: -------------------------------------------------------------------------------- 1 | export * from './functions'; 2 | -------------------------------------------------------------------------------- /src/utilities.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Column, 3 | Placeholder, 4 | SQL, 5 | Subquery, 6 | Table, 7 | View, 8 | ViewBaseConfig, 9 | is, 10 | type AnyColumn, 11 | type ColumnBuilderBase, 12 | type ColumnsSelection, 13 | type InferSelectModel, 14 | type SQLWrapper, 15 | type WithSubquery, 16 | } from 'drizzle-orm'; 17 | import type { 18 | AnyMySqlSelect, 19 | MySqlSchema, 20 | MySqlSelect, 21 | SubqueryWithSelection as MySqlSubqueryWithSelection, 22 | WithSubqueryWithSelection as MySqlWithSubqueryWithSelection, 23 | } from 'drizzle-orm/mysql-core'; 24 | import type { 25 | AnyPgSelect, 26 | PgSchema, 27 | PgSelect, 28 | SubqueryWithSelection as PgSubqueryWithSelection, 29 | WithSubqueryWithSelection as PgWithSubqueryWithSelection, 30 | } from 'drizzle-orm/pg-core'; 31 | import type { 32 | AnySQLiteSelect, 33 | SQLiteSelect, 34 | SubqueryWithSelection as SQLiteSubqueryWithSelection, 35 | WithSubqueryWithSelection as SQLiteWithSubqueryWithSelection, 36 | } from 'drizzle-orm/sqlite-core'; 37 | import type { SetOptional } from 'type-fest'; 38 | 39 | /** 40 | * Dialect agnostic select. 41 | * 42 | * @see PgSelect. 43 | * @see MySqlSelect 44 | * @see SQLiteSelect 45 | */ 46 | export type Select = SetOptional; 47 | 48 | /** 49 | * Dialect-agnostic schema. Excludes SQLite. 50 | */ 51 | export type Schema = PgSchema | MySqlSchema; 52 | 53 | /** 54 | * Dialect-agnostic subquery with selection. 55 | */ 56 | export type SubqueryWithSelection = 57 | | MySqlSubqueryWithSelection 58 | | PgSubqueryWithSelection 59 | | SQLiteSubqueryWithSelection; 60 | 61 | /** 62 | * Dialect-agnostic with subquery with selection. 63 | */ 64 | export type WithSubqueryWithSelection = 65 | | PgWithSubqueryWithSelection 66 | | SQLiteWithSubqueryWithSelection 67 | | MySqlWithSubqueryWithSelection; 68 | 69 | /** 70 | * Dialect agnostic AnySelect. 71 | * 72 | * @see AnyPgSelect 73 | * @see AnyMySqlSelect 74 | * @see AnySQLiteSelect 75 | */ 76 | export type AnySelect = SetOptional; 77 | 78 | /** 79 | * Infer type of table column. 80 | */ 81 | export type InferColumnType ColumnBuilderBase> = AnyColumn< 82 | Pick['_'], 'data' | 'dataType'> 83 | >; 84 | 85 | /** 86 | * Infer any SQL wrapper's expected return data type. 87 | */ 88 | export type InferData = T extends Table 89 | ? InferSelectModel 90 | : T extends Column 91 | ? T['_']['notNull'] extends true 92 | ? T['_']['data'] 93 | : T['_']['data'] | null 94 | : T extends View | Subquery 95 | ? T['_']['selectedFields'] 96 | : T extends SQL 97 | ? U 98 | : T extends SQL.Aliased 99 | ? U 100 | : unknown; 101 | 102 | /** 103 | * Infer table columns or (sub)query fields. 104 | */ 105 | export type InferColumns = 106 | T extends Table 107 | ? T['_']['columns'] 108 | : T extends View | Subquery | WithSubquery | AnySelect 109 | ? T['_']['selectedFields'] 110 | : never; 111 | 112 | /** 113 | * Infer a table's name or a (sub)query's alias. 114 | */ 115 | export type InferNameOrAlias = T extends Table | View | Column 116 | ? T['_']['name'] 117 | : T extends Subquery | WithSubquery 118 | ? T['_']['alias'] 119 | : T extends AnySelect 120 | ? T['_']['tableName'] 121 | : T extends SQL.Aliased 122 | ? T['fieldAlias'] 123 | : T extends Placeholder 124 | ? T['name'] 125 | : undefined; 126 | 127 | /** 128 | * Should replace `getTableColumns` to allow for more input versatility. 129 | * 130 | * @see https://github.com/drizzle-team/drizzle-orm/pull/1789 131 | */ 132 | export function getColumns< 133 | T extends 134 | | Table 135 | | View 136 | | Subquery 137 | | WithSubquery 138 | | AnySelect, 139 | >(table: T): InferColumns { 140 | return is(table, Table) 141 | ? // eslint-disable-next-line @typescript-eslint/no-explicit-any 142 | (table as any)[(Table as any).Symbol.Columns] 143 | : is(table, View) 144 | ? // eslint-disable-next-line @typescript-eslint/no-explicit-any 145 | (table as any)[ViewBaseConfig].selectedFields 146 | : // eslint-disable-next-line @typescript-eslint/no-explicit-any 147 | table._.selectedFields; 148 | } 149 | 150 | /** 151 | * Get a table's name or a (sub)query's alias. 152 | */ 153 | export function getNameOrAlias(query: T): InferNameOrAlias { 154 | return is(query, Table) 155 | ? // eslint-disable-next-line @typescript-eslint/no-explicit-any 156 | (query as any)[(Table as any).Symbol.Name] 157 | : is(query, View) 158 | ? // eslint-disable-next-line @typescript-eslint/no-explicit-any 159 | (query as any)[ViewBaseConfig].name 160 | : is(query, Column) 161 | ? query.name 162 | : is(query, Subquery) 163 | ? // eslint-disable-next-line @typescript-eslint/no-explicit-any 164 | query._.alias 165 | : is(query, SQL.Aliased) 166 | ? query.fieldAlias 167 | : is(query, Placeholder) 168 | ? query.name 169 | : undefined; 170 | } 171 | 172 | /** 173 | * Paginate a query. 174 | */ 175 | export function paginate( 176 | qb: T, 177 | { page, size = 20 }: { page: number; size?: number } 178 | ) { 179 | return qb.limit(size).offset(page * size); 180 | } 181 | 182 | // /** 183 | // * ... 184 | // */ 185 | // export function uuidDashless() { 186 | // return sql`replace(uuid(), '-', '')`.mapWith(String); 187 | // } 188 | -------------------------------------------------------------------------------- /src/values.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'drizzle-orm'; 2 | 3 | /** 4 | * SQL template true value. 5 | */ 6 | export const $true = sql`'true'`; 7 | 8 | /** 9 | * SQL template false value. 10 | */ 11 | export const $false = sql`'false'`; 12 | 13 | /** 14 | * SQL template boolean value. 15 | */ 16 | export function $boolean(value: T) { 17 | return sql`${value ? 'true' : 'false'}`; 18 | } 19 | 20 | /** 21 | * SQL template null value. 22 | */ 23 | export const $null = sql`null`; 24 | 25 | /** 26 | * @example 27 | * 28 | * ```sql 29 | * current_timestamp(); 30 | * ``` 31 | */ 32 | export const $currentTimestamp = sql`current_timestamp`; 33 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowUnreachableCode": false, 4 | "alwaysStrict": true, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noImplicitAny": true, 10 | "noImplicitThis": true, 11 | "skipLibCheck": true, 12 | "strict": true, 13 | "strictBindCallApply": true, 14 | "strictFunctionTypes": true, 15 | "strictNullChecks": true, 16 | "strictPropertyInitialization": true, 17 | "target": "ESNext", 18 | "useUnknownInCatchVariables": true, 19 | "verbatimModuleSyntax": true, 20 | "checkJs": true 21 | }, 22 | "exclude": ["dist"] 23 | } 24 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['./src/index.ts', './src/pg/index.ts', './src/mysql/index.ts', './src/sqlite/index.ts'], 5 | format: ['cjs', 'esm'], 6 | treeshake: true, 7 | outDir: 'dist', 8 | dts: true, 9 | sourcemap: true, 10 | clean: true, 11 | bundle: true, 12 | minify: true, 13 | skipNodeModulesBundle: true, 14 | target: 'esnext', 15 | }); 16 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": [ 4 | "./src/index.ts", 5 | "./src/pg/index.ts", 6 | "./src/mysql/index.ts", 7 | "./src/sqlite/index.ts" 8 | ], 9 | "out": "documentation", 10 | "name": "Drizzle ORM Helpers documentation", 11 | "disableSources": true, 12 | "basePath": ".", 13 | "cleanOutputDir": true, 14 | "hideBreadcrumbs": true, 15 | "publicPath": ".", 16 | "useHTMLAnchors": true, 17 | "readme": "none", 18 | "githubPages": false, 19 | "excludeGroups": false, 20 | "hidePageHeader": true, 21 | "entryFileName": "README", 22 | "entryModule": "src", 23 | "useCodeBlocks": true, 24 | "outputFileStrategy": "modules", 25 | "expandObjects": false, 26 | "expandParameters": true, 27 | "parametersFormat": "table", 28 | "propertiesFormat": "table", 29 | "enumMembersFormat": "table", 30 | "typeDeclarationFormat": "table", 31 | "indexFormat": "table", 32 | "plugin": ["typedoc-plugin-markdown", "typedoc-plugin-remark"], 33 | "remarkPlugins": [ 34 | "unified-prettier", 35 | [ 36 | "remark-github", 37 | { 38 | "repository": "https://github.com/iolyd/drizzle-orm-helpers" 39 | } 40 | ], 41 | [ 42 | "remark-toc", 43 | { 44 | "heading": "Table of Contents", 45 | "maxDepth": 3 46 | } 47 | ] 48 | ] 49 | } 50 | --------------------------------------------------------------------------------