├── clippy.toml ├── .nvmrc ├── book ├── static │ ├── .nojekyll │ └── img │ │ ├── logo.png │ │ ├── favicon.ico │ │ ├── docusaurus.png │ │ └── sqlx-ts-logo.png ├── docs │ ├── cli │ │ └── _category_.json │ ├── connect │ │ ├── _category_.json │ │ ├── sqlxignore.md │ │ ├── README.md │ │ └── environment-variables.md │ ├── type-generation │ │ ├── _category_.json │ │ └── delete.md │ ├── installation.md │ ├── troubleshooting.md │ └── limitations.md ├── tsconfig.json ├── .gitignore ├── README.md ├── sidebars.ts ├── src │ └── css │ │ └── custom.css └── package.json ├── node ├── .eslintignore ├── src │ ├── index.ts │ └── index.spec.ts ├── jest.config.js ├── tsconfig.json ├── .eslintrc.js └── package.json ├── tests ├── configs │ ├── .sqlxrc.empty.json │ ├── .sqlxrc.camelcase3.json │ ├── .sqlxrc.camelcase2.json │ ├── .sqlxrc.column_camel.json │ ├── .sqlxrc.camelcase1.json │ ├── .sqlxrc.column_pascal.json │ ├── .sqlxrc.sample.json │ ├── .sqlxrc.enabled.json │ ├── .sqlxrc.not_enabled.json │ └── .sqlxrc.column_pascal_override.json ├── demo │ ├── select │ │ ├── nullability.ts │ │ ├── date-functions.ts │ │ ├── boolean-functions.ts │ │ ├── date-functions.queries.ts │ │ ├── date-functions.snapshot.ts │ │ ├── boolean-functions.queries.ts │ │ ├── boolean-functions.snapshot.ts │ │ ├── number-functions.ts │ │ ├── number-functions.queries.ts │ │ └── number-functions.snapshot.ts │ ├── typescript │ │ ├── statement │ │ │ ├── block.ts │ │ │ ├── with.ts │ │ │ ├── try.queries.ts │ │ │ ├── try.snapshot.ts │ │ │ ├── try.ts │ │ │ ├── with.queries.ts │ │ │ ├── function.ts │ │ │ ├── switch.ts │ │ │ ├── with.snapshot.ts │ │ │ ├── if.ts │ │ │ ├── while.ts │ │ │ ├── using.ts │ │ │ ├── for.ts │ │ │ ├── using.queries.ts │ │ │ ├── using.snapshot.ts │ │ │ ├── switch.queries.ts │ │ │ ├── switch.snapshot.ts │ │ │ ├── while.queries.ts │ │ │ ├── while.snapshot.ts │ │ │ ├── if.queries.ts │ │ │ ├── if.snapshot.ts │ │ │ ├── function.queries.ts │ │ │ ├── function.snapshot.ts │ │ │ ├── for.queries.ts │ │ │ └── for.snapshot.ts │ │ ├── weird.name.ts │ │ ├── skip-string.ts │ │ ├── expression │ │ │ ├── array.ts │ │ │ ├── scope.ts │ │ │ ├── yield.ts │ │ │ ├── nullish-coalescing.ts │ │ │ ├── call.ts │ │ │ ├── conditional.ts │ │ │ ├── new.queries.ts │ │ │ ├── new.snapshot.ts │ │ │ ├── types.queries.ts │ │ │ ├── array.queries.ts │ │ │ ├── call.queries.ts │ │ │ ├── super.queries.ts │ │ │ ├── yield.queries.ts │ │ │ ├── call.snapshot.ts │ │ │ ├── types.snapshot.ts │ │ │ ├── array.snapshot.ts │ │ │ ├── super.snapshot.ts │ │ │ ├── yield.snapshot.ts │ │ │ ├── new.ts │ │ │ ├── object.ts │ │ │ ├── super.ts │ │ │ ├── logical.ts │ │ │ ├── scope.queries.ts │ │ │ ├── scope.snapshot.ts │ │ │ ├── conditional.queries.ts │ │ │ ├── conditional.snapshot.ts │ │ │ ├── nullish-coalescing.queries.ts │ │ │ ├── nullish-coalescing.snapshot.ts │ │ │ ├── await.ts │ │ │ ├── chain.queries.ts │ │ │ ├── chain.snapshot.ts │ │ │ ├── arrow-function.ts │ │ │ ├── chain.ts │ │ │ ├── as_const.ts │ │ │ ├── types.ts │ │ │ ├── logical.queries.ts │ │ │ ├── logical.snapshot.ts │ │ │ ├── object.queries.ts │ │ │ ├── object.snapshot.ts │ │ │ ├── arrow-function.queries.ts │ │ │ ├── arrow-function.snapshot.ts │ │ │ ├── await.queries.ts │ │ │ ├── await.snapshot.ts │ │ │ ├── binary-operations.ts │ │ │ ├── as_const.queries.ts │ │ │ └── as_const.snapshot.ts │ │ ├── weird.name.queries.ts │ │ ├── weird.snapshot.ts │ │ └── demo.ts │ ├── sql_files │ │ ├── basic_select.sql │ │ ├── insert_query.sql │ │ ├── select_with_params.sql │ │ ├── update_delete.sql │ │ ├── insert_query.queries.ts │ │ ├── basic_select.queries.ts │ │ ├── insert_query.snapshot.ts │ │ ├── basic_select.snapshot.ts │ │ ├── select_with_params.queries.ts │ │ ├── select_with_params.snapshot.ts │ │ ├── update_delete.queries.ts │ │ └── update_delete.snapshot.ts │ ├── ignore │ │ └── test.hello.ts │ ├── delete │ │ ├── delete.ts │ │ ├── delete.queries.ts │ │ ├── delete.snapshot.ts │ │ ├── delete_returning.ts │ │ ├── delete_returning.queries.ts │ │ └── delete_returning.snapshot.ts │ ├── file_extensions │ │ ├── queries-mjs.mjs │ │ ├── queries-mts.mts │ │ ├── queries-cts.cts │ │ ├── queries-cjs.cjs │ │ ├── queries-js.js │ │ ├── queries-js.queries.ts │ │ ├── queries-js.snapshot.ts │ │ ├── queries-cjs.queries.ts │ │ ├── queries-cts.queries.ts │ │ ├── queries-mjs.queries.ts │ │ ├── queries-mts.queries.ts │ │ ├── queries-cjs.snapshot.ts │ │ ├── queries-cts.snapshot.ts │ │ ├── queries-mjs.snapshot.ts │ │ └── queries-mts.snapshot.ts │ ├── update │ │ ├── update.ts │ │ ├── update.queries.ts │ │ ├── update.snapshot.ts │ │ ├── update_returning.ts │ │ ├── update_returning.queries.ts │ │ └── update_returning.snapshot.ts │ ├── join │ │ ├── cross_join.ts │ │ ├── right_join.ts │ │ ├── full_outer_join.ts │ │ ├── cross_join.queries.ts │ │ ├── cross_join.snapshot.ts │ │ ├── right_join.queries.ts │ │ ├── right_join.snapshot.ts │ │ ├── full_outer_join.queries.ts │ │ ├── full_outer_join.snapshot.ts │ │ ├── left_join.ts │ │ ├── multiple_joins.ts │ │ ├── multiple_joins.queries.ts │ │ ├── multiple_joins.snapshot.ts │ │ ├── left_join.queries.ts │ │ └── left_join.snapshot.ts │ ├── alias │ │ └── alias.ts │ ├── case_expressions │ │ ├── nested_case.queries.ts │ │ ├── nested_case.snapshot.ts │ │ ├── simple_case.queries.ts │ │ ├── nested_case.ts │ │ ├── simple_case.snapshot.ts │ │ ├── searched_case.queries.ts │ │ ├── searched_case.snapshot.ts │ │ ├── searched_case.ts │ │ ├── simple_case.ts │ │ ├── case_in_clauses.queries.ts │ │ ├── case_in_clauses.snapshot.ts │ │ └── case_in_clauses.ts │ ├── postgres │ │ ├── jsonb_operations.ts │ │ ├── array_operations.ts │ │ ├── jsonb_operations.queries.ts │ │ ├── jsonb_operations.snapshot.ts │ │ ├── upsert.ts │ │ ├── array_operations.queries.ts │ │ ├── array_operations.snapshot.ts │ │ ├── upsert.queries.ts │ │ └── upsert.snapshot.ts │ ├── insert │ │ └── returning.ts │ ├── string_functions │ │ ├── pattern_matching.ts │ │ ├── basic_string_functions.ts │ │ ├── pattern_matching.queries.ts │ │ └── pattern_matching.snapshot.ts │ ├── null_handling │ │ ├── coalesce.ts │ │ ├── nullif_and_is_null.ts │ │ ├── coalesce.queries.ts │ │ └── coalesce.snapshot.ts │ ├── window │ │ ├── row_number.ts │ │ ├── rank_functions.ts │ │ ├── partition_by.ts │ │ ├── row_number.queries.ts │ │ ├── row_number.snapshot.ts │ │ ├── partition_by.queries.ts │ │ └── partition_by.snapshot.ts │ ├── clauses │ │ ├── having.ts │ │ ├── distinct.ts │ │ ├── having.queries.ts │ │ ├── having.snapshot.ts │ │ ├── limit_offset.ts │ │ ├── order_by.ts │ │ └── group_by.ts │ ├── annotations │ │ └── annotations.ts │ ├── complex_expressions │ │ ├── type_casting.ts │ │ ├── type_casting.queries.ts │ │ ├── mathematical_operations.ts │ │ ├── type_casting.snapshot.ts │ │ └── boolean_logic.ts │ ├── datetime_functions │ │ ├── time_functions.ts │ │ ├── time_functions.queries.ts │ │ └── time_functions.snapshot.ts │ └── aggregate_functions │ │ ├── conditional_aggregates.ts │ │ ├── conditional_aggregates.queries.ts │ │ ├── conditional_aggregates.snapshot.ts │ │ └── basic_aggregates.ts ├── sample │ ├── some-query.sql │ ├── sample.ts │ └── sample.queries.ts ├── postgres_update_query_parameters.rs ├── postgres_query_parameters.rs └── generate_path.rs ├── src ├── ts_generator │ ├── types │ │ ├── db_conn.rs │ │ └── mod.rs │ ├── mod.rs │ └── sql_parser │ │ ├── mod.rs │ │ ├── expressions │ │ └── mod.rs │ │ └── translate_delete.rs ├── core │ ├── mysql │ │ └── mod.rs │ ├── postgres │ │ └── mod.rs │ └── mod.rs ├── lib.rs ├── common │ ├── errors.rs │ └── mod.rs └── parser │ ├── mod.rs │ └── import.rs ├── .sqlxignore ├── release.toml ├── samples ├── wildcard │ ├── index.ts │ └── index.queries.ts ├── demo │ ├── index.postgres.xtsx │ ├── package.json │ └── index.queries.ts └── multiple-db-connections │ ├── package.json │ └── multiple-db-connections.ts ├── rust-toolchain.toml ├── rustfmt.toml ├── .gitignore ├── ci ├── Dockerfile.ubuntu └── ubuntu-install-packages ├── test-utils ├── Cargo.toml └── src │ └── lib.rs ├── .sqlxrc.sample.json ├── docker-compose.yml ├── SECURITY.md ├── .github └── workflows │ ├── auto-merge-dependabot.yaml │ ├── deploy-gh-pages.yaml │ ├── node.yaml │ └── coverage.yaml ├── LICENSE └── Cargo.toml /clippy.toml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v22.14.0 2 | -------------------------------------------------------------------------------- /book/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /node/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.empty.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/demo/select/nullability.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ts_generator/types/db_conn.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/block.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.sqlxignore: -------------------------------------------------------------------------------- 1 | *.queries.ts 2 | *.snapshot.ts 3 | *.hello.ts 4 | -------------------------------------------------------------------------------- /src/core/mysql/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod pool; 2 | pub mod prepare; 3 | -------------------------------------------------------------------------------- /src/core/postgres/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod pool; 2 | pub mod prepare; 3 | -------------------------------------------------------------------------------- /tests/sample/some-query.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO items (name) VALUES ($1) 2 | -------------------------------------------------------------------------------- /src/ts_generator/types/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod db_conn; 2 | pub mod ts_query; 3 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | pub mod core; 3 | pub mod parser; 4 | pub mod ts_generator; 5 | -------------------------------------------------------------------------------- /book/docs/cli/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Command Line Interface", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /book/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonShin/sqlx-ts/HEAD/book/static/img/logo.png -------------------------------------------------------------------------------- /src/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod connection; 2 | pub mod execute; 3 | pub mod mysql; 4 | pub mod postgres; 5 | -------------------------------------------------------------------------------- /book/docs/connect/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Connecting to databases", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /book/docs/type-generation/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Type generation", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /book/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonShin/sqlx-ts/HEAD/book/static/img/favicon.ico -------------------------------------------------------------------------------- /tests/demo/sql_files/basic_select.sql: -------------------------------------------------------------------------------- 1 | -- @name: basic select 2 | SELECT id, name, rarity FROM items; 3 | -------------------------------------------------------------------------------- /book/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonShin/sqlx-ts/HEAD/book/static/img/docusaurus.png -------------------------------------------------------------------------------- /book/static/img/sqlx-ts-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonShin/sqlx-ts/HEAD/book/static/img/sqlx-ts-logo.png -------------------------------------------------------------------------------- /node/src/index.ts: -------------------------------------------------------------------------------- 1 | export function sql(query: T): string { 2 | return query[0]; 3 | } 4 | -------------------------------------------------------------------------------- /tests/demo/typescript/weird.name.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const weirdName = sql`SELECT id FROM items` 4 | -------------------------------------------------------------------------------- /tests/demo/sql_files/insert_query.sql: -------------------------------------------------------------------------------- 1 | -- @name: insert query 2 | INSERT INTO items (name, rarity) VALUES ($1, $2) RETURNING id, name; 3 | -------------------------------------------------------------------------------- /tests/demo/sql_files/select_with_params.sql: -------------------------------------------------------------------------------- 1 | -- @name: select with params 2 | SELECT id, name, rarity FROM items WHERE rarity = $1; 3 | -------------------------------------------------------------------------------- /release.toml: -------------------------------------------------------------------------------- 1 | pre-release-replacements = [ 2 | {file="Cargo.toml", search="version = \"0.0.0\"", replace="version = \"{{tag_name}}\""} 3 | ] -------------------------------------------------------------------------------- /tests/demo/typescript/skip-string.ts: -------------------------------------------------------------------------------- 1 | 2 | const shouldSkip = `skip` 3 | 4 | const shouldSkip2 = 'skip' 5 | 6 | const shouldSkip3 = "skip" 7 | -------------------------------------------------------------------------------- /src/ts_generator/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod annotations; 2 | pub mod errors; 3 | pub mod generator; 4 | pub mod information_schema; 5 | pub mod sql_parser; 6 | pub mod types; 7 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/array.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const arraySql = [sql` 4 | -- @name: arrayQuery 5 | SELECT id FROM items 6 | `] 7 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/with.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | with ([1, 2, 3]) { 4 | const withSql = sql`SELECT id FROM items WHERE $1;` 5 | } 6 | -------------------------------------------------------------------------------- /node/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: "ts-jest", 4 | testEnvironment: "node", 5 | }; 6 | -------------------------------------------------------------------------------- /samples/wildcard/index.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const wildcardQuery = sql` 4 | SELECT * 5 | FROM items 6 | JOIN tables ON tables.id = items.table_id; 7 | ` 8 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/scope.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | ( 4 | sql` 5 | -- @name: testParenthesisQuery 6 | SELECT * FROM items 7 | ` 8 | ) 9 | -------------------------------------------------------------------------------- /tests/demo/ignore/test.hello.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const sql1 = sql` 4 | -- @name: test ignore query 5 | -- @db: db_mysql 6 | SELECT * 7 | FROM items; 8 | ` 9 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/yield.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | function *gen() { 4 | yield sql` 5 | -- @name: yield query 6 | SELECT id FROM items; 7 | ` 8 | } -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | component = ["rustfmt@1.4.38", "rustc@1.79.0"] 4 | target = ["aarch64-unknown-linux-gnu", "i686-pc-windows-gnu", "x86_64-apple-darwin"] 5 | -------------------------------------------------------------------------------- /tests/demo/sql_files/update_delete.sql: -------------------------------------------------------------------------------- 1 | -- @name: update query 2 | UPDATE items SET name = $1 WHERE id = $2 RETURNING id, name; 3 | 4 | -- @name: delete query 5 | DELETE FROM items WHERE id = $1 RETURNING id; 6 | -------------------------------------------------------------------------------- /src/ts_generator/sql_parser/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod expressions; 2 | pub mod quoted_strings; 3 | pub mod translate_delete; 4 | pub mod translate_insert; 5 | pub mod translate_query; 6 | pub mod translate_stmt; 7 | pub mod translate_update; 8 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/nullish-coalescing.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const something = false 4 | const somethingElse = something ?? sql` 5 | -- @name: testNullishCoalescingQuery 6 | SELECT * FROM items 7 | ` 8 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/call.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | function tester(someSql: string) { 4 | return "Hello World"; 5 | } 6 | 7 | tester(sql` 8 | -- @name: caller test 9 | SELECT id FROM items WHERE id = 1 10 | `) 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/conditional.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // @ts-ignore 4 | testData = true === 1 ? sql` 5 | -- @name: truthy 6 | SELECT id FROM items 7 | ` : sql` 8 | -- @name: falsy 9 | SELECT id FROM items 10 | ` 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/try.queries.ts: -------------------------------------------------------------------------------- 1 | export type Try2Params = []; 2 | 3 | export interface ITry2Result { 4 | someNumber: number; 5 | } 6 | 7 | export interface ITry2Query { 8 | params: Try2Params; 9 | result: ITry2Result; 10 | } 11 | -------------------------------------------------------------------------------- /node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/**/*.ts"], 3 | "exclude": ["src/**/*.spec.ts"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "declaration": true, 7 | "strict": true, 8 | "esModuleInterop": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /book/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | }, 7 | "exclude": [".docusaurus", "build"] 8 | } 9 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/try.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type Try2Params = []; 2 | 3 | export interface ITry2Result { 4 | someNumber: number; 5 | } 6 | 7 | export interface ITry2Query { 8 | params: Try2Params; 9 | result: ITry2Result; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/try.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | try { 4 | // const try1 = sql`SELECT id FROM items` 5 | const try2 = sql`SELECT 1 as some_number FROM items` 6 | } catch { 7 | throw new Error('This should never happen') 8 | } -------------------------------------------------------------------------------- /tests/demo/typescript/expression/new.queries.ts: -------------------------------------------------------------------------------- 1 | export type NewClassParams = []; 2 | 3 | export interface INewClassResult { 4 | id: number; 5 | } 6 | 7 | export interface INewClassQuery { 8 | params: NewClassParams; 9 | result: INewClassResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/with.queries.ts: -------------------------------------------------------------------------------- 1 | export type WithSqlParams = [boolean]; 2 | 3 | export interface IWithSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IWithSqlQuery { 8 | params: WithSqlParams; 9 | result: IWithSqlResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/weird.name.queries.ts: -------------------------------------------------------------------------------- 1 | export type WeirdNameParams = []; 2 | 3 | export interface IWeirdNameResult { 4 | id: number; 5 | } 6 | 7 | export interface IWeirdNameQuery { 8 | params: WeirdNameParams; 9 | result: IWeirdNameResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/weird.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type WeirdNameParams = []; 2 | 3 | export interface IWeirdNameResult { 4 | id: number; 5 | } 6 | 7 | export interface IWeirdNameQuery { 8 | params: WeirdNameParams; 9 | result: IWeirdNameResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/new.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type NewClassParams = []; 2 | 3 | export interface INewClassResult { 4 | id: number; 5 | } 6 | 7 | export interface INewClassQuery { 8 | params: NewClassParams; 9 | result: INewClassResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/types.queries.ts: -------------------------------------------------------------------------------- 1 | export type ModuleSqlParams = []; 2 | 3 | export interface IModuleSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IModuleSqlQuery { 8 | params: ModuleSqlParams; 9 | result: IModuleSqlResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/function.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | function test() { 4 | const functionAssign = sql`SELECT id FROM items` 5 | 6 | return sql` 7 | -- @name: return query 8 | SELECT id FROM items 9 | `; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/switch.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | 4 | switch (true) { 5 | case true: 6 | const case1 = sql`SELECT id FROM items`; 7 | break; 8 | default: 9 | const case2 = sql`SELECT id FROM items`; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/array.queries.ts: -------------------------------------------------------------------------------- 1 | export type ArrayQueryParams = []; 2 | 3 | export interface IArrayQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface IArrayQueryQuery { 8 | params: ArrayQueryParams; 9 | result: IArrayQueryResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/call.queries.ts: -------------------------------------------------------------------------------- 1 | export type CallerTestParams = []; 2 | 3 | export interface ICallerTestResult { 4 | id: number; 5 | } 6 | 7 | export interface ICallerTestQuery { 8 | params: CallerTestParams; 9 | result: ICallerTestResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/super.queries.ts: -------------------------------------------------------------------------------- 1 | export type SuperQueryParams = []; 2 | 3 | export interface ISuperQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface ISuperQueryQuery { 8 | params: SuperQueryParams; 9 | result: ISuperQueryResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/yield.queries.ts: -------------------------------------------------------------------------------- 1 | export type YieldQueryParams = []; 2 | 3 | export interface IYieldQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface IYieldQueryQuery { 8 | params: YieldQueryParams; 9 | result: IYieldQueryResult; 10 | } 11 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/with.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type WithSqlParams = [boolean]; 2 | 3 | export interface IWithSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IWithSqlQuery { 8 | params: WithSqlParams; 9 | result: IWithSqlResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/call.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CallerTestParams = []; 2 | 3 | export interface ICallerTestResult { 4 | id: number; 5 | } 6 | 7 | export interface ICallerTestQuery { 8 | params: CallerTestParams; 9 | result: ICallerTestResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/types.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type ModuleSqlParams = []; 2 | 3 | export interface IModuleSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IModuleSqlQuery { 8 | params: ModuleSqlParams; 9 | result: IModuleSqlResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/array.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type ArrayQueryParams = []; 2 | 3 | export interface IArrayQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface IArrayQueryQuery { 8 | params: ArrayQueryParams; 9 | result: IArrayQueryResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/super.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type SuperQueryParams = []; 2 | 3 | export interface ISuperQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface ISuperQueryQuery { 8 | params: SuperQueryParams; 9 | result: ISuperQueryResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/yield.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type YieldQueryParams = []; 2 | 3 | export interface IYieldQueryResult { 4 | id: number; 5 | } 6 | 7 | export interface IYieldQueryQuery { 8 | params: YieldQueryParams; 9 | result: IYieldQueryResult; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/if.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | if (true) { 4 | const ifstmt = sql`SELECT id FROM items;`; 5 | } 6 | 7 | function testIfStatement() { 8 | if (true) { 9 | const nestedIfStmt = sql`SELECT id FROM items;`; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/while.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | while (true) { 4 | const whileSql = sql`SELECT id FROM items WHERE $1;` 5 | } 6 | 7 | let i = 0 8 | 9 | do { 10 | const query = sql`SELECT id FROM items`; 11 | i++; 12 | } while (i < 5); 13 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/new.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | class NewClass { 4 | constructor(theQuery: string) { 5 | console.log(theQuery) 6 | } 7 | } 8 | 9 | const testInstance = new NewClass(sql` 10 | -- @name: new class 11 | SELECT id FROM items 12 | `) 13 | -------------------------------------------------------------------------------- /tests/demo/sql_files/insert_query.queries.ts: -------------------------------------------------------------------------------- 1 | export type InsertQueryParams = [string, string | null]; 2 | 3 | export interface IInsertQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IInsertQueryQuery { 9 | params: InsertQueryParams; 10 | result: IInsertQueryResult; 11 | } 12 | -------------------------------------------------------------------------------- /samples/demo/index.postgres.xtsx: -------------------------------------------------------------------------------- 1 | import { sql } from "sqlx-ts"; 2 | 3 | const testQuery2 = sql` 4 | -- @name: some query 2 5 | -- @db: default 6 | SELECT 7 | id, 8 | EXISTS(SELECT 1 FROM items WHERE points > 0) AS test_name 9 | FROM items 10 | WHERE id = $1 11 | AND points > $2 12 | AND points < $3; 13 | ` 14 | -------------------------------------------------------------------------------- /tests/demo/delete/delete.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const deleteSql1 = sql` 4 | DELETE FROM items 5 | WHERE id = $1 6 | ` 7 | const deleteSql2 = sql` 8 | DELETE FROM "items" 9 | WHERE "id" = $1 10 | ` 11 | 12 | const deleteSql3 = sql` 13 | DELETE FROM "items" 14 | WHERE "id" = $1 AND name = $2 15 | ` 16 | -------------------------------------------------------------------------------- /tests/demo/sql_files/basic_select.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicSelectParams = []; 2 | 3 | export interface IBasicSelectResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface IBasicSelectQuery { 10 | params: BasicSelectParams; 11 | result: IBasicSelectResult; 12 | } 13 | -------------------------------------------------------------------------------- /tests/demo/sql_files/insert_query.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type InsertQueryParams = [string, string | null]; 2 | 3 | export interface IInsertQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IInsertQueryQuery { 9 | params: InsertQueryParams; 10 | result: IInsertQueryResult; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/object.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const obj = { 4 | a: sql` 5 | -- @name: anotherTestObjectQuery 6 | SELECT * FROM items 7 | `, 8 | b: { 9 | c: sql` 10 | -- @name: nestedTestObjectQuery 11 | SELECT * FROM items 12 | ` 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/using.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const getResource = () => ({ 4 | [Symbol.asyncDispose]: async () => { 5 | const testAsyncUsing = sql` 6 | SELECT * FROM items; 7 | ` 8 | }, 9 | }); 10 | 11 | { 12 | await using resource = getResource(); 13 | } 14 | -------------------------------------------------------------------------------- /tests/demo/sql_files/basic_select.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicSelectParams = []; 2 | 3 | export interface IBasicSelectResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface IBasicSelectQuery { 10 | params: BasicSelectParams; 11 | result: IBasicSelectResult; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /book/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/for.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | for (;true;) { 4 | const for1 = sql`SELECT id FROM items` 5 | } 6 | 7 | const stuff = [] 8 | 9 | for (const item of stuff) { 10 | const for2 = sql`SELECT id FROM items` 11 | } 12 | 13 | for (const item in stuff) { 14 | const for3 = sql`SELECT id FROM items` 15 | } -------------------------------------------------------------------------------- /tests/demo/sql_files/select_with_params.queries.ts: -------------------------------------------------------------------------------- 1 | export type SelectWithParamsParams = [string | null]; 2 | 3 | export interface ISelectWithParamsResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ISelectWithParamsQuery { 10 | params: SelectWithParamsParams; 11 | result: ISelectWithParamsResult; 12 | } 13 | -------------------------------------------------------------------------------- /tests/demo/sql_files/select_with_params.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type SelectWithParamsParams = [string | null]; 2 | 3 | export interface ISelectWithParamsResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ISelectWithParamsQuery { 10 | params: SelectWithParamsParams; 11 | result: ISelectWithParamsResult; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /samples/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "sequelize": "^6.31.0", 11 | "sqlx-ts": "file:../../node" 12 | }, 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /samples/multiple-db-connections/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multiple-db-connections", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "sqlx-ts": "file:../../node" 11 | }, 12 | "author": "", 13 | "license": "ISC" 14 | } 15 | -------------------------------------------------------------------------------- /samples/multiple-db-connections/multiple-db-connections.ts: -------------------------------------------------------------------------------- 1 | import { sql } from "sqlx-ts"; 2 | 3 | // It should always fallback to default 4 | const nonameDB = sql`SELECT * FROM items;`; 5 | 6 | const defaultDb = sql` 7 | /* db: default */ 8 | SELECT * FROM items; 9 | `; 10 | 11 | const postgresDb = sql` 12 | /* db: db_mysql */ 13 | SELECT * FROM itemz; 14 | `; 15 | -------------------------------------------------------------------------------- /samples/demo/index.queries.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export type TestQueryParams = []; 4 | 5 | 6 | export interface ITestQueryResult { 7 | food_type: string; 8 | id: number; 9 | points: number; 10 | table_id: number; 11 | time_takes_to_cook: number; 12 | }; 13 | 14 | 15 | export interface ITestQueryQuery { 16 | params: TestQueryParams; 17 | result: ITestQueryResult; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/super.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | class SuperClass { 4 | constructor(sqlTest: string) { 5 | console.log(sqlTest); 6 | } 7 | } 8 | 9 | class ChildClass extends SuperClass { 10 | constructor() { 11 | super(sql` 12 | -- @name: super query 13 | SELECT id FROM items 14 | `); 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/ts_generator/sql_parser/expressions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod functions; 2 | pub mod translate_data_type; 3 | pub mod translate_expr; 4 | pub mod translate_table_with_joins; 5 | pub mod translate_wildcard_expr; 6 | 7 | #[cfg(test)] 8 | #[path = "./functions.test.rs"] 9 | mod functions_test; 10 | #[cfg(test)] 11 | #[path = "./translate_table_with_joins.test.rs"] 12 | mod translate_table_with_joins_test; 13 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mjs.mjs: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // .mjs file extension test (ES Module JavaScript) 4 | const mjsQuery = sql` 5 | -- @name: mjs query 6 | SELECT id, name FROM items WHERE rarity = $1 7 | ` 8 | 9 | export const mjsFunction = () => { 10 | return sql` 11 | -- @name: mjs function query 12 | SELECT id, name FROM items WHERE id = $1 13 | ` 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mts.mts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // .mts file extension test (ES Module TypeScript) 4 | const mtsQuery = sql` 5 | -- @name: mts query 6 | SELECT id, name FROM items WHERE rarity = $1 7 | ` 8 | 9 | export const mtsFunction = () => { 10 | return sql` 11 | -- @name: mts function query 12 | SELECT id, name FROM items WHERE id = $1 13 | ` 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/update/update.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const updateQuery = sql` 4 | UPDATE items 5 | SET name = $1, rarity = $2 6 | WHERE id = $3 7 | ` 8 | 9 | const quotedUpdateQuery = sql` 10 | UPDATE "items" 11 | SET "name" = $1, "rarity" = $2 12 | WHERE "id" = $3 13 | ` 14 | 15 | const nullableFieldUpdate = sql` 16 | UPDATE "items" 17 | SET rarity = $1 18 | WHERE "id" = $2 19 | ` 20 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/using.queries.ts: -------------------------------------------------------------------------------- 1 | export type TestAsyncUsingParams = []; 2 | 3 | export interface ITestAsyncUsingResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestAsyncUsingQuery { 12 | params: TestAsyncUsingParams; 13 | result: ITestAsyncUsingResult; 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/using.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type TestAsyncUsingParams = []; 2 | 3 | export interface ITestAsyncUsingResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestAsyncUsingQuery { 12 | params: TestAsyncUsingParams; 13 | result: ITestAsyncUsingResult; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /book/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Installation 6 | 7 | With npm: 8 | 9 | ```bash 10 | $ npm install --save-dev sqlx-ts 11 | ``` 12 | 13 | With yarn: 14 | 15 | ```bash 16 | $ yarn add --dev sqlx-ts 17 | ``` 18 | 19 | Verify the installation of `sqlx-ts` binary by running 20 | 21 | ```bash 22 | $ npx sqlx-ts --version 23 | ``` 24 | 25 | 🚀 you now have `sqlx-ts` installed 🚀 -------------------------------------------------------------------------------- /tests/demo/typescript/expression/logical.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const testData = true 4 | 5 | const test1 = testData ?? sql` 6 | -- @name: nullish coalescing 7 | SELECT id FROM items 8 | ` 9 | 10 | const test2 = testData || sql` 11 | -- @name: pipePipe 12 | SELECT id FROM items 13 | ` 14 | 15 | const test3 = testData && sql` 16 | -- @name: ampersand ampersand 17 | SELECT id FROM items 18 | ` 19 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | max_width = 120 3 | # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#chain_width 4 | chain_width = 70 5 | # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#match_arm_leading_pipes 6 | match_arm_leading_pipes = "Never" 7 | # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#merge_derives 8 | merge_derives = true 9 | tab_spaces = 2 10 | -------------------------------------------------------------------------------- /tests/sample/sample.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const sampleSelectQuery = sql` 4 | SELECT id as some_id, name FROM items WHERE id = $1 5 | ` 6 | 7 | const sampleInsertQuery = sql` 8 | INSERT INTO items (name) VALUES ($1) 9 | ` 10 | 11 | const sampleUpdateQuery = sql` 12 | UPDATE items SET name = $1 WHERE id = $2 13 | ` 14 | 15 | const sampleDeleteQuery = sql` 16 | DELETE FROM items WHERE id = $1 17 | ` 18 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cts.cts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // .cts file extension test (CommonJS TypeScript) 4 | const ctsQuery = sql` 5 | -- @name: cts query 6 | SELECT id, name FROM items WHERE rarity = $1 7 | ` 8 | 9 | module.exports = { 10 | ctsQuery, 11 | ctsFunction: () => { 12 | return sql` 13 | -- @name: cts function query 14 | SELECT id, name FROM items WHERE id = $1 15 | ` 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/scope.queries.ts: -------------------------------------------------------------------------------- 1 | export type TestParenthesisQueryParams = []; 2 | 3 | export interface ITestParenthesisQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestParenthesisQueryQuery { 12 | params: TestParenthesisQueryParams; 13 | result: ITestParenthesisQueryResult; 14 | } 15 | -------------------------------------------------------------------------------- /samples/wildcard/index.queries.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export type WildcardQueryParams = []; 4 | 5 | 6 | export interface IWildcardQueryResult { 7 | id: number; 8 | time_takes_to_cook: number; 9 | food_type: string; 10 | table_id: number; 11 | number: number; 12 | points: number | null; 13 | }; 14 | 15 | 16 | export interface IWildcardQueryQuery { 17 | params: WildcardQueryParams; 18 | result: IWildcardQueryResult; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cjs.cjs: -------------------------------------------------------------------------------- 1 | const { sql } = require('sqlx-ts') 2 | 3 | // .cjs file extension test (CommonJS JavaScript) 4 | const cjsQuery = sql` 5 | -- @name: cjs query 6 | SELECT id, name FROM items WHERE rarity = $1 7 | ` 8 | 9 | module.exports = { 10 | cjsQuery, 11 | cjsFunction: () => { 12 | return sql` 13 | -- @name: cjs function query 14 | SELECT id, name FROM items WHERE id = $1 15 | ` 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/scope.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type TestParenthesisQueryParams = []; 2 | 3 | export interface ITestParenthesisQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestParenthesisQueryQuery { 12 | params: TestParenthesisQueryParams; 13 | result: ITestParenthesisQueryResult; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-js.js: -------------------------------------------------------------------------------- 1 | const { sql } = require('sqlx-ts') 2 | 3 | // .js file extension test (JavaScript) 4 | const jsQuery = sql` 5 | -- @name: js query 6 | SELECT id, name FROM items WHERE rarity = $1 7 | ` 8 | 9 | const jsFunction = () => { 10 | return sql` 11 | -- @name: js function query 12 | SELECT id, name FROM items WHERE id = $1 13 | ` 14 | } 15 | 16 | module.exports = { 17 | jsQuery, 18 | jsFunction 19 | } 20 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/switch.queries.ts: -------------------------------------------------------------------------------- 1 | export type Case1Params = []; 2 | 3 | export interface ICase1Result { 4 | id: number; 5 | } 6 | 7 | export interface ICase1Query { 8 | params: Case1Params; 9 | result: ICase1Result; 10 | } 11 | 12 | export type Case2Params = []; 13 | 14 | export interface ICase2Result { 15 | id: number; 16 | } 17 | 18 | export interface ICase2Query { 19 | params: Case2Params; 20 | result: ICase2Result; 21 | } 22 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/switch.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type Case1Params = []; 2 | 3 | export interface ICase1Result { 4 | id: number; 5 | } 6 | 7 | export interface ICase1Query { 8 | params: Case1Params; 9 | result: ICase1Result; 10 | } 11 | 12 | export type Case2Params = []; 13 | 14 | export interface ICase2Result { 15 | id: number; 16 | } 17 | 18 | export interface ICase2Query { 19 | params: Case2Params; 20 | result: ICase2Result; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | /target 4 | 5 | # intellij 6 | .idea 7 | 8 | # scratch files 9 | **/*.scratch.rs 10 | 11 | .env 12 | .env.mysql 13 | 14 | # node/typescript 15 | dist 16 | node_modules 17 | node/README.md 18 | node/sqlx-ts 19 | 20 | 21 | # book 22 | _book/book 23 | book/.docusaurus 24 | 25 | # vscode 26 | .run 27 | .vscode 28 | 29 | # code coverage 30 | *.profraw 31 | coverage 32 | 33 | # staging area for testing TS files 34 | tests/staging 35 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/conditional.queries.ts: -------------------------------------------------------------------------------- 1 | export type TruthyParams = []; 2 | 3 | export interface ITruthyResult { 4 | id: number; 5 | } 6 | 7 | export interface ITruthyQuery { 8 | params: TruthyParams; 9 | result: ITruthyResult; 10 | } 11 | 12 | export type FalsyParams = []; 13 | 14 | export interface IFalsyResult { 15 | id: number; 16 | } 17 | 18 | export interface IFalsyQuery { 19 | params: FalsyParams; 20 | result: IFalsyResult; 21 | } 22 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/conditional.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type TruthyParams = []; 2 | 3 | export interface ITruthyResult { 4 | id: number; 5 | } 6 | 7 | export interface ITruthyQuery { 8 | params: TruthyParams; 9 | result: ITruthyResult; 10 | } 11 | 12 | export type FalsyParams = []; 13 | 14 | export interface IFalsyResult { 15 | id: number; 16 | } 17 | 18 | export interface IFalsyQuery { 19 | params: FalsyParams; 20 | result: IFalsyResult; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/nullish-coalescing.queries.ts: -------------------------------------------------------------------------------- 1 | export type TestNullishCoalescingQueryParams = []; 2 | 3 | export interface ITestNullishCoalescingQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestNullishCoalescingQueryQuery { 12 | params: TestNullishCoalescingQueryParams; 13 | result: ITestNullishCoalescingQueryResult; 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/while.queries.ts: -------------------------------------------------------------------------------- 1 | export type WhileSqlParams = [boolean]; 2 | 3 | export interface IWhileSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IWhileSqlQuery { 8 | params: WhileSqlParams; 9 | result: IWhileSqlResult; 10 | } 11 | 12 | export type QueryParams = []; 13 | 14 | export interface IQueryResult { 15 | id: number; 16 | } 17 | 18 | export interface IQueryQuery { 19 | params: QueryParams; 20 | result: IQueryResult; 21 | } 22 | -------------------------------------------------------------------------------- /tests/demo/select/date-functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const atTimeZone = sql` 4 | SELECT 5 | id, 6 | '2018-09-02 07:09:19'::timestamp AT TIME ZONE 'America/Chicago' as some_date 7 | FROM items; 8 | ` 9 | 10 | const cast = sql` 11 | SELECT 12 | id, 13 | CAST('2015-01-01' AS DATE) as DATE 14 | FROM items; 15 | ` 16 | 17 | const extract = sql` 18 | SELECT 19 | id, 20 | EXTRACT(MONTH FROM DATE '2017-08-08') AS THE_MONTH 21 | FROM items; 22 | ` 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/while.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type WhileSqlParams = [boolean]; 2 | 3 | export interface IWhileSqlResult { 4 | id: number; 5 | } 6 | 7 | export interface IWhileSqlQuery { 8 | params: WhileSqlParams; 9 | result: IWhileSqlResult; 10 | } 11 | 12 | export type QueryParams = []; 13 | 14 | export interface IQueryResult { 15 | id: number; 16 | } 17 | 18 | export interface IQueryQuery { 19 | params: QueryParams; 20 | result: IQueryResult; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/nullish-coalescing.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type TestNullishCoalescingQueryParams = []; 2 | 3 | export interface ITestNullishCoalescingQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface ITestNullishCoalescingQueryQuery { 12 | params: TestNullishCoalescingQueryParams; 13 | result: ITestNullishCoalescingQueryResult; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/if.queries.ts: -------------------------------------------------------------------------------- 1 | export type IfstmtParams = []; 2 | 3 | export interface IIfstmtResult { 4 | id: number; 5 | } 6 | 7 | export interface IIfstmtQuery { 8 | params: IfstmtParams; 9 | result: IIfstmtResult; 10 | } 11 | 12 | export type NestedIfStmtParams = []; 13 | 14 | export interface INestedIfStmtResult { 15 | id: number; 16 | } 17 | 18 | export interface INestedIfStmtQuery { 19 | params: NestedIfStmtParams; 20 | result: INestedIfStmtResult; 21 | } 22 | -------------------------------------------------------------------------------- /tests/demo/join/cross_join.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic CROSS JOIN 4 | const basicCrossJoin = sql` 5 | -- @name: basic cross join 6 | SELECT items.id, items.name, inventory.quantity 7 | FROM items 8 | CROSS JOIN inventory 9 | ` 10 | 11 | // CROSS JOIN with WHERE filter 12 | const crossJoinWithWhere = sql` 13 | -- @name: cross join with where 14 | SELECT items.id, items.name, inventory.quantity 15 | FROM items 16 | CROSS JOIN inventory 17 | WHERE items.rarity = $1 18 | ` 19 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/if.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type IfstmtParams = []; 2 | 3 | export interface IIfstmtResult { 4 | id: number; 5 | } 6 | 7 | export interface IIfstmtQuery { 8 | params: IfstmtParams; 9 | result: IIfstmtResult; 10 | } 11 | 12 | export type NestedIfStmtParams = []; 13 | 14 | export interface INestedIfStmtResult { 15 | id: number; 16 | } 17 | 18 | export interface INestedIfStmtQuery { 19 | params: NestedIfStmtParams; 20 | result: INestedIfStmtResult; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/demo/select/boolean-functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Exists 4 | const exists = sql` 5 | SELECT EXISTS(SELECT * FROM items WHERE id = $1) AS exists 6 | FROM items 7 | ` 8 | 9 | // Is True, Is False, Is Null, Is Not Null 10 | const isTrue = sql` 11 | SELECT ($1 IS TRUE) as is_true 12 | FROM items 13 | ` 14 | 15 | const isFalse = sql` 16 | SELECT ($1 IS FALSE) as is_false 17 | FROM items 18 | ` 19 | 20 | const inList = sql` 21 | SELECT 1 IN (1, 2, 3) as test 22 | FROM items 23 | ` 24 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/function.queries.ts: -------------------------------------------------------------------------------- 1 | export type FunctionAssignParams = []; 2 | 3 | export interface IFunctionAssignResult { 4 | id: number; 5 | } 6 | 7 | export interface IFunctionAssignQuery { 8 | params: FunctionAssignParams; 9 | result: IFunctionAssignResult; 10 | } 11 | 12 | export type ReturnQueryParams = []; 13 | 14 | export interface IReturnQueryResult { 15 | id: number; 16 | } 17 | 18 | export interface IReturnQueryQuery { 19 | params: ReturnQueryParams; 20 | result: IReturnQueryResult; 21 | } 22 | -------------------------------------------------------------------------------- /node/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": false, 4 | "node": true, 5 | "es2021": true, 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | ], 11 | "parser": "@typescript-eslint/parser", 12 | "parserOptions": { 13 | "ecmaVersion": "latest", 14 | "sourceType": "module", 15 | }, 16 | "plugins": [ 17 | "@typescript-eslint", 18 | ], 19 | "rules": { 20 | "@typescript-eslint/no-var-requires": "off" 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.camelcase3.json: -------------------------------------------------------------------------------- 1 | { 2 | "connections": { 3 | "default": { 4 | "DB_TYPE": "postgres", 5 | "DB_HOST": "127.0.0.1", 6 | "DB_PORT": 54321, 7 | "DB_USER": "postgres", 8 | "DB_PASS": "postgres", 9 | "DB_NAME": "postgres", 10 | "PG_SEARCH_PATH": "public,myschema" 11 | }, 12 | "db_mysql": { 13 | "DB_TYPE": "mysql", 14 | "DB_HOST": "127.0.0.1", 15 | "DB_PORT": 33306, 16 | "DB_USER": "root", 17 | "DB_NAME": "sqlx-ts" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /tests/demo/typescript/statement/function.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type FunctionAssignParams = []; 2 | 3 | export interface IFunctionAssignResult { 4 | id: number; 5 | } 6 | 7 | export interface IFunctionAssignQuery { 8 | params: FunctionAssignParams; 9 | result: IFunctionAssignResult; 10 | } 11 | 12 | export type ReturnQueryParams = []; 13 | 14 | export interface IReturnQueryResult { 15 | id: number; 16 | } 17 | 18 | export interface IReturnQueryQuery { 19 | params: ReturnQueryParams; 20 | result: IReturnQueryResult; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/demo/sql_files/update_delete.queries.ts: -------------------------------------------------------------------------------- 1 | export type UpdateQueryParams = [string, number]; 2 | 3 | export interface IUpdateQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IUpdateQueryQuery { 9 | params: UpdateQueryParams; 10 | result: IUpdateQueryResult; 11 | } 12 | 13 | export type DeleteQueryParams = [number]; 14 | 15 | export interface IDeleteQueryResult { 16 | id: number; 17 | } 18 | 19 | export interface IDeleteQueryQuery { 20 | params: DeleteQueryParams; 21 | result: IDeleteQueryResult; 22 | } 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/await.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | async function asyncFunction() { 4 | return await sql` 5 | -- @name: async plain function 6 | SELECT id FROM items; 7 | ` 8 | } 9 | 10 | const asyncLambdaAwaited = async () => await sql`SELECT id FROM items` 11 | 12 | const asyncLambda = async () => sql`SELECT id FROM items` 13 | 14 | (async function () { 15 | const iifFunction = sql`SELECT id FROM items;` 16 | })() 17 | 18 | (async () => sql` 19 | -- @name: iif lambda 20 | SELECT id FROM items; 21 | `)() 22 | -------------------------------------------------------------------------------- /src/common/errors.rs: -------------------------------------------------------------------------------- 1 | // Common error messages 2 | pub static DB_CONN_POOL_RETRIEVE_ERROR: &str = 3 | "Failed to retrieve a connection from the pool. Increase the pool size and try again"; 4 | pub static DB_SCHEME_READ_ERROR: &str = "Failed to read the database schema to retrieve details. Please raise the issue on https://github.com/JasonShin/sqlx-ts/issues"; 5 | pub static DB_CONN_FROM_LOCAL_CACHE_ERROR: &str = "Failed to retrieve a connection from local cache, check the database name annotated in your query and connections config in your configuration file"; 6 | -------------------------------------------------------------------------------- /tests/demo/sql_files/update_delete.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type UpdateQueryParams = [string, number]; 2 | 3 | export interface IUpdateQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IUpdateQueryQuery { 9 | params: UpdateQueryParams; 10 | result: IUpdateQueryResult; 11 | } 12 | 13 | export type DeleteQueryParams = [number]; 14 | 15 | export interface IDeleteQueryResult { 16 | id: number; 17 | } 18 | 19 | export interface IDeleteQueryQuery { 20 | params: DeleteQueryParams; 21 | result: IDeleteQueryResult; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/chain.queries.ts: -------------------------------------------------------------------------------- 1 | export type ParentChildParams = []; 2 | 3 | export interface IParentChildResult { 4 | id: number; 5 | } 6 | 7 | export interface IParentChildQuery { 8 | params: ParentChildParams; 9 | result: IParentChildResult; 10 | } 11 | 12 | export type OptionalParentChildParams = []; 13 | 14 | export interface IOptionalParentChildResult { 15 | id: number; 16 | } 17 | 18 | export interface IOptionalParentChildQuery { 19 | params: OptionalParentChildParams; 20 | result: IOptionalParentChildResult; 21 | } 22 | -------------------------------------------------------------------------------- /src/common/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod logger; 2 | extern crate core; 3 | 4 | use swc_common::MultiSpan; 5 | 6 | pub mod cli; 7 | pub mod config; 8 | pub mod dotenv; 9 | pub mod lazy; 10 | pub mod types; 11 | 12 | pub mod errors; 13 | 14 | // Source Parser 15 | #[allow(clippy::upper_case_acronyms)] 16 | #[derive(Debug, Clone)] 17 | pub struct SQL { 18 | /// Note that not all sql`` statements belong to a variable expression, therefore we must store it as an option 19 | pub var_decl_name: Option, 20 | pub query: String, 21 | pub span: MultiSpan, 22 | } 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/chain.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type ParentChildParams = []; 2 | 3 | export interface IParentChildResult { 4 | id: number; 5 | } 6 | 7 | export interface IParentChildQuery { 8 | params: ParentChildParams; 9 | result: IParentChildResult; 10 | } 11 | 12 | export type OptionalParentChildParams = []; 13 | 14 | export interface IOptionalParentChildResult { 15 | id: number; 16 | } 17 | 18 | export interface IOptionalParentChildQuery { 19 | params: OptionalParentChildParams; 20 | result: IOptionalParentChildResult; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/arrow-function.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const plainArrowFunction = () => sql`SELECT id FROM items` 4 | 5 | const nameOverrideArrowFunction = () => sql` 6 | -- @name: name overridden arrow func 7 | SELECT id FROM items; 8 | ` 9 | 10 | const arrowFunction = () => { 11 | return sql` 12 | -- @name: arrow function 13 | SELECT id FROM items 14 | ` 15 | } 16 | 17 | // TODO: this one isn't generating types / skips the query checker 18 | const arrowFunctionDefaultArgument = (x = sql`SELECT * FROM items`) => null 19 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-js.queries.ts: -------------------------------------------------------------------------------- 1 | export type JsQueryParams = [string | null]; 2 | 3 | export interface IJsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IJsQueryQuery { 9 | params: JsQueryParams; 10 | result: IJsQueryResult; 11 | } 12 | 13 | export type JsFunctionQueryParams = [number]; 14 | 15 | export interface IJsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IJsFunctionQueryQuery { 21 | params: JsFunctionQueryParams; 22 | result: IJsFunctionQueryResult; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/join/right_join.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic RIGHT JOIN 4 | const basicRightJoin = sql` 5 | -- @name: basic right join 6 | SELECT items.id, items.name, inventory.quantity 7 | FROM items 8 | RIGHT JOIN inventory ON items.inventory_id = inventory.id 9 | ` 10 | 11 | // RIGHT JOIN with parameters 12 | const rightJoinWithParams = sql` 13 | -- @name: right join with params 14 | SELECT items.id, items.name, inventory.quantity 15 | FROM items 16 | RIGHT JOIN inventory ON items.inventory_id = inventory.id 17 | WHERE inventory.quantity > $1 18 | ` 19 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-js.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type JsQueryParams = [string | null]; 2 | 3 | export interface IJsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IJsQueryQuery { 9 | params: JsQueryParams; 10 | result: IJsQueryResult; 11 | } 12 | 13 | export type JsFunctionQueryParams = [number]; 14 | 15 | export interface IJsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IJsFunctionQueryQuery { 21 | params: JsFunctionQueryParams; 22 | result: IJsFunctionQueryResult; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cjs.queries.ts: -------------------------------------------------------------------------------- 1 | export type CjsQueryParams = [string | null]; 2 | 3 | export interface ICjsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface ICjsQueryQuery { 9 | params: CjsQueryParams; 10 | result: ICjsQueryResult; 11 | } 12 | 13 | export type CjsFunctionQueryParams = [number]; 14 | 15 | export interface ICjsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface ICjsFunctionQueryQuery { 21 | params: CjsFunctionQueryParams; 22 | result: ICjsFunctionQueryResult; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cts.queries.ts: -------------------------------------------------------------------------------- 1 | export type CtsQueryParams = [string | null]; 2 | 3 | export interface ICtsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface ICtsQueryQuery { 9 | params: CtsQueryParams; 10 | result: ICtsQueryResult; 11 | } 12 | 13 | export type CtsFunctionQueryParams = [number]; 14 | 15 | export interface ICtsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface ICtsFunctionQueryQuery { 21 | params: CtsFunctionQueryParams; 22 | result: ICtsFunctionQueryResult; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mjs.queries.ts: -------------------------------------------------------------------------------- 1 | export type MjsQueryParams = [string | null]; 2 | 3 | export interface IMjsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IMjsQueryQuery { 9 | params: MjsQueryParams; 10 | result: IMjsQueryResult; 11 | } 12 | 13 | export type MjsFunctionQueryParams = [number]; 14 | 15 | export interface IMjsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IMjsFunctionQueryQuery { 21 | params: MjsFunctionQueryParams; 22 | result: IMjsFunctionQueryResult; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mts.queries.ts: -------------------------------------------------------------------------------- 1 | export type MtsQueryParams = [string | null]; 2 | 3 | export interface IMtsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IMtsQueryQuery { 9 | params: MtsQueryParams; 10 | result: IMtsQueryResult; 11 | } 12 | 13 | export type MtsFunctionQueryParams = [number]; 14 | 15 | export interface IMtsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IMtsFunctionQueryQuery { 21 | params: MtsFunctionQueryParams; 22 | result: IMtsFunctionQueryResult; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cjs.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CjsQueryParams = [string | null]; 2 | 3 | export interface ICjsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface ICjsQueryQuery { 9 | params: CjsQueryParams; 10 | result: ICjsQueryResult; 11 | } 12 | 13 | export type CjsFunctionQueryParams = [number]; 14 | 15 | export interface ICjsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface ICjsFunctionQueryQuery { 21 | params: CjsFunctionQueryParams; 22 | result: ICjsFunctionQueryResult; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-cts.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CtsQueryParams = [string | null]; 2 | 3 | export interface ICtsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface ICtsQueryQuery { 9 | params: CtsQueryParams; 10 | result: ICtsQueryResult; 11 | } 12 | 13 | export type CtsFunctionQueryParams = [number]; 14 | 15 | export interface ICtsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface ICtsFunctionQueryQuery { 21 | params: CtsFunctionQueryParams; 22 | result: ICtsFunctionQueryResult; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mjs.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type MjsQueryParams = [string | null]; 2 | 3 | export interface IMjsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IMjsQueryQuery { 9 | params: MjsQueryParams; 10 | result: IMjsQueryResult; 11 | } 12 | 13 | export type MjsFunctionQueryParams = [number]; 14 | 15 | export interface IMjsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IMjsFunctionQueryQuery { 21 | params: MjsFunctionQueryParams; 22 | result: IMjsFunctionQueryResult; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/demo/file_extensions/queries-mts.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type MtsQueryParams = [string | null]; 2 | 3 | export interface IMtsQueryResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IMtsQueryQuery { 9 | params: MtsQueryParams; 10 | result: IMtsQueryResult; 11 | } 12 | 13 | export type MtsFunctionQueryParams = [number]; 14 | 15 | export interface IMtsFunctionQueryResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IMtsFunctionQueryQuery { 21 | params: MtsFunctionQueryParams; 22 | result: IMtsFunctionQueryResult; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.camelcase2.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "convertToCamelCaseColumnName": true 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.column_camel.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "columnNamingConvention": "camel" 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.camelcase1.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "convertToCamelCaseColumnName": false 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.column_pascal.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "columnNamingConvention": "pascal" 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/demo/typescript/expression/chain.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | function parent() { 4 | return { 5 | child: function (sqlString: string) { 6 | return null 7 | } 8 | } 9 | } 10 | 11 | parent().child(sql` 12 | -- @name: parent child 13 | SELECT id FROM items 14 | `) 15 | 16 | function optionalParent(): null | { child: (string) => null } { 17 | return { 18 | child: function (sqlString: string) { 19 | return null 20 | } 21 | } 22 | } 23 | 24 | optionalParent()?.child(sql` 25 | -- @name: optional parent child 26 | SELECT id FROM items 27 | `) -------------------------------------------------------------------------------- /ci/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | # This image is to test ubuntu environment of sqlx-ts binary 2 | # 1. docker build -f ci/Dockerfile.ubuntu -t sqlx-ts-ubuntu . 3 | # 2. docker run -it sqlx-ts-ubuntu /bin/bash 4 | 5 | FROM ubuntu 6 | 7 | RUN apt-get update -y 8 | 9 | RUN apt-get install -y --no-install-recommends \ 10 | asciidoctor \ 11 | zsh xz-utils liblz4-tool musl-tools \ 12 | brotli zstd \ 13 | build-essential libssl-dev pkg-config 14 | 15 | RUN apt-get install -y curl 16 | RUN apt-get install -y git 17 | 18 | RUN curl https://sh.rustup.rs -sSf | bash -s -- -y 19 | 20 | RUN git clone https://github.com/JasonShin/sqlx-ts.git 21 | -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "enabled": true, 4 | "columnNamingConvention": "camel", 5 | "convertToCamelCaseColumnName": false 6 | }, 7 | "connections": { 8 | "default": { 9 | "DB_TYPE": "postgres", 10 | "DB_HOST": "127.0.0.1", 11 | "DB_PORT": 54321, 12 | "DB_USER": "postgres", 13 | "DB_PASS": "postgres", 14 | "DB_NAME": "postgres" 15 | }, 16 | "db_mysql": { 17 | "DB_TYPE": "mysql", 18 | "DB_HOST": "127.0.0.1", 19 | "DB_PORT": 33306, 20 | "DB_USER": "root", 21 | "DB_NAME": "sqlx-ts" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.enabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "enabled": false 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.not_enabled.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "enabled": false 4 | }, 5 | "connections": { 6 | "default": { 7 | "DB_TYPE": "postgres", 8 | "DB_HOST": "127.0.0.1", 9 | "DB_PORT": 54321, 10 | "DB_USER": "postgres", 11 | "DB_PASS": "postgres", 12 | "DB_NAME": "postgres", 13 | "PG_SEARCH_PATH": "public,myschema" 14 | }, 15 | "db_mysql": { 16 | "DB_TYPE": "mysql", 17 | "DB_HOST": "127.0.0.1", 18 | "DB_PORT": 33306, 19 | "DB_USER": "root", 20 | "DB_NAME": "sqlx-ts" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /test-utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_utils" 3 | version = "0.1.0" 4 | edition = "2021" 5 | homepage = "https://github.com/JasonShin/sqlx-ts" 6 | authors = ['Jason Shin '] 7 | license = "MIT" 8 | description = "test utils for sqlx-ts" 9 | readme = "README.md" 10 | keywords = ["cli", "sql", "sqlx", "typescript", "javascript"] 11 | categories = ["command-line-utilities"] 12 | documentation = "https://jasonshin.github.io/sqlx-ts/" 13 | 14 | [dependencies] 15 | serde = { version = "1.0.188", features = ["derive"] } 16 | serde_json = { version = "1.0.107" } 17 | regex = { version = "1.5" } 18 | tempfile = "3.3.0" 19 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/for.queries.ts: -------------------------------------------------------------------------------- 1 | export type For1Params = []; 2 | 3 | export interface IFor1Result { 4 | id: number; 5 | } 6 | 7 | export interface IFor1Query { 8 | params: For1Params; 9 | result: IFor1Result; 10 | } 11 | 12 | export type For2Params = []; 13 | 14 | export interface IFor2Result { 15 | id: number; 16 | } 17 | 18 | export interface IFor2Query { 19 | params: For2Params; 20 | result: IFor2Result; 21 | } 22 | 23 | export type For3Params = []; 24 | 25 | export interface IFor3Result { 26 | id: number; 27 | } 28 | 29 | export interface IFor3Query { 30 | params: For3Params; 31 | result: IFor3Result; 32 | } 33 | -------------------------------------------------------------------------------- /node/src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { sql } from "./index"; 2 | 3 | test("should return single line", () => { 4 | const rawSql = sql`SELECT * FROM test;`; 5 | 6 | expect(rawSql).toBe("SELECT * FROM test;"); 7 | }); 8 | 9 | test("should return multiple lines", () => { 10 | const rawSql = sql` 11 | SELECT * 12 | FROM test 13 | WHERE createdAt > 2019-1-1; 14 | `; 15 | 16 | expect(rawSql).toBe(` 17 | SELECT * 18 | FROM test 19 | WHERE createdAt > 2019-1-1; 20 | `); 21 | }); 22 | 23 | test("should return empty", () => { 24 | const rawSql = sql``; 25 | 26 | expect(rawSql).toBe(""); 27 | }); 28 | -------------------------------------------------------------------------------- /tests/demo/alias/alias.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const sql1 = sql` 4 | SELECT 5 | id as id1 6 | FROM items; 7 | ` 8 | 9 | const sql2 = sql` 10 | SELECT items.id as id2 11 | FROM items 12 | ` 13 | 14 | const sql3 = sql` 15 | SELECT items.id 16 | FROM items 17 | ` 18 | 19 | const sql4 = sql` 20 | SELECT 21 | COUNT(*) AS the_count 22 | FROM items 23 | ` 24 | 25 | const sql5 = sql` 26 | SELECT AVG(quantity) AS the_avg 27 | FROM inventory 28 | ` 29 | 30 | const sql6 = sql` 31 | SELECT LOWER(varchar1) as lower_varchar 32 | FROM random 33 | ` 34 | 35 | const sql7 = sql` 36 | SELECT NOW() AS current_time 37 | FROM items 38 | ` 39 | -------------------------------------------------------------------------------- /tests/demo/join/full_outer_join.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic FULL OUTER JOIN (PostgreSQL only) 4 | const basicFullOuterJoin = sql` 5 | -- @name: basic full outer join 6 | SELECT items.id, items.name, inventory.quantity 7 | FROM items 8 | FULL OUTER JOIN inventory ON items.inventory_id = inventory.id 9 | ` 10 | 11 | // FULL OUTER JOIN with COALESCE 12 | const fullOuterJoinWithCoalesce = sql` 13 | -- @name: full outer join with coalesce 14 | SELECT 15 | COALESCE(items.id, inventory.id) AS id, 16 | items.name, 17 | inventory.quantity 18 | FROM items 19 | FULL OUTER JOIN inventory ON items.inventory_id = inventory.id 20 | ` 21 | -------------------------------------------------------------------------------- /tests/demo/typescript/statement/for.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type For1Params = []; 2 | 3 | export interface IFor1Result { 4 | id: number; 5 | } 6 | 7 | export interface IFor1Query { 8 | params: For1Params; 9 | result: IFor1Result; 10 | } 11 | 12 | export type For2Params = []; 13 | 14 | export interface IFor2Result { 15 | id: number; 16 | } 17 | 18 | export interface IFor2Query { 19 | params: For2Params; 20 | result: IFor2Result; 21 | } 22 | 23 | export type For3Params = []; 24 | 25 | export interface IFor3Result { 26 | id: number; 27 | } 28 | 29 | export interface IFor3Query { 30 | params: For3Params; 31 | result: IFor3Result; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /.sqlxrc.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "enabled": true, 4 | "columnNamingConvention": "camel", 5 | "convertToCamelCaseColumnName": false 6 | }, 7 | "connections": { 8 | "default": { 9 | "DB_TYPE": "postgres", 10 | "DB_HOST": "127.0.0.1", 11 | "DB_PORT": 54321, 12 | "DB_USER": "postgres", 13 | "DB_PASS": "postgres", 14 | "DB_NAME": "postgres", 15 | "PG_SEARCH_PATH": "public,myschema" 16 | }, 17 | "db_mysql": { 18 | "DB_TYPE": "mysql", 19 | "DB_HOST": "127.0.0.1", 20 | "DB_PORT": 33306, 21 | "DB_USER": "root", 22 | "DB_NAME": "sqlx-ts" 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /tests/configs/.sqlxrc.column_pascal_override.json: -------------------------------------------------------------------------------- 1 | { 2 | "generateTypes": { 3 | "convertToCamelCaseColumnName": true, 4 | "columnNamingConvention": "pascal" 5 | }, 6 | "connections": { 7 | "default": { 8 | "DB_TYPE": "postgres", 9 | "DB_HOST": "127.0.0.1", 10 | "DB_PORT": 54321, 11 | "DB_USER": "postgres", 12 | "DB_PASS": "postgres", 13 | "DB_NAME": "postgres", 14 | "PG_SEARCH_PATH": "public,myschema" 15 | }, 16 | "db_mysql": { 17 | "DB_TYPE": "mysql", 18 | "DB_HOST": "127.0.0.1", 19 | "DB_PORT": 33306, 20 | "DB_USER": "root", 21 | "DB_NAME": "sqlx-ts" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /book/docs/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | 6 | # Troubleshooting 7 | 8 | ## MacOS 9 | 10 | #### Running the binary simply returns `[1] killed ./sqlx-ts --help` 11 | 12 | This is because SQLX-TS haven't yet solved the developer license issue described https://users. 13 | rust-lang.org/t/distributing-cli-apps-on-macos/70223/13 for MacOS specifically. 14 | 15 | To fix this, you will need to goto `System Preferences -> Security & Privacy` 16 | 17 | 18 | 19 | You will see `sqlx-ts` binary blocked. Please manually enable it and you can start using sqlx-ts 20 | locally. 21 | 22 |
23 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/as_const.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic as const 4 | const basicAsConst = { 5 | somequery: sql`SELECT id, name FROM items` 6 | } as const 7 | 8 | // Function returning as const 9 | const functionReturningAsConst = { 10 | somequery: () => sql`SELECT id, name FROM items WHERE rarity = $1` 11 | } as const 12 | 13 | // Nested as const 14 | const nestedAsConst = { 15 | queries: { 16 | item: sql`SELECT id, name FROM items WHERE id = $1` 17 | } 18 | } as const 19 | 20 | // as const with type assertion 21 | const asConstWithTypeAssertion = { 22 | query: sql`SELECT id, name FROM items` 23 | } as const satisfies Record 24 | -------------------------------------------------------------------------------- /tests/demo/join/cross_join.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicCrossJoinParams = []; 2 | 3 | export interface IBasicCrossJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicCrossJoinQuery { 10 | params: BasicCrossJoinParams; 11 | result: IBasicCrossJoinResult; 12 | } 13 | 14 | export type CrossJoinWithWhereParams = [string | null]; 15 | 16 | export interface ICrossJoinWithWhereResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface ICrossJoinWithWhereQuery { 23 | params: CrossJoinWithWhereParams; 24 | result: ICrossJoinWithWhereResult; 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/join/cross_join.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicCrossJoinParams = []; 2 | 3 | export interface IBasicCrossJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicCrossJoinQuery { 10 | params: BasicCrossJoinParams; 11 | result: IBasicCrossJoinResult; 12 | } 13 | 14 | export type CrossJoinWithWhereParams = [string | null]; 15 | 16 | export interface ICrossJoinWithWhereResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface ICrossJoinWithWhereQuery { 23 | params: CrossJoinWithWhereParams; 24 | result: ICrossJoinWithWhereResult; 25 | } 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | 5 | postgres: 6 | image: postgres:${PG_VERSION:-13} 7 | restart: always 8 | environment: 9 | POSTGRES_PASSWORD: postgres 10 | volumes: 11 | - ./playpen/db/postgres_migration.sql:/docker-entrypoint-initdb.d/migration.sql 12 | ports: 13 | - 54321:5432 14 | 15 | mysql: 16 | image: mysql:${MYSQL_VERSION:-8} 17 | restart: always 18 | volumes: 19 | - ./playpen/db/${MYSQL_MIGRATION_FILE:-mysql_migration.sql}:/docker-entrypoint-initdb.d/mysql_migration.sql 20 | ports: 21 | - 33306:3306 22 | environment: 23 | MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 24 | MYSQL_DATABASE: sqlx-ts 25 | -------------------------------------------------------------------------------- /tests/demo/join/right_join.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicRightJoinParams = []; 2 | 3 | export interface IBasicRightJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicRightJoinQuery { 10 | params: BasicRightJoinParams; 11 | result: IBasicRightJoinResult; 12 | } 13 | 14 | export type RightJoinWithParamsParams = [number | null]; 15 | 16 | export interface IRightJoinWithParamsResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface IRightJoinWithParamsQuery { 23 | params: RightJoinWithParamsParams; 24 | result: IRightJoinWithParamsResult; 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/join/right_join.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicRightJoinParams = []; 2 | 3 | export interface IBasicRightJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicRightJoinQuery { 10 | params: BasicRightJoinParams; 11 | result: IBasicRightJoinResult; 12 | } 13 | 14 | export type RightJoinWithParamsParams = [number | null]; 15 | 16 | export interface IRightJoinWithParamsResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface IRightJoinWithParamsQuery { 23 | params: RightJoinWithParamsParams; 24 | result: IRightJoinWithParamsResult; 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/nested_case.queries.ts: -------------------------------------------------------------------------------- 1 | export type NestedCaseBasicParams = []; 2 | 3 | export interface INestedCaseBasicResult { 4 | detailedRarity: any; 5 | id: number; 6 | name: string; 7 | rarity: string | null; 8 | } 9 | 10 | export interface INestedCaseBasicQuery { 11 | params: NestedCaseBasicParams; 12 | result: INestedCaseBasicResult; 13 | } 14 | 15 | export type NestedCaseMultipleLevelsParams = []; 16 | 17 | export interface INestedCaseMultipleLevelsResult { 18 | id: number; 19 | name: string; 20 | tier: any; 21 | } 22 | 23 | export interface INestedCaseMultipleLevelsQuery { 24 | params: NestedCaseMultipleLevelsParams; 25 | result: INestedCaseMultipleLevelsResult; 26 | } 27 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/nested_case.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type NestedCaseBasicParams = []; 2 | 3 | export interface INestedCaseBasicResult { 4 | detailedRarity: any; 5 | id: number; 6 | name: string; 7 | rarity: string | null; 8 | } 9 | 10 | export interface INestedCaseBasicQuery { 11 | params: NestedCaseBasicParams; 12 | result: INestedCaseBasicResult; 13 | } 14 | 15 | export type NestedCaseMultipleLevelsParams = []; 16 | 17 | export interface INestedCaseMultipleLevelsResult { 18 | id: number; 19 | name: string; 20 | tier: any; 21 | } 22 | 23 | export interface INestedCaseMultipleLevelsQuery { 24 | params: NestedCaseMultipleLevelsParams; 25 | result: INestedCaseMultipleLevelsResult; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /tests/demo/delete/delete.queries.ts: -------------------------------------------------------------------------------- 1 | export type DeleteSql1Params = [number]; 2 | 3 | export interface IDeleteSql1Result { 4 | 5 | } 6 | 7 | export interface IDeleteSql1Query { 8 | params: DeleteSql1Params; 9 | result: IDeleteSql1Result; 10 | } 11 | 12 | export type DeleteSql2Params = [number]; 13 | 14 | export interface IDeleteSql2Result { 15 | 16 | } 17 | 18 | export interface IDeleteSql2Query { 19 | params: DeleteSql2Params; 20 | result: IDeleteSql2Result; 21 | } 22 | 23 | export type DeleteSql3Params = [number, string]; 24 | 25 | export interface IDeleteSql3Result { 26 | 27 | } 28 | 29 | export interface IDeleteSql3Query { 30 | params: DeleteSql3Params; 31 | result: IDeleteSql3Result; 32 | } 33 | -------------------------------------------------------------------------------- /book/docs/connect/sqlxignore.md: -------------------------------------------------------------------------------- 1 | # Ignore files 2 | 3 | you can use `.sqlxignore` file in order to ignore certain files from being processed by SQLX-TS. 4 | 5 | The `.sqlxignore` file must be located at the same directory as you run `sqlx-ts` CLI. Typically the file should live at the same level as _.gitignore._ 6 | 7 | By default, `*.queries.ts` and `*.queries.js` files are ignored. 8 | 9 | You can include more files in the ignore list by creating `.sqlxignore` 10 | 11 | ``` 12 | *.queries.ts 13 | *.something.* 14 | ``` 15 | 16 | `*` ignores all matching patterns. 17 | - The first one ignores all files with `.queries.ts` extension 18 | - The second one ignores all files with the string `.something.` in the filename 19 | -------------------------------------------------------------------------------- /tests/demo/delete/delete.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type DeleteSql1Params = [number]; 2 | 3 | export interface IDeleteSql1Result { 4 | 5 | } 6 | 7 | export interface IDeleteSql1Query { 8 | params: DeleteSql1Params; 9 | result: IDeleteSql1Result; 10 | } 11 | 12 | export type DeleteSql2Params = [number]; 13 | 14 | export interface IDeleteSql2Result { 15 | 16 | } 17 | 18 | export interface IDeleteSql2Query { 19 | params: DeleteSql2Params; 20 | result: IDeleteSql2Result; 21 | } 22 | 23 | export type DeleteSql3Params = [number, string]; 24 | 25 | export interface IDeleteSql3Result { 26 | 27 | } 28 | 29 | export interface IDeleteSql3Query { 30 | params: DeleteSql3Params; 31 | result: IDeleteSql3Result; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/ts_generator/sql_parser/translate_delete.rs: -------------------------------------------------------------------------------- 1 | use crate::core::connection::DBConn; 2 | use crate::ts_generator::errors::TsGeneratorError; 3 | use crate::ts_generator::sql_parser::expressions::translate_expr::translate_expr; 4 | use crate::ts_generator::types::ts_query::TsQuery; 5 | use sqlparser::ast::Expr; 6 | 7 | pub async fn translate_delete( 8 | ts_query: &mut TsQuery, 9 | where_conditions: &Expr, // WHERE conditions of the delete statement 10 | table_name: &str, 11 | db_conn: &DBConn, 12 | ) -> Result<(), TsGeneratorError> { 13 | translate_expr( 14 | where_conditions, 15 | &Some(table_name), 16 | &None, 17 | None, 18 | ts_query, 19 | db_conn, 20 | false, 21 | ) 22 | .await 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/join/full_outer_join.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicFullOuterJoinParams = []; 2 | 3 | export interface IBasicFullOuterJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicFullOuterJoinQuery { 10 | params: BasicFullOuterJoinParams; 11 | result: IBasicFullOuterJoinResult; 12 | } 13 | 14 | export type FullOuterJoinWithCoalesceParams = []; 15 | 16 | export interface IFullOuterJoinWithCoalesceResult { 17 | id: number; 18 | inventoryQuantity: number | null; 19 | itemsName: string; 20 | } 21 | 22 | export interface IFullOuterJoinWithCoalesceQuery { 23 | params: FullOuterJoinWithCoalesceParams; 24 | result: IFullOuterJoinWithCoalesceResult; 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/join/full_outer_join.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicFullOuterJoinParams = []; 2 | 3 | export interface IBasicFullOuterJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicFullOuterJoinQuery { 10 | params: BasicFullOuterJoinParams; 11 | result: IBasicFullOuterJoinResult; 12 | } 13 | 14 | export type FullOuterJoinWithCoalesceParams = []; 15 | 16 | export interface IFullOuterJoinWithCoalesceResult { 17 | id: number; 18 | inventoryQuantity: number | null; 19 | itemsName: string; 20 | } 21 | 22 | export interface IFullOuterJoinWithCoalesceQuery { 23 | params: FullOuterJoinWithCoalesceParams; 24 | result: IFullOuterJoinWithCoalesceResult; 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/select/date-functions.queries.ts: -------------------------------------------------------------------------------- 1 | export type AtTimeZoneParams = []; 2 | 3 | export interface IAtTimeZoneResult { 4 | id: number; 5 | someDate: Date; 6 | } 7 | 8 | export interface IAtTimeZoneQuery { 9 | params: AtTimeZoneParams; 10 | result: IAtTimeZoneResult; 11 | } 12 | 13 | export type CastParams = []; 14 | 15 | export interface ICastResult { 16 | date: Date; 17 | id: number; 18 | } 19 | 20 | export interface ICastQuery { 21 | params: CastParams; 22 | result: ICastResult; 23 | } 24 | 25 | export type ExtractParams = []; 26 | 27 | export interface IExtractResult { 28 | id: number; 29 | theMonth: Date; 30 | } 31 | 32 | export interface IExtractQuery { 33 | params: ExtractParams; 34 | result: IExtractResult; 35 | } 36 | -------------------------------------------------------------------------------- /tests/demo/select/date-functions.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type AtTimeZoneParams = []; 2 | 3 | export interface IAtTimeZoneResult { 4 | id: number; 5 | someDate: Date; 6 | } 7 | 8 | export interface IAtTimeZoneQuery { 9 | params: AtTimeZoneParams; 10 | result: IAtTimeZoneResult; 11 | } 12 | 13 | export type CastParams = []; 14 | 15 | export interface ICastResult { 16 | date: Date; 17 | id: number; 18 | } 19 | 20 | export interface ICastQuery { 21 | params: CastParams; 22 | result: ICastResult; 23 | } 24 | 25 | export type ExtractParams = []; 26 | 27 | export interface IExtractResult { 28 | id: number; 29 | theMonth: Date; 30 | } 31 | 32 | export interface IExtractQuery { 33 | params: ExtractParams; 34 | result: IExtractResult; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/types.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | /////////////////////////////////// 4 | // Interface, type, enum, module // 5 | /////////////////////////////////// 6 | 7 | interface TestInterface { 8 | name: string; 9 | } 10 | 11 | type TestType = number; 12 | 13 | enum TestEnum { 14 | a, 15 | b, 16 | c, 17 | } 18 | 19 | module TestModule { 20 | } 21 | 22 | 23 | interface TestInterface { 24 | sql1: string 25 | get sql2(): string 26 | set sql3(value: string) 27 | } 28 | 29 | module TestModule { 30 | const moduleSql = sql`SELECT id FROM items` 31 | } 32 | 33 | let name: any = 'test' 34 | let companyName = name 35 | let partnerName = name as string 36 | let someName = 'test' as const 37 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Safety is one of the core principle of sqlx-ts, and to that end, we would like to ensure that Rust has a secure implementation. 6 | Thank you for taking the time to responsibly disclose any issues you find. 7 | 8 | All security bugs in the CLI and node module distributions should be reported by email to visualbbasic@gmail.com or create a GitHub issue. 9 | Your vulnerability report will be acknowledged as soon as possible, and you’ll receive a more detailed response to your enquiry indicating the next steps in handling your report. 10 | 11 | While sqlx-ts is sitting on the safe side as it's a CLI application, we still would like to be alerted on any security issues and react on those issues ASAP. 12 | -------------------------------------------------------------------------------- /ci/ubuntu-install-packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Reference: https://github.com/BurntSushi/ripgrep/blob/master/ci/ubuntu-install-packages 4 | # This script gets run in weird environments that have been stripped of just 5 | # about every inessential thing. In order to keep this script versatile, we 6 | # just install 'sudo' and use it like normal if it doesn't exist. If it doesn't 7 | # exist, we assume we're root. (Otherwise we ain't doing much of anything 8 | # anyway.) 9 | if ! command -V sudo; then 10 | apt-get update 11 | apt-get install -y --no-install-recommends sudo 12 | fi 13 | sudo apt-get update 14 | sudo apt-get install -y --no-install-recommends \ 15 | asciidoctor \ 16 | zsh xz-utils liblz4-tool musl-tools \ 17 | brotli zstd \ 18 | build-essential libssl-dev pkg-config 19 | -------------------------------------------------------------------------------- /tests/demo/postgres/jsonb_operations.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // jsonb_build_object basic 4 | const jsonbBuildObjectBasic = sql` 5 | -- @name: jsonb build object basic 6 | SELECT 7 | id, 8 | jsonb_build_object('id', id, 'name', name, 'rarity', rarity) AS item_json 9 | FROM items 10 | ` 11 | 12 | // jsonb_agg for aggregation 13 | const jsonbAggregation = sql` 14 | -- @name: jsonb aggregation 15 | SELECT 16 | rarity, 17 | jsonb_agg(jsonb_build_object('id', id, 'name', name)) AS items 18 | FROM items 19 | GROUP BY rarity 20 | ` 21 | 22 | // JSON operators in SELECT 23 | const jsonOperatorsSelect = sql` 24 | -- @name: json operators select 25 | SELECT 26 | id, 27 | name, 28 | jsonb_build_object('id', id, 'name', name) ->> 'name' AS extracted_name 29 | FROM items 30 | ` 31 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/logical.queries.ts: -------------------------------------------------------------------------------- 1 | export type NullishCoalescingParams = []; 2 | 3 | export interface INullishCoalescingResult { 4 | id: number; 5 | } 6 | 7 | export interface INullishCoalescingQuery { 8 | params: NullishCoalescingParams; 9 | result: INullishCoalescingResult; 10 | } 11 | 12 | export type PipePipeParams = []; 13 | 14 | export interface IPipePipeResult { 15 | id: number; 16 | } 17 | 18 | export interface IPipePipeQuery { 19 | params: PipePipeParams; 20 | result: IPipePipeResult; 21 | } 22 | 23 | export type AmpersandAmpersandParams = []; 24 | 25 | export interface IAmpersandAmpersandResult { 26 | id: number; 27 | } 28 | 29 | export interface IAmpersandAmpersandQuery { 30 | params: AmpersandAmpersandParams; 31 | result: IAmpersandAmpersandResult; 32 | } 33 | -------------------------------------------------------------------------------- /tests/demo/delete/delete_returning.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Issue #226: DELETE with RETURNING clause should generate types 4 | const deleteReturningAll = sql` 5 | -- @name: delete returning all 6 | DELETE FROM items 7 | WHERE id = $1 8 | RETURNING * 9 | ` 10 | 11 | const deleteReturningSpecific = sql` 12 | -- @name: delete returning specific 13 | DELETE FROM items 14 | WHERE id = $1 15 | RETURNING id, name 16 | ` 17 | 18 | const deleteReturningWithAlias = sql` 19 | -- @name: delete returning with alias 20 | DELETE FROM items 21 | WHERE id = $1 22 | RETURNING id AS deleted_id, name AS deleted_name 23 | ` 24 | 25 | const deleteReturningExpression = sql` 26 | -- @name: delete returning expression 27 | DELETE FROM items 28 | WHERE id = $1 29 | RETURNING id, UPPER(name) AS upper_name 30 | ` 31 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/logical.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type NullishCoalescingParams = []; 2 | 3 | export interface INullishCoalescingResult { 4 | id: number; 5 | } 6 | 7 | export interface INullishCoalescingQuery { 8 | params: NullishCoalescingParams; 9 | result: INullishCoalescingResult; 10 | } 11 | 12 | export type PipePipeParams = []; 13 | 14 | export interface IPipePipeResult { 15 | id: number; 16 | } 17 | 18 | export interface IPipePipeQuery { 19 | params: PipePipeParams; 20 | result: IPipePipeResult; 21 | } 22 | 23 | export type AmpersandAmpersandParams = []; 24 | 25 | export interface IAmpersandAmpersandResult { 26 | id: number; 27 | } 28 | 29 | export interface IAmpersandAmpersandQuery { 30 | params: AmpersandAmpersandParams; 31 | result: IAmpersandAmpersandResult; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /book/docs/limitations.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # Limitations 6 | 7 | The page aims to list down limitations of SQLX-TS. So for the users who are interested in using the tool, you have a clear idea what are the current limitations. However, as we evolve the tools, some of the limitations would be fixed in the future releases. 8 | 9 | ### 1. parsing of SQL is done using sqlparser-rs and any bugs in this modules would be inherited 10 | 11 | [sqlparser-rs](https://github.com/sqlparser-rs/sqlparser-rs) is an essential module of SQLX-TS in order to process SQLs into Typescript type definitions. As a result, any bug in this module will be inherited to sqlx-ts and we will need an update in the module in order to fix the problem. So far, sqlparser-rs is well maintained and being updated in the recent days. 12 | -------------------------------------------------------------------------------- /src/parser/mod.rs: -------------------------------------------------------------------------------- 1 | mod decl; 2 | mod import; 3 | mod js_parser; 4 | mod sql_parser; 5 | mod tag; 6 | 7 | use crate::common::SQL; 8 | use crate::parser::js_parser::parse_js_file; 9 | use crate::parser::sql_parser::parse_sql_file; 10 | use color_eyre::eyre::Result; 11 | use std::collections::HashMap; 12 | use std::path::PathBuf; 13 | use swc_common::errors::Handler; 14 | 15 | pub fn parse_source(path: &PathBuf) -> Result<(HashMap>, Handler)> { 16 | let extension = path.extension().and_then(|s| s.to_str()).unwrap_or(""); 17 | let result = match extension { 18 | "ts" | "js" | "mts" | "cts" | "mjs" | "cjs" => parse_js_file(path), 19 | "sql" => parse_sql_file(path), 20 | _ => { 21 | return Err(color_eyre::eyre::eyre!("Unsupported file extension: {}", extension)); 22 | } 23 | }; 24 | result 25 | } 26 | -------------------------------------------------------------------------------- /tests/demo/insert/returning.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const insertWildcard = sql` 4 | INSERT INTO items 5 | VALUES (1, 'sword', 'epic', 'hmm', null) 6 | RETURNING *; 7 | ` 8 | 9 | const insertSelector = sql` 10 | INSERT INTO items 11 | VALUES (1, 'sword', 'epic', 'hmm', null) 12 | RETURNING id, rarity; 13 | ` 14 | 15 | const insertAlias = sql` 16 | INSERT INTO items 17 | VALUES (1, 'sword', 'epic', 'hmm', 1) 18 | RETURNING id as id1, rarity as Rarity1; 19 | ` 20 | 21 | const insertQuoted = sql` 22 | INSERT INTO items 23 | VALUES (1, 'sword', 'epic', 'hmm', 1) 24 | RETURNING "id" as id1, rarity as "Rarity1"; 25 | ` 26 | 27 | 28 | const insertParams = sql` 29 | INSERT INTO items (id, name, rarity, flavor_text, inventory_id) 30 | VALUES (1, 'sword', 'epic', 'hmm', 1) 31 | RETURNING "id" as id1, rarity as "Rarity1"; 32 | ` 33 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/object.queries.ts: -------------------------------------------------------------------------------- 1 | export type AnotherTestObjectQueryParams = []; 2 | 3 | export interface IAnotherTestObjectQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IAnotherTestObjectQueryQuery { 12 | params: AnotherTestObjectQueryParams; 13 | result: IAnotherTestObjectQueryResult; 14 | } 15 | 16 | export type NestedTestObjectQueryParams = []; 17 | 18 | export interface INestedTestObjectQueryResult { 19 | flavor_text: string | null; 20 | id: number; 21 | inventory_id: number | null; 22 | name: string; 23 | rarity: string | null; 24 | } 25 | 26 | export interface INestedTestObjectQueryQuery { 27 | params: NestedTestObjectQueryParams; 28 | result: INestedTestObjectQueryResult; 29 | } 30 | -------------------------------------------------------------------------------- /tests/demo/update/update.queries.ts: -------------------------------------------------------------------------------- 1 | export type UpdateQueryParams = [string, string | null, number]; 2 | 3 | export interface IUpdateQueryResult { 4 | 5 | } 6 | 7 | export interface IUpdateQueryQuery { 8 | params: UpdateQueryParams; 9 | result: IUpdateQueryResult; 10 | } 11 | 12 | export type QuotedUpdateQueryParams = [string, string | null, number]; 13 | 14 | export interface IQuotedUpdateQueryResult { 15 | 16 | } 17 | 18 | export interface IQuotedUpdateQueryQuery { 19 | params: QuotedUpdateQueryParams; 20 | result: IQuotedUpdateQueryResult; 21 | } 22 | 23 | export type NullableFieldUpdateParams = [string | null, number]; 24 | 25 | export interface INullableFieldUpdateResult { 26 | 27 | } 28 | 29 | export interface INullableFieldUpdateQuery { 30 | params: NullableFieldUpdateParams; 31 | result: INullableFieldUpdateResult; 32 | } 33 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/object.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type AnotherTestObjectQueryParams = []; 2 | 3 | export interface IAnotherTestObjectQueryResult { 4 | flavor_text: string | null; 5 | id: number; 6 | inventory_id: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IAnotherTestObjectQueryQuery { 12 | params: AnotherTestObjectQueryParams; 13 | result: IAnotherTestObjectQueryResult; 14 | } 15 | 16 | export type NestedTestObjectQueryParams = []; 17 | 18 | export interface INestedTestObjectQueryResult { 19 | flavor_text: string | null; 20 | id: number; 21 | inventory_id: number | null; 22 | name: string; 23 | rarity: string | null; 24 | } 25 | 26 | export interface INestedTestObjectQueryQuery { 27 | params: NestedTestObjectQueryParams; 28 | result: INestedTestObjectQueryResult; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /tests/demo/update/update.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type UpdateQueryParams = [string, string | null, number]; 2 | 3 | export interface IUpdateQueryResult { 4 | 5 | } 6 | 7 | export interface IUpdateQueryQuery { 8 | params: UpdateQueryParams; 9 | result: IUpdateQueryResult; 10 | } 11 | 12 | export type QuotedUpdateQueryParams = [string, string | null, number]; 13 | 14 | export interface IQuotedUpdateQueryResult { 15 | 16 | } 17 | 18 | export interface IQuotedUpdateQueryQuery { 19 | params: QuotedUpdateQueryParams; 20 | result: IQuotedUpdateQueryResult; 21 | } 22 | 23 | export type NullableFieldUpdateParams = [string | null, number]; 24 | 25 | export interface INullableFieldUpdateResult { 26 | 27 | } 28 | 29 | export interface INullableFieldUpdateQuery { 30 | params: NullableFieldUpdateParams; 31 | result: INullableFieldUpdateResult; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/arrow-function.queries.ts: -------------------------------------------------------------------------------- 1 | export type PlainArrowFunctionParams = []; 2 | 3 | export interface IPlainArrowFunctionResult { 4 | id: number; 5 | } 6 | 7 | export interface IPlainArrowFunctionQuery { 8 | params: PlainArrowFunctionParams; 9 | result: IPlainArrowFunctionResult; 10 | } 11 | 12 | export type NameOverriddenArrowFuncParams = []; 13 | 14 | export interface INameOverriddenArrowFuncResult { 15 | id: number; 16 | } 17 | 18 | export interface INameOverriddenArrowFuncQuery { 19 | params: NameOverriddenArrowFuncParams; 20 | result: INameOverriddenArrowFuncResult; 21 | } 22 | 23 | export type ArrowFunctionParams = []; 24 | 25 | export interface IArrowFunctionResult { 26 | id: number; 27 | } 28 | 29 | export interface IArrowFunctionQuery { 30 | params: ArrowFunctionParams; 31 | result: IArrowFunctionResult; 32 | } 33 | -------------------------------------------------------------------------------- /tests/demo/update/update_returning.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Issue #226: UPDATE with RETURNING clause should generate types 4 | const updateReturningAll = sql` 5 | -- @name: update returning all 6 | UPDATE items 7 | SET name = $1 8 | WHERE id = $2 9 | RETURNING * 10 | ` 11 | 12 | const updateReturningSpecific = sql` 13 | -- @name: update returning specific 14 | UPDATE items 15 | SET name = $1 16 | WHERE id = $2 17 | RETURNING id, name 18 | ` 19 | 20 | const updateReturningWithAlias = sql` 21 | -- @name: update returning with alias 22 | UPDATE items 23 | SET name = $1 24 | WHERE id = $2 25 | RETURNING id AS updated_id, name AS updated_name 26 | ` 27 | 28 | const updateReturningExpression = sql` 29 | -- @name: update returning expression 30 | UPDATE items 31 | SET name = $1 32 | WHERE id = $2 33 | RETURNING id, LOWER(name) AS lower_name 34 | ` 35 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/arrow-function.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type PlainArrowFunctionParams = []; 2 | 3 | export interface IPlainArrowFunctionResult { 4 | id: number; 5 | } 6 | 7 | export interface IPlainArrowFunctionQuery { 8 | params: PlainArrowFunctionParams; 9 | result: IPlainArrowFunctionResult; 10 | } 11 | 12 | export type NameOverriddenArrowFuncParams = []; 13 | 14 | export interface INameOverriddenArrowFuncResult { 15 | id: number; 16 | } 17 | 18 | export interface INameOverriddenArrowFuncQuery { 19 | params: NameOverriddenArrowFuncParams; 20 | result: INameOverriddenArrowFuncResult; 21 | } 22 | 23 | export type ArrowFunctionParams = []; 24 | 25 | export interface IArrowFunctionResult { 26 | id: number; 27 | } 28 | 29 | export interface IArrowFunctionQuery { 30 | params: ArrowFunctionParams; 31 | result: IArrowFunctionResult; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/auto-merge-dependabot.yaml: -------------------------------------------------------------------------------- 1 | name: auto-merge-dependabot.yaml 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: github.actor == 'dependabot[bot]' 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v2 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - name: Enable auto-merge for Dependabot PRs 19 | if: contains(steps.metadata.outputs.dependency-names, 'my-dependency') && steps.metadata.outputs.update-type == 'version-update:semver-patch' 20 | run: gh pr merge --auto --merge "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | -------------------------------------------------------------------------------- /tests/demo/postgres/array_operations.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // array_agg basic 4 | const arrayAggBasic = sql` 5 | -- @name: array agg basic 6 | SELECT 7 | rarity, 8 | array_agg(name) AS names 9 | FROM items 10 | GROUP BY rarity 11 | ` 12 | 13 | // array_agg with ORDER BY 14 | const arrayAggWithOrderBy = sql` 15 | -- @name: array agg with order by 16 | SELECT 17 | rarity, 18 | array_agg(name ORDER BY id) AS names_ordered 19 | FROM items 20 | GROUP BY rarity 21 | ` 22 | 23 | // Array literal and ANY 24 | const arrayLiteralAny = sql` 25 | -- @name: array literal any 26 | SELECT id, name, rarity 27 | FROM items 28 | WHERE rarity = ANY(ARRAY['common', 'rare']) 29 | ` 30 | 31 | // Array with parameters 32 | const arrayWithParams = sql` 33 | -- @name: array with params 34 | SELECT id, name, rarity 35 | FROM items 36 | WHERE rarity = ANY($1::text[]) 37 | ` 38 | -------------------------------------------------------------------------------- /.github/workflows/deploy-gh-pages.yaml: -------------------------------------------------------------------------------- 1 | name: gh-pages 2 | on: 3 | push: 4 | branches: [main] 5 | 6 | jobs: 7 | publish-docs-and-install-script: 8 | runs-on: ubuntu-latest 9 | defaults: 10 | run: 11 | working-directory: ./book 12 | steps: 13 | - name: Checkout 🛎️ 14 | uses: actions/checkout@v3 15 | 16 | - name: Set up Node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: 22.x 20 | 21 | - name: Install dependencies 22 | run: npm ci 23 | 24 | - name: Build 25 | run: npm run build 26 | 27 | - name: copies install.sh into the deployment folder 28 | run: cp ../scripts/install.sh ./build/ 29 | 30 | - name: Deploy 🚀 31 | uses: JamesIves/github-pages-deploy-action@v4.3.0 32 | with: 33 | branch: gh-pages 34 | folder: book/build 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/demo/select/boolean-functions.queries.ts: -------------------------------------------------------------------------------- 1 | export type ExistsParams = [number]; 2 | 3 | export interface IExistsResult { 4 | exists: boolean; 5 | } 6 | 7 | export interface IExistsQuery { 8 | params: ExistsParams; 9 | result: IExistsResult; 10 | } 11 | 12 | export type IsTrueParams = []; 13 | 14 | export interface IIsTrueResult { 15 | isTrue: boolean; 16 | } 17 | 18 | export interface IIsTrueQuery { 19 | params: IsTrueParams; 20 | result: IIsTrueResult; 21 | } 22 | 23 | export type IsFalseParams = []; 24 | 25 | export interface IIsFalseResult { 26 | isFalse: boolean; 27 | } 28 | 29 | export interface IIsFalseQuery { 30 | params: IsFalseParams; 31 | result: IIsFalseResult; 32 | } 33 | 34 | export type InListParams = []; 35 | 36 | export interface IInListResult { 37 | test: boolean; 38 | } 39 | 40 | export interface IInListQuery { 41 | params: InListParams; 42 | result: IInListResult; 43 | } 44 | -------------------------------------------------------------------------------- /tests/demo/string_functions/pattern_matching.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // LIKE operator basic 4 | const likeBasic = sql` 5 | -- @name: like basic 6 | SELECT id, name, rarity 7 | FROM items 8 | WHERE name LIKE 'S%' 9 | ` 10 | 11 | // LIKE with parameter 12 | const likeWithParam = sql` 13 | -- @name: like with param 14 | SELECT id, name, rarity 15 | FROM items 16 | WHERE name LIKE $1 17 | ` 18 | 19 | // ILIKE (case-insensitive LIKE) 20 | const ilike = sql` 21 | -- @name: ilike 22 | SELECT id, name, rarity 23 | FROM items 24 | WHERE name ILIKE '%sword%' 25 | ` 26 | 27 | // NOT LIKE 28 | const notLike = sql` 29 | -- @name: not like 30 | SELECT id, name, rarity 31 | FROM items 32 | WHERE name NOT LIKE 'A%' 33 | ` 34 | 35 | // SIMILAR TO (regex pattern) 36 | const similarTo = sql` 37 | -- @name: similar to 38 | SELECT id, name, rarity 39 | FROM items 40 | WHERE name SIMILAR TO '%(sword|shield)%' 41 | ` 42 | -------------------------------------------------------------------------------- /tests/demo/select/boolean-functions.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type ExistsParams = [number]; 2 | 3 | export interface IExistsResult { 4 | exists: boolean; 5 | } 6 | 7 | export interface IExistsQuery { 8 | params: ExistsParams; 9 | result: IExistsResult; 10 | } 11 | 12 | export type IsTrueParams = []; 13 | 14 | export interface IIsTrueResult { 15 | isTrue: boolean; 16 | } 17 | 18 | export interface IIsTrueQuery { 19 | params: IsTrueParams; 20 | result: IIsTrueResult; 21 | } 22 | 23 | export type IsFalseParams = []; 24 | 25 | export interface IIsFalseResult { 26 | isFalse: boolean; 27 | } 28 | 29 | export interface IIsFalseQuery { 30 | params: IsFalseParams; 31 | result: IIsFalseResult; 32 | } 33 | 34 | export type InListParams = []; 35 | 36 | export interface IInListResult { 37 | test: boolean; 38 | } 39 | 40 | export interface IInListQuery { 41 | params: InListParams; 42 | result: IInListResult; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/node.yaml: -------------------------------------------------------------------------------- 1 | name: node.yaml 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref }} 5 | cancel-in-progress: true 6 | 7 | on: 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | node: [ 20 ] 19 | defaults: 20 | run: 21 | working-directory: ./node 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - name: Use Node.js 26 | uses: actions/setup-node@v3 27 | with: 28 | node-version: ${{ matrix.node }} 29 | 30 | - name: install dependencies 31 | run: npm install --ignore-scripts 32 | 33 | - name: lint 34 | run: npm run lint 35 | 36 | - name: build 37 | run: npm run compile 38 | 39 | - name: test 40 | run: npm run test 41 | -------------------------------------------------------------------------------- /book/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /tests/demo/null_handling/coalesce.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // COALESCE basic 4 | const coalesceBasic = sql` 5 | -- @name: coalesce basic 6 | SELECT 7 | id, 8 | name, 9 | COALESCE(rarity, 'unknown') AS rarity_display 10 | FROM items 11 | ` 12 | 13 | // COALESCE with multiple fallbacks 14 | const coalesceMultiple = sql` 15 | -- @name: coalesce multiple 16 | SELECT 17 | id, 18 | name, 19 | COALESCE(flavor_text, name, 'no description') AS description 20 | FROM items 21 | ` 22 | 23 | // COALESCE with numeric values 24 | const coalesceNumeric = sql` 25 | -- @name: coalesce numeric 26 | SELECT 27 | id, 28 | name, 29 | COALESCE(inventory_id, 0) AS inventory_id_safe 30 | FROM items 31 | ` 32 | 33 | // COALESCE with aggregates 34 | const coalesceWithAggregates = sql` 35 | -- @name: coalesce with aggregates 36 | SELECT 37 | COALESCE(rarity, 'unknown') AS rarity_group, 38 | COUNT(*) AS count 39 | FROM items 40 | GROUP BY 1 41 | ` 42 | -------------------------------------------------------------------------------- /tests/demo/postgres/jsonb_operations.queries.ts: -------------------------------------------------------------------------------- 1 | export type JsonbBuildObjectBasicParams = []; 2 | 3 | export interface IJsonbBuildObjectBasicResult { 4 | id: number; 5 | itemJson: any; 6 | } 7 | 8 | export interface IJsonbBuildObjectBasicQuery { 9 | params: JsonbBuildObjectBasicParams; 10 | result: IJsonbBuildObjectBasicResult; 11 | } 12 | 13 | export type JsonbAggregationParams = []; 14 | 15 | export interface IJsonbAggregationResult { 16 | items: any; 17 | rarity: string | null; 18 | } 19 | 20 | export interface IJsonbAggregationQuery { 21 | params: JsonbAggregationParams; 22 | result: IJsonbAggregationResult; 23 | } 24 | 25 | export type JsonOperatorsSelectParams = []; 26 | 27 | export interface IJsonOperatorsSelectResult { 28 | extractedName: string; 29 | id: number; 30 | name: string; 31 | } 32 | 33 | export interface IJsonOperatorsSelectQuery { 34 | params: JsonOperatorsSelectParams; 35 | result: IJsonOperatorsSelectResult; 36 | } 37 | -------------------------------------------------------------------------------- /tests/demo/postgres/jsonb_operations.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type JsonbBuildObjectBasicParams = []; 2 | 3 | export interface IJsonbBuildObjectBasicResult { 4 | id: number; 5 | itemJson: any; 6 | } 7 | 8 | export interface IJsonbBuildObjectBasicQuery { 9 | params: JsonbBuildObjectBasicParams; 10 | result: IJsonbBuildObjectBasicResult; 11 | } 12 | 13 | export type JsonbAggregationParams = []; 14 | 15 | export interface IJsonbAggregationResult { 16 | items: any; 17 | rarity: string | null; 18 | } 19 | 20 | export interface IJsonbAggregationQuery { 21 | params: JsonbAggregationParams; 22 | result: IJsonbAggregationResult; 23 | } 24 | 25 | export type JsonOperatorsSelectParams = []; 26 | 27 | export interface IJsonOperatorsSelectResult { 28 | extractedName: string; 29 | id: number; 30 | name: string; 31 | } 32 | 33 | export interface IJsonOperatorsSelectQuery { 34 | params: JsonOperatorsSelectParams; 35 | result: IJsonOperatorsSelectResult; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tests/postgres_update_query_parameters.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod postgres_update_query_parameters { 3 | use assert_cmd::prelude::*; 4 | use pretty_assertions::assert_eq; 5 | use std::env; 6 | use std::fs; 7 | use std::io::Write; 8 | use std::process::Command; 9 | use tempfile::tempdir; 10 | 11 | use test_utils::test_utils::TSString; 12 | use test_utils::{run_test, sandbox::TestConfig}; 13 | 14 | #[rustfmt::skip] 15 | run_test!(should_pick_query_params_from_single_row_of_values, TestConfig::new("postgres", true, None, None), 16 | 17 | //// TS query //// 18 | r#" 19 | const someUpdateQuery = sql` 20 | UPDATE items 21 | SET rarity = $1; 22 | ` 23 | "#, 24 | 25 | //// Generated TS interfaces //// 26 | r#" 27 | export type SomeUpdateQueryParams = [string | null]; 28 | 29 | export interface ISomeUpdateQueryResult { 30 | 31 | } 32 | 33 | export interface ISomeUpdateQueryQuery { 34 | params: SomeUpdateQueryParams; 35 | result: ISomeUpdateQueryResult; 36 | } 37 | "#); 38 | } 39 | -------------------------------------------------------------------------------- /tests/demo/select/number-functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const ceil = sql` 4 | SELECT 5 | id, 6 | CEIL(51.11) AS some_number 7 | FROM items; 8 | ` 9 | 10 | const all = sql` 11 | select 12 | abs(1) as abs1, 13 | acos(1) as acos1, 14 | asin(1) as asin1, 15 | atan(1) as atan1, 16 | avg(1) as avg1, 17 | ceil(1) as ceil1, 18 | ceiling(1) as ceiling1, 19 | cos(1) as cos1, 20 | cot(1) as cot1, 21 | count(1) as count1, 22 | degrees(1) as degrees1, 23 | exp(1) as exp1, 24 | floor(1) as floor1, 25 | greatest(1) as greatest1, 26 | least(1) as least1, 27 | ln(1) as ln1, 28 | log(1) as log1, 29 | log10(1) as log101, 30 | max(1) as max1, 31 | min(1) as min1, 32 | pow(1, 1) as pow1, 33 | mod(1, 1) as mod1, 34 | pi() as pi1, 35 | power(1, 1) as pow2, 36 | radians(1) as radians1, 37 | round(1, 1) as round1, 38 | sign(1) as sign1, 39 | sin(1) as sin1, 40 | sqrt(1) as sqrt1, 41 | sum(1) as sum1, 42 | tan(1) as tan1, 43 | trunc(1.1) as trunc1 44 | from items; 45 | ` 46 | -------------------------------------------------------------------------------- /book/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; 2 | 3 | // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) 4 | 5 | /** 6 | * Creating a sidebar enables you to: 7 | - create an ordered group of docs 8 | - render a sidebar for each doc of that group 9 | - provide next/previous navigation 10 | 11 | The sidebars can be generated from the filesystem, or explicitly defined here. 12 | 13 | Create as many sidebars as you want. 14 | */ 15 | const sidebars: SidebarsConfig = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial-basics/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | export default sidebars; 34 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/simple_case.queries.ts: -------------------------------------------------------------------------------- 1 | export type SimpleCaseBasicParams = []; 2 | 3 | export interface ISimpleCaseBasicResult { 4 | id: number; 5 | name: string; 6 | rarityCode: any; 7 | } 8 | 9 | export interface ISimpleCaseBasicQuery { 10 | params: SimpleCaseBasicParams; 11 | result: ISimpleCaseBasicResult; 12 | } 13 | 14 | export type SimpleCaseWithNullParams = []; 15 | 16 | export interface ISimpleCaseWithNullResult { 17 | id: number; 18 | name: string; 19 | rarityLevel: any; 20 | } 21 | 22 | export interface ISimpleCaseWithNullQuery { 23 | params: SimpleCaseWithNullParams; 24 | result: ISimpleCaseWithNullResult; 25 | } 26 | 27 | export type MultipleCaseExpressionsParams = []; 28 | 29 | export interface IMultipleCaseExpressionsResult { 30 | id: number; 31 | idRange: any; 32 | name: string; 33 | rarityTier: any; 34 | } 35 | 36 | export interface IMultipleCaseExpressionsQuery { 37 | params: MultipleCaseExpressionsParams; 38 | result: IMultipleCaseExpressionsResult; 39 | } 40 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/nested_case.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Nested CASE basic 4 | const nestedCaseBasic = sql` 5 | -- @name: nested case basic 6 | SELECT 7 | id, 8 | name, 9 | rarity, 10 | CASE rarity 11 | WHEN 'legendary' THEN 12 | CASE 13 | WHEN id > 10 THEN 'ultra rare' 14 | ELSE 'rare' 15 | END 16 | WHEN 'rare' THEN 'uncommon' 17 | ELSE 'common' 18 | END AS detailed_rarity 19 | FROM items 20 | ` 21 | 22 | // Nested CASE with multiple levels 23 | const nestedCaseMultipleLevels = sql` 24 | -- @name: nested case multiple levels 25 | SELECT 26 | id, 27 | name, 28 | CASE 29 | WHEN rarity = 'legendary' THEN 30 | CASE 31 | WHEN id > 15 THEN 'S-tier' 32 | WHEN id > 10 THEN 'A-tier' 33 | ELSE 'B-tier' 34 | END 35 | WHEN rarity = 'rare' THEN 36 | CASE 37 | WHEN id > 10 THEN 'C-tier' 38 | ELSE 'D-tier' 39 | END 40 | ELSE 'E-tier' 41 | END AS tier 42 | FROM items 43 | ` 44 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/simple_case.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type SimpleCaseBasicParams = []; 2 | 3 | export interface ISimpleCaseBasicResult { 4 | id: number; 5 | name: string; 6 | rarityCode: any; 7 | } 8 | 9 | export interface ISimpleCaseBasicQuery { 10 | params: SimpleCaseBasicParams; 11 | result: ISimpleCaseBasicResult; 12 | } 13 | 14 | export type SimpleCaseWithNullParams = []; 15 | 16 | export interface ISimpleCaseWithNullResult { 17 | id: number; 18 | name: string; 19 | rarityLevel: any; 20 | } 21 | 22 | export interface ISimpleCaseWithNullQuery { 23 | params: SimpleCaseWithNullParams; 24 | result: ISimpleCaseWithNullResult; 25 | } 26 | 27 | export type MultipleCaseExpressionsParams = []; 28 | 29 | export interface IMultipleCaseExpressionsResult { 30 | id: number; 31 | idRange: any; 32 | name: string; 33 | rarityTier: any; 34 | } 35 | 36 | export interface IMultipleCaseExpressionsQuery { 37 | params: MultipleCaseExpressionsParams; 38 | result: IMultipleCaseExpressionsResult; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /book/docs/type-generation/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # DELETE statement 6 | 7 | To read more about how SQLX-TS translates query parameters, [visit this page](/type-generation#capabilities) 8 | 9 | ## MySQL 10 | 11 | Query params within a DELETE statement will be converted Typescript types 12 | 13 | ```typescript 14 | const someQuery = sql` 15 | DELETE FROM items WHERE id = ? 16 | ` 17 | ``` 18 | 19 | would generate following 20 | 21 | ```typescript 22 | export type SomeQueryParams = [number] 23 | 24 | export interface ISomeQueryQuery { 25 | params: SomeQueryParams 26 | results: null 27 | } 28 | ``` 29 | 30 | ## PostgreSQL 31 | 32 | If you the following query in your Typescript code 33 | 34 | ```typescript 35 | const someQuery = sql` 36 | DELETE FROM items WHERE id = $1; 37 | ` 38 | ``` 39 | 40 | would result in 41 | 42 | ```typescript 43 | export type SomeQueryParams = [number] 44 | 45 | export interface ISomeQueryQuery { 46 | params: SomeQueryParams 47 | results: null 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/await.queries.ts: -------------------------------------------------------------------------------- 1 | export type AsyncPlainFunctionParams = []; 2 | 3 | export interface IAsyncPlainFunctionResult { 4 | id: number; 5 | } 6 | 7 | export interface IAsyncPlainFunctionQuery { 8 | params: AsyncPlainFunctionParams; 9 | result: IAsyncPlainFunctionResult; 10 | } 11 | 12 | export type AsyncLambdaAwaitedParams = []; 13 | 14 | export interface IAsyncLambdaAwaitedResult { 15 | id: number; 16 | } 17 | 18 | export interface IAsyncLambdaAwaitedQuery { 19 | params: AsyncLambdaAwaitedParams; 20 | result: IAsyncLambdaAwaitedResult; 21 | } 22 | 23 | export type AsyncLambdaParams = []; 24 | 25 | export interface IAsyncLambdaResult { 26 | id: number; 27 | } 28 | 29 | export interface IAsyncLambdaQuery { 30 | params: AsyncLambdaParams; 31 | result: IAsyncLambdaResult; 32 | } 33 | 34 | export type IifLambdaParams = []; 35 | 36 | export interface IIifLambdaResult { 37 | id: number; 38 | } 39 | 40 | export interface IIifLambdaQuery { 41 | params: IifLambdaParams; 42 | result: IIifLambdaResult; 43 | } 44 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/await.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type AsyncPlainFunctionParams = []; 2 | 3 | export interface IAsyncPlainFunctionResult { 4 | id: number; 5 | } 6 | 7 | export interface IAsyncPlainFunctionQuery { 8 | params: AsyncPlainFunctionParams; 9 | result: IAsyncPlainFunctionResult; 10 | } 11 | 12 | export type AsyncLambdaAwaitedParams = []; 13 | 14 | export interface IAsyncLambdaAwaitedResult { 15 | id: number; 16 | } 17 | 18 | export interface IAsyncLambdaAwaitedQuery { 19 | params: AsyncLambdaAwaitedParams; 20 | result: IAsyncLambdaAwaitedResult; 21 | } 22 | 23 | export type AsyncLambdaParams = []; 24 | 25 | export interface IAsyncLambdaResult { 26 | id: number; 27 | } 28 | 29 | export interface IAsyncLambdaQuery { 30 | params: AsyncLambdaParams; 31 | result: IAsyncLambdaResult; 32 | } 33 | 34 | export type IifLambdaParams = []; 35 | 36 | export interface IIifLambdaResult { 37 | id: number; 38 | } 39 | 40 | export interface IIifLambdaQuery { 41 | params: IifLambdaParams; 42 | result: IIifLambdaResult; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright <2025> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /tests/demo/window/row_number.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic ROW_NUMBER 4 | const basicRowNumber = sql` 5 | -- @name: basic row number 6 | SELECT 7 | id, 8 | name, 9 | rarity, 10 | ROW_NUMBER() OVER (ORDER BY id) AS row_num 11 | FROM items 12 | ` 13 | 14 | // ROW_NUMBER with PARTITION BY 15 | const rowNumberWithPartition = sql` 16 | -- @name: row number with partition 17 | SELECT 18 | id, 19 | name, 20 | rarity, 21 | ROW_NUMBER() OVER (PARTITION BY rarity ORDER BY id) AS row_num 22 | FROM items 23 | ` 24 | 25 | // ROW_NUMBER with WHERE 26 | const rowNumberWithWhere = sql` 27 | -- @name: row number with where 28 | SELECT 29 | id, 30 | name, 31 | rarity, 32 | ROW_NUMBER() OVER (ORDER BY name) AS row_num 33 | FROM items 34 | WHERE rarity IS NOT NULL 35 | ` 36 | 37 | // ROW_NUMBER with parameters 38 | const rowNumberWithParams = sql` 39 | -- @name: row number with params 40 | SELECT 41 | id, 42 | name, 43 | rarity, 44 | ROW_NUMBER() OVER (ORDER BY id) AS row_num 45 | FROM items 46 | WHERE rarity = $1 47 | ` 48 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/binary-operations.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | let testData = '' 4 | 5 | // logical 6 | testData = true ?? sql` 7 | -- @name: nullish coalescing 8 | SELECT id FROM items 9 | ` 10 | 11 | testData = true || sql` 12 | -- @name: pipePipe 13 | SELECT id FROM items 14 | ` 15 | 16 | testData = true && sql` 17 | -- @name: ampersand ampersand 18 | SELECT id FROM items 19 | ` 20 | 21 | testData = 1 < sql` 22 | -- @name: less 23 | SELECT id FROM items; 24 | ` 25 | 26 | 1 <= sql` 27 | -- @name: less than 28 | SELECT id FROM items; 29 | ` 30 | 31 | 1 > sql` 32 | -- @name: greater than 33 | SELECT id FROM items; 34 | ` 35 | 36 | 1 >= sql` 37 | -- @name: greater equal 38 | SELECT id FROM items; 39 | ` 40 | 41 | 1 == sql` 42 | -- @name: equal equal 43 | SELECT id FROM items; 44 | ` 45 | 46 | 1 === sql` 47 | -- @name: equal equal equal 48 | SELECT id FROM items; 49 | ` 50 | 51 | 1 !== sql` 52 | -- @name: not equal equal 53 | SELECT id FROM items; 54 | ` 55 | 56 | 1 != sql` 57 | -- @name: not equal 58 | SELECT id FROM items; 59 | ` 60 | -------------------------------------------------------------------------------- /tests/demo/clauses/having.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // HAVING basic 4 | const havingBasic = sql` 5 | -- @name: having basic 6 | SELECT rarity, COUNT(*) AS count 7 | FROM items 8 | GROUP BY rarity 9 | HAVING COUNT(*) > 1 10 | ` 11 | 12 | // HAVING with aggregate condition 13 | const havingWithAggregate = sql` 14 | -- @name: having with aggregate 15 | SELECT rarity, COUNT(*) AS count, MAX(id) AS max_id 16 | FROM items 17 | GROUP BY rarity 18 | HAVING COUNT(*) > $1 AND MAX(id) > $2 19 | ` 20 | 21 | // HAVING with SUM 22 | const havingWithSum = sql` 23 | -- @name: having with sum 24 | SELECT items.rarity, SUM(inventory.quantity) AS total_quantity 25 | FROM items 26 | LEFT JOIN inventory ON items.inventory_id = inventory.id 27 | GROUP BY items.rarity 28 | HAVING SUM(inventory.quantity) > 10 29 | ` 30 | 31 | // HAVING with multiple conditions 32 | const havingMultipleConditions = sql` 33 | -- @name: having multiple conditions 34 | SELECT rarity, COUNT(*) AS count, AVG(id) AS avg_id 35 | FROM items 36 | GROUP BY rarity 37 | HAVING COUNT(*) > 1 AND AVG(id) < 100 38 | ` 39 | -------------------------------------------------------------------------------- /book/docs/connect/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Connecting to databases 6 | 7 | `sqlx-ts` supports the following approach connect to the database 8 | 9 | 1. [File based configuration](/connect/config-file) 10 | 2. [CLI options](#2-cli-options) 11 | 3. [Environment variables](/connect/environment-variables) 12 | 13 | If you provide database host by a CLI option and an environment variable, CLI option will take 14 | the priority over the environment variable. 15 | 16 | ### 1. File based config 17 | 18 | If your project needs connections to multiple databases for SQL check, you have to use the file 19 | based config and specify connection details for those databases. [Please check here for more details](/connect/config-file) 20 | 21 | ### 2. CLI options 22 | 23 | Run the following command for more details 24 | 25 | ```bash 26 | $ sqlx-ts --help 27 | ``` 28 | 29 | ### 3. Environment variables 30 | 31 | You can only configure the primary database connection through environment variables. [Please check here for more details](/connect/environment-variables) 32 | -------------------------------------------------------------------------------- /test-utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod sandbox; 2 | 3 | pub mod test_utils { 4 | use regex::Regex; 5 | 6 | pub trait TSString { 7 | fn flatten(&self) -> Self; 8 | } 9 | 10 | impl TSString for String { 11 | fn flatten(&self) -> Self { 12 | let re = Regex::new(r"[\n\s]+").unwrap(); 13 | re.replace_all(&self, " ").trim().to_string() 14 | } 15 | } 16 | 17 | #[test] 18 | fn test1() { 19 | let some_js = r#" 20 | export type SomeQueryParams = [number, number, number]; 21 | 22 | export interface ISomeQueryResult { 23 | id: number; 24 | table_id: number; 25 | food_type: string; 26 | points: number; 27 | time_takes_to_cook: number; 28 | }; 29 | "#; 30 | 31 | let expected = "export type SomeQueryParams = [number, number, number]; export interface ISomeQueryResult { id: number; table_id: number; food_type: string; points: number; time_takes_to_cook: number; };"; 32 | let result = some_js.to_string().flatten(); 33 | 34 | assert_eq!(expected, result); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/searched_case.queries.ts: -------------------------------------------------------------------------------- 1 | export type SearchedCaseBasicParams = []; 2 | 3 | export interface ISearchedCaseBasicResult { 4 | id: number; 5 | idCategory: any; 6 | name: string; 7 | } 8 | 9 | export interface ISearchedCaseBasicQuery { 10 | params: SearchedCaseBasicParams; 11 | result: ISearchedCaseBasicResult; 12 | } 13 | 14 | export type SearchedCaseMultipleConditionsParams = []; 15 | 16 | export interface ISearchedCaseMultipleConditionsResult { 17 | id: number; 18 | itemClass: any; 19 | name: string; 20 | rarity: string | null; 21 | } 22 | 23 | export interface ISearchedCaseMultipleConditionsQuery { 24 | params: SearchedCaseMultipleConditionsParams; 25 | result: ISearchedCaseMultipleConditionsResult; 26 | } 27 | 28 | export type SearchedCaseWithParamsParams = []; 29 | 30 | export interface ISearchedCaseWithParamsResult { 31 | id: number; 32 | name: string; 33 | thresholdStatus: any; 34 | } 35 | 36 | export interface ISearchedCaseWithParamsQuery { 37 | params: SearchedCaseWithParamsParams; 38 | result: ISearchedCaseWithParamsResult; 39 | } 40 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/searched_case.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type SearchedCaseBasicParams = []; 2 | 3 | export interface ISearchedCaseBasicResult { 4 | id: number; 5 | idCategory: any; 6 | name: string; 7 | } 8 | 9 | export interface ISearchedCaseBasicQuery { 10 | params: SearchedCaseBasicParams; 11 | result: ISearchedCaseBasicResult; 12 | } 13 | 14 | export type SearchedCaseMultipleConditionsParams = []; 15 | 16 | export interface ISearchedCaseMultipleConditionsResult { 17 | id: number; 18 | itemClass: any; 19 | name: string; 20 | rarity: string | null; 21 | } 22 | 23 | export interface ISearchedCaseMultipleConditionsQuery { 24 | params: SearchedCaseMultipleConditionsParams; 25 | result: ISearchedCaseMultipleConditionsResult; 26 | } 27 | 28 | export type SearchedCaseWithParamsParams = []; 29 | 30 | export interface ISearchedCaseWithParamsResult { 31 | id: number; 32 | name: string; 33 | thresholdStatus: any; 34 | } 35 | 36 | export interface ISearchedCaseWithParamsQuery { 37 | params: SearchedCaseWithParamsParams; 38 | result: ISearchedCaseWithParamsResult; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /tests/demo/select/number-functions.queries.ts: -------------------------------------------------------------------------------- 1 | export type CeilParams = []; 2 | 3 | export interface ICeilResult { 4 | id: number; 5 | someNumber: number; 6 | } 7 | 8 | export interface ICeilQuery { 9 | params: CeilParams; 10 | result: ICeilResult; 11 | } 12 | 13 | export type AllParams = []; 14 | 15 | export interface IAllResult { 16 | abs1: number; 17 | acos1: number; 18 | asin1: number; 19 | atan1: number; 20 | avg1: number; 21 | ceil1: number; 22 | ceiling1: number; 23 | cos1: number; 24 | cot1: number; 25 | count1: number; 26 | degrees1: number; 27 | exp1: number; 28 | floor1: number; 29 | greatest1: number; 30 | least1: number; 31 | ln1: number; 32 | log1: number; 33 | log101: number; 34 | max1: number; 35 | min1: number; 36 | mod1: number; 37 | pi1: number; 38 | pow1: number; 39 | pow2: number; 40 | radians1: number; 41 | round1: number; 42 | sign1: number; 43 | sin1: number; 44 | sqrt1: number; 45 | sum1: number; 46 | tan1: number; 47 | trunc1: number; 48 | } 49 | 50 | export interface IAllQuery { 51 | params: AllParams; 52 | result: IAllResult; 53 | } 54 | -------------------------------------------------------------------------------- /tests/demo/annotations/annotations.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | const annotationSql1 = sql` 4 | -- @name: test mysql query 5 | -- @db: db_mysql 6 | SELECT * 7 | FROM items; 8 | ` 9 | 10 | const annotationSql2 = sql` 11 | -- @name: test postgres query 12 | -- @db: default 13 | SELECT * 14 | FROM items; 15 | ` 16 | 17 | const annotationSql3 = sql` 18 | -- @result id: string 19 | SELECT 20 | id 21 | FROM items; 22 | ` 23 | 24 | const annotationSql4 = sql` 25 | -- @param 1: string 26 | SELECT * 27 | FROM inventory 28 | WHERE quantity > $1 29 | ` 30 | 31 | const annotationSql5 = sql` 32 | -- @result inventory_id: boolean 33 | -- @param 1: string 34 | SELECT 35 | inventory.id AS inventory_id 36 | FROM inventory 37 | JOIN items ON items.inventory_id = inventory.id 38 | WHERE inventory.id = $1 39 | ` 40 | 41 | const annotationSql6 = sql` 42 | -- @name: test mysql query with param overrides 43 | -- @db: db_mysql 44 | -- @param 1: string 45 | SELECT 46 | inventory.id AS inventory_id 47 | FROM inventory 48 | JOIN items ON items.inventory_id = inventory.id 49 | WHERE inventory.id = ? 50 | ` 51 | -------------------------------------------------------------------------------- /tests/demo/complex_expressions/type_casting.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // CAST function 4 | const castFunction = sql` 5 | -- @name: cast function 6 | SELECT 7 | id, 8 | name, 9 | CAST(id AS TEXT) AS id_as_text, 10 | CAST(id AS FLOAT) AS id_as_float, 11 | CAST(id AS BIGINT) AS id_as_bigint 12 | FROM items 13 | ` 14 | 15 | // PostgreSQL casting syntax 16 | const postgresqlCasting = sql` 17 | -- @name: postgresql casting 18 | SELECT 19 | id, 20 | name, 21 | id::TEXT AS id_as_text, 22 | id::FLOAT AS id_as_float, 23 | id::VARCHAR(10) AS id_as_varchar 24 | FROM items 25 | ` 26 | 27 | // Casting with operations 28 | const castingWithOperations = sql` 29 | -- @name: casting with operations 30 | SELECT 31 | id, 32 | name, 33 | (id::FLOAT / 3)::NUMERIC(10, 2) AS id_div_3_precise, 34 | CAST(CONCAT(id, '') AS INTEGER) AS id_from_concat 35 | FROM items 36 | ` 37 | 38 | // NULL casting 39 | const nullCasting = sql` 40 | -- @name: null casting 41 | SELECT 42 | id, 43 | name, 44 | CAST(NULL AS INTEGER) AS null_int, 45 | CAST(NULL AS TEXT) AS null_text 46 | FROM items 47 | ` 48 | -------------------------------------------------------------------------------- /tests/demo/select/number-functions.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CeilParams = []; 2 | 3 | export interface ICeilResult { 4 | id: number; 5 | someNumber: number; 6 | } 7 | 8 | export interface ICeilQuery { 9 | params: CeilParams; 10 | result: ICeilResult; 11 | } 12 | 13 | export type AllParams = []; 14 | 15 | export interface IAllResult { 16 | abs1: number; 17 | acos1: number; 18 | asin1: number; 19 | atan1: number; 20 | avg1: number; 21 | ceil1: number; 22 | ceiling1: number; 23 | cos1: number; 24 | cot1: number; 25 | count1: number; 26 | degrees1: number; 27 | exp1: number; 28 | floor1: number; 29 | greatest1: number; 30 | least1: number; 31 | ln1: number; 32 | log1: number; 33 | log101: number; 34 | max1: number; 35 | min1: number; 36 | mod1: number; 37 | pi1: number; 38 | pow1: number; 39 | pow2: number; 40 | radians1: number; 41 | round1: number; 42 | sign1: number; 43 | sin1: number; 44 | sqrt1: number; 45 | sum1: number; 46 | tan1: number; 47 | trunc1: number; 48 | } 49 | 50 | export interface IAllQuery { 51 | params: AllParams; 52 | result: IAllResult; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /tests/sample/sample.queries.ts: -------------------------------------------------------------------------------- 1 | export type SampleSelectQueryParams = [number]; 2 | 3 | export interface ISampleSelectQueryResult { 4 | name: string; 5 | some_id: number; 6 | } 7 | 8 | export interface ISampleSelectQueryQuery { 9 | params: SampleSelectQueryParams; 10 | result: ISampleSelectQueryResult; 11 | } 12 | 13 | export type SampleInsertQueryParams = [string]; 14 | 15 | export interface ISampleInsertQueryResult { 16 | 17 | } 18 | 19 | export interface ISampleInsertQueryQuery { 20 | params: SampleInsertQueryParams; 21 | result: ISampleInsertQueryResult; 22 | } 23 | 24 | export type SampleUpdateQueryParams = [string, number]; 25 | 26 | export interface ISampleUpdateQueryResult { 27 | 28 | } 29 | 30 | export interface ISampleUpdateQueryQuery { 31 | params: SampleUpdateQueryParams; 32 | result: ISampleUpdateQueryResult; 33 | } 34 | 35 | export type SampleDeleteQueryParams = [number]; 36 | 37 | export interface ISampleDeleteQueryResult { 38 | 39 | } 40 | 41 | export interface ISampleDeleteQueryQuery { 42 | params: SampleDeleteQueryParams; 43 | result: ISampleDeleteQueryResult; 44 | } 45 | -------------------------------------------------------------------------------- /tests/demo/postgres/upsert.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // INSERT ON CONFLICT DO NOTHING 4 | const upsertDoNothing = sql` 5 | -- @name: upsert do nothing 6 | INSERT INTO items (id, name, rarity) 7 | VALUES ($1, $2, $3) 8 | ON CONFLICT (id) DO NOTHING 9 | ` 10 | 11 | // INSERT ON CONFLICT DO UPDATE 12 | const upsertDoUpdate = sql` 13 | -- @name: upsert do update 14 | INSERT INTO items (id, name, rarity) 15 | VALUES ($1, $2, $3) 16 | ON CONFLICT (id) DO UPDATE 17 | SET name = EXCLUDED.name, rarity = EXCLUDED.rarity 18 | ` 19 | 20 | // INSERT ON CONFLICT with WHERE clause 21 | const upsertWithWhere = sql` 22 | -- @name: upsert with where 23 | INSERT INTO items (id, name, rarity) 24 | VALUES ($1, $2, $3) 25 | ON CONFLICT (id) DO UPDATE 26 | SET name = EXCLUDED.name 27 | WHERE items.rarity != 'legendary' 28 | ` 29 | 30 | // INSERT ON CONFLICT with RETURNING 31 | const upsertWithReturning = sql` 32 | -- @name: upsert with returning 33 | INSERT INTO items (id, name, rarity) 34 | VALUES ($1, $2, $3) 35 | ON CONFLICT (id) DO UPDATE 36 | SET name = EXCLUDED.name, rarity = EXCLUDED.rarity 37 | RETURNING * 38 | ` 39 | -------------------------------------------------------------------------------- /node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sqlx-ts", 3 | "version": "0.35.0", 4 | "description": "sqlx-ts ensures your raw SQLs are compile-time checked", 5 | "main": "dist/index.js", 6 | "maintainers": [ 7 | "visualbbasic@gmail.com" 8 | ], 9 | "author": "Jason Shin ", 10 | "license": "MIT", 11 | "bin": "./sqlx-ts", 12 | "scripts": { 13 | "postinstall": "node postinstall.js", 14 | "compile": "npx tsc -p tsconfig.json", 15 | "lint": "npx eslint --ext .ts src", 16 | "lint:fix": "npx eslint --ext .ts src --fix", 17 | "test": "npx jest", 18 | "prepublishOnly": "cp ../README.md . && npm i && npm run compile" 19 | }, 20 | "dependencies": { 21 | "adm-zip": "^0.5.16" 22 | }, 23 | "devDependencies": { 24 | "@types/jest": "^27.4.1", 25 | "@types/node": "^20.14.8", 26 | "@typescript-eslint/eslint-plugin": "^5.19.0", 27 | "@typescript-eslint/parser": "^5.19.0", 28 | "eslint": "^8.13.0", 29 | "jest": "^27.5.1", 30 | "ts-jest": "^27.1.4", 31 | "typescript": "^4.6.3" 32 | }, 33 | "engines": { 34 | "node": ">=12" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/searched_case.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Searched CASE basic 4 | const searchedCaseBasic = sql` 5 | -- @name: searched case basic 6 | SELECT 7 | id, 8 | name, 9 | CASE 10 | WHEN id < 5 THEN 'low' 11 | WHEN id < 10 THEN 'medium' 12 | ELSE 'high' 13 | END AS id_category 14 | FROM items 15 | ` 16 | 17 | // Searched CASE with multiple conditions 18 | const searchedCaseMultipleConditions = sql` 19 | -- @name: searched case multiple conditions 20 | SELECT 21 | id, 22 | name, 23 | rarity, 24 | CASE 25 | WHEN rarity = 'legendary' AND id > 10 THEN 'premium' 26 | WHEN rarity = 'legendary' THEN 'special' 27 | WHEN rarity = 'rare' THEN 'good' 28 | ELSE 'standard' 29 | END AS item_class 30 | FROM items 31 | ` 32 | 33 | // Searched CASE with parameters 34 | const searchedCaseWithParams = sql` 35 | -- @name: searched case with params 36 | SELECT 37 | id, 38 | name, 39 | CASE 40 | WHEN id > $1 THEN 'above threshold' 41 | WHEN id = $1 THEN 'at threshold' 42 | ELSE 'below threshold' 43 | END AS threshold_status 44 | FROM items 45 | ` 46 | -------------------------------------------------------------------------------- /tests/postgres_query_parameters.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod postgres_query_parameters_tests { 3 | use assert_cmd::prelude::*; 4 | use std::env; 5 | use std::fs; 6 | use std::io::Write; 7 | use std::process::Command; 8 | use tempfile::tempdir; 9 | 10 | use pretty_assertions::assert_eq; 11 | use test_utils::test_utils::TSString; 12 | use test_utils::{run_test, sandbox::TestConfig}; 13 | 14 | #[rustfmt::skip] 15 | run_test!(should_pick_query_params_from_flat_list_of_binary_ops, TestConfig::new("postgres", true, None, None), 16 | 17 | //// TS query //// 18 | r#" 19 | const someQuery = sql` 20 | SELECT * 21 | FROM inventory 22 | WHERE quantity > $1 23 | AND quantity < $2 24 | OR quantity = $3 25 | `; 26 | "#, 27 | 28 | //// Generated TS interfaces //// 29 | r#" 30 | export type SomeQueryParams = [number | null, number | null, number | null]; 31 | 32 | export interface ISomeQueryResult { 33 | character_id: number | null; 34 | id: number; 35 | quantity: number | null; 36 | } 37 | 38 | export interface ISomeQueryQuery { 39 | params: SomeQueryParams; 40 | result: ISomeQueryResult; 41 | } 42 | "#); 43 | } 44 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/simple_case.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Simple CASE expression 4 | const simpleCaseBasic = sql` 5 | -- @name: simple case basic 6 | SELECT 7 | id, 8 | name, 9 | CASE rarity 10 | WHEN 'common' THEN 'C' 11 | WHEN 'rare' THEN 'R' 12 | WHEN 'legendary' THEN 'L' 13 | ELSE 'U' 14 | END AS rarity_code 15 | FROM items 16 | ` 17 | 18 | // Simple CASE with NULL handling 19 | const simpleCaseWithNull = sql` 20 | -- @name: simple case with null 21 | SELECT 22 | id, 23 | name, 24 | CASE rarity 25 | WHEN 'common' THEN 1 26 | WHEN 'rare' THEN 2 27 | WHEN 'legendary' THEN 3 28 | ELSE 0 29 | END AS rarity_level 30 | FROM items 31 | ` 32 | 33 | // Multiple CASE expressions 34 | const multipleCaseExpressions = sql` 35 | -- @name: multiple case expressions 36 | SELECT 37 | id, 38 | name, 39 | CASE rarity 40 | WHEN 'common' THEN 'low' 41 | WHEN 'rare' THEN 'medium' 42 | ELSE 'high' 43 | END AS rarity_tier, 44 | CASE 45 | WHEN id < 5 THEN 'early' 46 | WHEN id < 10 THEN 'mid' 47 | ELSE 'late' 48 | END AS id_range 49 | FROM items 50 | ` 51 | -------------------------------------------------------------------------------- /tests/demo/join/left_join.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic LEFT JOIN 4 | const basicLeftJoin = sql` 5 | -- @name: basic left join 6 | SELECT items.id, items.name, inventory.quantity 7 | FROM items 8 | LEFT JOIN inventory ON items.inventory_id = inventory.id 9 | ` 10 | 11 | // LEFT JOIN with WHERE clause 12 | const leftJoinWithWhere = sql` 13 | -- @name: left join with where 14 | SELECT items.id, items.name, inventory.quantity 15 | FROM items 16 | LEFT JOIN inventory ON items.inventory_id = inventory.id 17 | WHERE items.rarity = $1 18 | ` 19 | 20 | // LEFT JOIN with NULL handling 21 | const leftJoinNullHandling = sql` 22 | -- @name: left join null handling 23 | SELECT items.id, items.name, COALESCE(inventory.quantity, 0) AS quantity 24 | FROM items 25 | LEFT JOIN inventory ON items.inventory_id = inventory.id 26 | ` 27 | 28 | // Multiple LEFT JOINs 29 | const multipleLeftJoins = sql` 30 | -- @name: multiple left joins 31 | SELECT items.id, items.name, inventory.quantity 32 | FROM items 33 | LEFT JOIN inventory ON items.inventory_id = inventory.id 34 | LEFT JOIN characters ON inventory.character_id = characters.id 35 | ` 36 | -------------------------------------------------------------------------------- /tests/demo/null_handling/nullif_and_is_null.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // IS NULL basic 4 | const isNullBasic = sql` 5 | -- @name: is null basic 6 | SELECT id, name, rarity 7 | FROM items 8 | WHERE rarity IS NULL 9 | ` 10 | 11 | // IS NOT NULL 12 | const isNotNull = sql` 13 | -- @name: is not null 14 | SELECT id, name, rarity 15 | FROM items 16 | WHERE rarity IS NOT NULL 17 | ` 18 | 19 | // NULLIF basic 20 | const nullifBasic = sql` 21 | -- @name: nullif basic 22 | SELECT 23 | id, 24 | name, 25 | NULLIF(rarity, 'common') AS rarity_excluding_common 26 | FROM items 27 | ` 28 | 29 | // NULLIF with empty string 30 | const nullifEmptyString = sql` 31 | -- @name: nullif empty string 32 | SELECT 33 | id, 34 | name, 35 | NULLIF(name, '') AS name_safe 36 | FROM items 37 | ` 38 | 39 | // IS DISTINCT FROM 40 | const isDistinctFrom = sql` 41 | -- @name: is distinct from 42 | SELECT id, name, rarity 43 | FROM items 44 | WHERE rarity IS DISTINCT FROM $1 45 | ` 46 | 47 | // IS NOT DISTINCT FROM 48 | const isNotDistinctFrom = sql` 49 | -- @name: is not distinct from 50 | SELECT id, name, rarity 51 | FROM items 52 | WHERE rarity IS NOT DISTINCT FROM $1 53 | ` 54 | -------------------------------------------------------------------------------- /tests/demo/datetime_functions/time_functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // NOW function 4 | const nowFunction = sql` 5 | -- @name: now function 6 | SELECT 7 | id, 8 | name, 9 | NOW() AS current_time, 10 | CURRENT_TIME AS current_time_only 11 | FROM characters 12 | ` 13 | 14 | // Time comparison 15 | const timeComparison = sql` 16 | -- @name: time comparison 17 | SELECT 18 | id, 19 | name, 20 | login_time, 21 | logout_time 22 | FROM characters 23 | WHERE login_time IS NOT NULL AND logout_time IS NOT NULL 24 | AND logout_time > login_time 25 | ` 26 | 27 | // Interval operations 28 | const intervalOperations = sql` 29 | -- @name: interval operations 30 | SELECT 31 | id, 32 | name, 33 | created_at, 34 | created_at + INTERVAL '1 hour' AS one_hour_later, 35 | created_at - INTERVAL '30 minutes' AS thirty_minutes_ago 36 | FROM characters 37 | WHERE created_at IS NOT NULL 38 | ` 39 | 40 | // Date difference 41 | const dateDifference = sql` 42 | -- @name: date difference 43 | SELECT 44 | id, 45 | name, 46 | logout_time - login_time AS session_duration 47 | FROM characters 48 | WHERE login_time IS NOT NULL AND logout_time IS NOT NULL 49 | ` 50 | -------------------------------------------------------------------------------- /book/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /tests/demo/typescript/demo.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | import { QueryTypes, Sequelize } from 'sequelize' 3 | 4 | ///// Sequelize ///// 5 | 6 | async function demo() { 7 | const sequelize = new Sequelize('postgres://') 8 | const result = await sequelize.query(sql` 9 | -- @name: testSequelizeQuery 10 | SELECT * FROM items 11 | WHERE id = $1; 12 | `!, { 13 | type: QueryTypes.SELECT, 14 | replacements: [], 15 | }) 16 | } 17 | 18 | // Native driver 19 | (async () => { 20 | await sql` 21 | -- @name: testAwaitQuery 22 | SELECT * FROM items 23 | ` 24 | await sql` 25 | -- @name: testAwaitQuery2 26 | SELECT * FROM items 27 | ` 28 | 29 | const awaitClientQuery = await client.query(sql` 30 | SELECT * FROM items; 31 | `) 32 | 33 | const [rows, i] = await connection.execute>(sql` 34 | -- @name: getItemsWithRows 35 | SELECT * FROM items 36 | `) 37 | 38 | await connection.execute(sql` 39 | -- @name: testInsert 40 | -- @db: db_mysql 41 | INSERT INTO items (id, name, rarity, flavor_text, inventory_id) VALUES (?, ?, ?, 'test', 1); 42 | `) 43 | 44 | connection.destroy() 45 | })(); 46 | -------------------------------------------------------------------------------- /src/parser/import.rs: -------------------------------------------------------------------------------- 1 | use swc_ecma_ast::{ImportDecl, ImportSpecifier, ModuleExportName}; 2 | 3 | pub fn find_sqlx_import_alias(import_decl: &ImportDecl) -> Option { 4 | let mut name: Option = None; 5 | let src = import_decl.src.value.to_string_lossy().to_string(); 6 | 7 | if src == "sqlx-ts" { 8 | for specifier in &import_decl.specifiers { 9 | if let ImportSpecifier::Named(import_named_specifier) = specifier { 10 | // for exampleL 11 | // import { sql: aliased } from 'sqlx-ts' <<< should satisfy following 12 | if let Some(imported) = &import_named_specifier.imported { 13 | match imported { 14 | ModuleExportName::Ident(ident) => { 15 | if ident.sym == "sql" { 16 | name = Some(import_named_specifier.local.sym.to_string()) 17 | } 18 | } 19 | _ => continue, 20 | } 21 | // for example: 22 | // import { sql } from 'sqlx-ts' <<< should satisfy following 23 | } else if import_named_specifier.local.sym == "sql" { 24 | name = Some("sql".to_string()) 25 | } 26 | } 27 | } 28 | } 29 | 30 | name 31 | } 32 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yaml: -------------------------------------------------------------------------------- 1 | name: coverage.yaml 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref }} 5 | cancel-in-progress: true 6 | 7 | on: 8 | schedule: 9 | - cron: '0 1 * * *' 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | 14 | jobs: 15 | coverage: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout sources 20 | uses: actions/checkout@v2 21 | 22 | - name: Install stable toolchain 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | profile: minimal 26 | toolchain: stable 27 | override: true 28 | 29 | - name: build docker-compose services for integration tests 30 | run: docker-compose -f docker-compose.yml up -d 31 | 32 | - uses: GuillaumeFalourd/wait-sleep-action@v1 33 | with: 34 | time: '10' # for 10 seconds 35 | 36 | - name: Check the docker-compose services running 37 | run: docker ps -a 38 | 39 | - name: Install tarpaulin 40 | run: cargo install cargo-tarpaulin 41 | 42 | - name: Run coverage 43 | run: cargo tarpaulin --tests -o html -b --coveralls ${{ secrets.COVERALLS_KEY }} --engine Llvm 44 | -------------------------------------------------------------------------------- /tests/demo/window/rank_functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // RANK basic 4 | const basicRank = sql` 5 | -- @name: basic rank 6 | SELECT 7 | id, 8 | name, 9 | rarity, 10 | RANK() OVER (ORDER BY id) AS rank 11 | FROM items 12 | ` 13 | 14 | // DENSE_RANK 15 | const densRank = sql` 16 | -- @name: dense rank 17 | SELECT 18 | id, 19 | name, 20 | rarity, 21 | DENSE_RANK() OVER (ORDER BY id DESC) AS dense_rank 22 | FROM items 23 | ` 24 | 25 | // RANK with PARTITION BY 26 | const rankWithPartition = sql` 27 | -- @name: rank with partition 28 | SELECT 29 | id, 30 | name, 31 | rarity, 32 | RANK() OVER (PARTITION BY rarity ORDER BY id) AS rank 33 | FROM items 34 | ` 35 | 36 | // Multiple ranking functions 37 | const multipleRanking = sql` 38 | -- @name: multiple ranking 39 | SELECT 40 | id, 41 | name, 42 | rarity, 43 | ROW_NUMBER() OVER (ORDER BY id) AS row_num, 44 | RANK() OVER (ORDER BY id) AS rank, 45 | DENSE_RANK() OVER (ORDER BY id) AS dense_rank 46 | FROM items 47 | ` 48 | 49 | // NTILE for quartiles 50 | const ntileQuartiles = sql` 51 | -- @name: ntile quartiles 52 | SELECT 53 | id, 54 | name, 55 | NTILE(4) OVER (ORDER BY id) AS quartile 56 | FROM items 57 | ` 58 | -------------------------------------------------------------------------------- /tests/demo/window/partition_by.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Single column partition 4 | const singlePartition = sql` 5 | -- @name: single partition 6 | SELECT 7 | id, 8 | name, 9 | rarity, 10 | COUNT(*) OVER (PARTITION BY rarity) AS rarity_count 11 | FROM items 12 | ` 13 | 14 | // Multiple column partition 15 | const multiplePartition = sql` 16 | -- @name: multiple partition 17 | SELECT 18 | id, 19 | name, 20 | rarity, 21 | COUNT(*) OVER (PARTITION BY rarity, name) AS count_per_group 22 | FROM items 23 | ` 24 | 25 | // Window aggregate functions 26 | const windowAggregates = sql` 27 | -- @name: window aggregates 28 | SELECT 29 | id, 30 | name, 31 | rarity, 32 | COUNT(*) OVER (PARTITION BY rarity) AS count, 33 | SUM(id) OVER (PARTITION BY rarity) AS sum_id, 34 | AVG(id) OVER (PARTITION BY rarity) AS avg_id, 35 | MIN(id) OVER (PARTITION BY rarity) AS min_id, 36 | MAX(id) OVER (PARTITION BY rarity) AS max_id 37 | FROM items 38 | ` 39 | 40 | // Window with ORDER BY 41 | const windowWithOrderBy = sql` 42 | -- @name: window with order by 43 | SELECT 44 | id, 45 | name, 46 | rarity, 47 | SUM(id) OVER (PARTITION BY rarity ORDER BY id) AS running_sum 48 | FROM items 49 | ` 50 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/as_const.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicAsConstParams = []; 2 | 3 | export interface IBasicAsConstResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IBasicAsConstQuery { 9 | params: BasicAsConstParams; 10 | result: IBasicAsConstResult; 11 | } 12 | 13 | export type FunctionReturningAsConstParams = [string | null]; 14 | 15 | export interface IFunctionReturningAsConstResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IFunctionReturningAsConstQuery { 21 | params: FunctionReturningAsConstParams; 22 | result: IFunctionReturningAsConstResult; 23 | } 24 | 25 | export type NestedAsConstParams = [number]; 26 | 27 | export interface INestedAsConstResult { 28 | id: number; 29 | name: string; 30 | } 31 | 32 | export interface INestedAsConstQuery { 33 | params: NestedAsConstParams; 34 | result: INestedAsConstResult; 35 | } 36 | 37 | export type AsConstWithTypeAssertionParams = []; 38 | 39 | export interface IAsConstWithTypeAssertionResult { 40 | id: number; 41 | name: string; 42 | } 43 | 44 | export interface IAsConstWithTypeAssertionQuery { 45 | params: AsConstWithTypeAssertionParams; 46 | result: IAsConstWithTypeAssertionResult; 47 | } 48 | -------------------------------------------------------------------------------- /tests/generate_path.rs: -------------------------------------------------------------------------------- 1 | /// Test suites for converting any case to camelCase if generateTypes.convertToCamelCase is true 2 | /// 3 | #[cfg(test)] 4 | mod generate_path_tests { 5 | use assert_cmd::prelude::*; 6 | use std::env; 7 | use std::fs; 8 | use std::io::Write; 9 | use std::path::PathBuf; 10 | use std::process::Command; 11 | use tempfile::tempdir; 12 | 13 | use pretty_assertions::assert_eq; 14 | use test_utils::test_utils::TSString; 15 | use test_utils::{run_test, sandbox::TestConfig}; 16 | 17 | #[rustfmt::skip] 18 | run_test!(should_generate_path, TestConfig::new("postgres", true, Some(PathBuf::from("types/types.ts")), Some(".sqlxrc.camelcase1.json".to_string())), 19 | //// TS query //// 20 | r#" 21 | const someQuery = sql` 22 | SELECT 23 | name, 24 | id AS HelloWorld, 25 | id AS hello_world 26 | FROM items; 27 | ` 28 | "#, 29 | 30 | //// Generated TS interfaces //// 31 | r#" 32 | export type SomeQueryParams = []; 33 | 34 | export interface ISomeQueryResult { 35 | HelloWorld: number; 36 | hello_world: number; 37 | name: string; 38 | } 39 | 40 | export interface ISomeQueryQuery { 41 | params: SomeQueryParams; 42 | result: ISomeQueryResult; 43 | } 44 | "# 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /tests/demo/typescript/expression/as_const.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicAsConstParams = []; 2 | 3 | export interface IBasicAsConstResult { 4 | id: number; 5 | name: string; 6 | } 7 | 8 | export interface IBasicAsConstQuery { 9 | params: BasicAsConstParams; 10 | result: IBasicAsConstResult; 11 | } 12 | 13 | export type FunctionReturningAsConstParams = [string | null]; 14 | 15 | export interface IFunctionReturningAsConstResult { 16 | id: number; 17 | name: string; 18 | } 19 | 20 | export interface IFunctionReturningAsConstQuery { 21 | params: FunctionReturningAsConstParams; 22 | result: IFunctionReturningAsConstResult; 23 | } 24 | 25 | export type NestedAsConstParams = [number]; 26 | 27 | export interface INestedAsConstResult { 28 | id: number; 29 | name: string; 30 | } 31 | 32 | export interface INestedAsConstQuery { 33 | params: NestedAsConstParams; 34 | result: INestedAsConstResult; 35 | } 36 | 37 | export type AsConstWithTypeAssertionParams = []; 38 | 39 | export interface IAsConstWithTypeAssertionResult { 40 | id: number; 41 | name: string; 42 | } 43 | 44 | export interface IAsConstWithTypeAssertionQuery { 45 | params: AsConstWithTypeAssertionParams; 46 | result: IAsConstWithTypeAssertionResult; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/demo/aggregate_functions/conditional_aggregates.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // COUNT with FILTER 4 | const countWithFilter = sql` 5 | -- @name: count with filter 6 | SELECT 7 | rarity, 8 | COUNT(*) FILTER (WHERE id > 5) AS count_above_5, 9 | COUNT(*) FILTER (WHERE id <= 5) AS count_at_or_below_5 10 | FROM items 11 | GROUP BY rarity 12 | ` 13 | 14 | // SUM with FILTER 15 | const sumWithFilter = sql` 16 | -- @name: sum with filter 17 | SELECT 18 | rarity, 19 | SUM(id) FILTER (WHERE id > 5) AS sum_above_5, 20 | SUM(id) FILTER (WHERE id <= 5) AS sum_at_or_below_5 21 | FROM items 22 | GROUP BY rarity 23 | ` 24 | 25 | // AVG with FILTER 26 | const avgWithFilter = sql` 27 | -- @name: avg with filter 28 | SELECT 29 | rarity, 30 | AVG(id) FILTER (WHERE id > 5) AS avg_above_5 31 | FROM items 32 | GROUP BY rarity 33 | ` 34 | 35 | // Multiple FILTER conditions 36 | const multipleFilters = sql` 37 | -- @name: multiple filters 38 | SELECT 39 | COUNT(*) FILTER (WHERE rarity = 'common') AS count_common, 40 | COUNT(*) FILTER (WHERE rarity = 'rare') AS count_rare, 41 | COUNT(*) FILTER (WHERE rarity = 'legendary') AS count_legendary, 42 | COUNT(*) FILTER (WHERE rarity IS NULL) AS count_unknown 43 | FROM items 44 | ` 45 | -------------------------------------------------------------------------------- /tests/demo/postgres/array_operations.queries.ts: -------------------------------------------------------------------------------- 1 | export type ArrayAggBasicParams = []; 2 | 3 | export interface IArrayAggBasicResult { 4 | names: any; 5 | rarity: string | null; 6 | } 7 | 8 | export interface IArrayAggBasicQuery { 9 | params: ArrayAggBasicParams; 10 | result: IArrayAggBasicResult; 11 | } 12 | 13 | export type ArrayAggWithOrderByParams = []; 14 | 15 | export interface IArrayAggWithOrderByResult { 16 | namesOrdered: any; 17 | rarity: string | null; 18 | } 19 | 20 | export interface IArrayAggWithOrderByQuery { 21 | params: ArrayAggWithOrderByParams; 22 | result: IArrayAggWithOrderByResult; 23 | } 24 | 25 | export type ArrayLiteralAnyParams = []; 26 | 27 | export interface IArrayLiteralAnyResult { 28 | id: number; 29 | name: string; 30 | rarity: string | null; 31 | } 32 | 33 | export interface IArrayLiteralAnyQuery { 34 | params: ArrayLiteralAnyParams; 35 | result: IArrayLiteralAnyResult; 36 | } 37 | 38 | export type ArrayWithParamsParams = [Array]; 39 | 40 | export interface IArrayWithParamsResult { 41 | id: number; 42 | name: string; 43 | rarity: string | null; 44 | } 45 | 46 | export interface IArrayWithParamsQuery { 47 | params: ArrayWithParamsParams; 48 | result: IArrayWithParamsResult; 49 | } 50 | -------------------------------------------------------------------------------- /tests/demo/postgres/array_operations.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type ArrayAggBasicParams = []; 2 | 3 | export interface IArrayAggBasicResult { 4 | names: any; 5 | rarity: string | null; 6 | } 7 | 8 | export interface IArrayAggBasicQuery { 9 | params: ArrayAggBasicParams; 10 | result: IArrayAggBasicResult; 11 | } 12 | 13 | export type ArrayAggWithOrderByParams = []; 14 | 15 | export interface IArrayAggWithOrderByResult { 16 | namesOrdered: any; 17 | rarity: string | null; 18 | } 19 | 20 | export interface IArrayAggWithOrderByQuery { 21 | params: ArrayAggWithOrderByParams; 22 | result: IArrayAggWithOrderByResult; 23 | } 24 | 25 | export type ArrayLiteralAnyParams = []; 26 | 27 | export interface IArrayLiteralAnyResult { 28 | id: number; 29 | name: string; 30 | rarity: string | null; 31 | } 32 | 33 | export interface IArrayLiteralAnyQuery { 34 | params: ArrayLiteralAnyParams; 35 | result: IArrayLiteralAnyResult; 36 | } 37 | 38 | export type ArrayWithParamsParams = [Array]; 39 | 40 | export interface IArrayWithParamsResult { 41 | id: number; 42 | name: string; 43 | rarity: string | null; 44 | } 45 | 46 | export interface IArrayWithParamsQuery { 47 | params: ArrayWithParamsParams; 48 | result: IArrayWithParamsResult; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /tests/demo/null_handling/coalesce.queries.ts: -------------------------------------------------------------------------------- 1 | export type CoalesceBasicParams = []; 2 | 3 | export interface ICoalesceBasicResult { 4 | id: number; 5 | name: string; 6 | rarityDisplay: string; 7 | } 8 | 9 | export interface ICoalesceBasicQuery { 10 | params: CoalesceBasicParams; 11 | result: ICoalesceBasicResult; 12 | } 13 | 14 | export type CoalesceMultipleParams = []; 15 | 16 | export interface ICoalesceMultipleResult { 17 | description: string; 18 | id: number; 19 | name: string; 20 | } 21 | 22 | export interface ICoalesceMultipleQuery { 23 | params: CoalesceMultipleParams; 24 | result: ICoalesceMultipleResult; 25 | } 26 | 27 | export type CoalesceNumericParams = []; 28 | 29 | export interface ICoalesceNumericResult { 30 | id: number; 31 | inventoryIdSafe: number; 32 | name: string; 33 | } 34 | 35 | export interface ICoalesceNumericQuery { 36 | params: CoalesceNumericParams; 37 | result: ICoalesceNumericResult; 38 | } 39 | 40 | export type CoalesceWithAggregatesParams = []; 41 | 42 | export interface ICoalesceWithAggregatesResult { 43 | count: number; 44 | rarityGroup: string; 45 | } 46 | 47 | export interface ICoalesceWithAggregatesQuery { 48 | params: CoalesceWithAggregatesParams; 49 | result: ICoalesceWithAggregatesResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/postgres/upsert.queries.ts: -------------------------------------------------------------------------------- 1 | export type UpsertDoNothingParams = [number, string, string | null]; 2 | 3 | export interface IUpsertDoNothingResult { 4 | 5 | } 6 | 7 | export interface IUpsertDoNothingQuery { 8 | params: UpsertDoNothingParams; 9 | result: IUpsertDoNothingResult; 10 | } 11 | 12 | export type UpsertDoUpdateParams = [number, string, string | null]; 13 | 14 | export interface IUpsertDoUpdateResult { 15 | 16 | } 17 | 18 | export interface IUpsertDoUpdateQuery { 19 | params: UpsertDoUpdateParams; 20 | result: IUpsertDoUpdateResult; 21 | } 22 | 23 | export type UpsertWithWhereParams = [number, string, string | null]; 24 | 25 | export interface IUpsertWithWhereResult { 26 | 27 | } 28 | 29 | export interface IUpsertWithWhereQuery { 30 | params: UpsertWithWhereParams; 31 | result: IUpsertWithWhereResult; 32 | } 33 | 34 | export type UpsertWithReturningParams = [number, string, string | null]; 35 | 36 | export interface IUpsertWithReturningResult { 37 | flavorText: string | null; 38 | id: number; 39 | inventoryId: number | null; 40 | name: string; 41 | rarity: string | null; 42 | } 43 | 44 | export interface IUpsertWithReturningQuery { 45 | params: UpsertWithReturningParams; 46 | result: IUpsertWithReturningResult; 47 | } 48 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/case_in_clauses.queries.ts: -------------------------------------------------------------------------------- 1 | export type CaseInWhereParams = []; 2 | 3 | export interface ICaseInWhereResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ICaseInWhereQuery { 10 | params: CaseInWhereParams; 11 | result: ICaseInWhereResult; 12 | } 13 | 14 | export type CaseInOrderByParams = []; 15 | 16 | export interface ICaseInOrderByResult { 17 | id: number; 18 | name: string; 19 | rarity: string | null; 20 | } 21 | 22 | export interface ICaseInOrderByQuery { 23 | params: CaseInOrderByParams; 24 | result: ICaseInOrderByResult; 25 | } 26 | 27 | export type CaseInGroupByHavingParams = []; 28 | 29 | export interface ICaseInGroupByHavingResult { 30 | count: number; 31 | rarityGroup: any; 32 | } 33 | 34 | export interface ICaseInGroupByHavingQuery { 35 | params: CaseInGroupByHavingParams; 36 | result: ICaseInGroupByHavingResult; 37 | } 38 | 39 | export type CaseWithAggregatesParams = []; 40 | 41 | export interface ICaseWithAggregatesResult { 42 | countAbove5: number; 43 | countAtOrBelow5: number; 44 | rarity: string | null; 45 | } 46 | 47 | export interface ICaseWithAggregatesQuery { 48 | params: CaseWithAggregatesParams; 49 | result: ICaseWithAggregatesResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/clauses/distinct.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // DISTINCT basic 4 | const distinctBasic = sql` 5 | -- @name: distinct basic 6 | SELECT DISTINCT rarity FROM items 7 | ` 8 | 9 | // DISTINCT multiple columns 10 | const distinctMultiple = sql` 11 | -- @name: distinct multiple 12 | SELECT DISTINCT rarity, name FROM items 13 | ` 14 | 15 | // DISTINCT with WHERE 16 | const distinctWithWhere = sql` 17 | -- @name: distinct with where 18 | SELECT DISTINCT rarity FROM items 19 | WHERE name IS NOT NULL 20 | ` 21 | 22 | // DISTINCT with parameters 23 | const distinctWithParams = sql` 24 | -- @name: distinct with params 25 | SELECT DISTINCT rarity FROM items 26 | WHERE id > $1 27 | ` 28 | 29 | // DISTINCT ON (PostgreSQL specific) 30 | const distinctOn = sql` 31 | -- @name: distinct on 32 | SELECT DISTINCT ON (rarity) id, rarity, name 33 | FROM items 34 | ORDER BY rarity, id DESC 35 | ` 36 | 37 | // DISTINCT with ORDER BY 38 | const distinctWithOrderBy = sql` 39 | -- @name: distinct with order by 40 | SELECT DISTINCT rarity FROM items 41 | ORDER BY rarity ASC 42 | ` 43 | 44 | // DISTINCT with aggregate 45 | const distinctWithAggregate = sql` 46 | -- @name: distinct with aggregate 47 | SELECT COUNT(DISTINCT rarity) AS unique_rarities FROM items 48 | ` 49 | -------------------------------------------------------------------------------- /tests/demo/clauses/having.queries.ts: -------------------------------------------------------------------------------- 1 | export type HavingBasicParams = []; 2 | 3 | export interface IHavingBasicResult { 4 | count: number; 5 | rarity: string | null; 6 | } 7 | 8 | export interface IHavingBasicQuery { 9 | params: HavingBasicParams; 10 | result: IHavingBasicResult; 11 | } 12 | 13 | export type HavingWithAggregateParams = []; 14 | 15 | export interface IHavingWithAggregateResult { 16 | count: number; 17 | maxId: number; 18 | rarity: string | null; 19 | } 20 | 21 | export interface IHavingWithAggregateQuery { 22 | params: HavingWithAggregateParams; 23 | result: IHavingWithAggregateResult; 24 | } 25 | 26 | export type HavingWithSumParams = []; 27 | 28 | export interface IHavingWithSumResult { 29 | itemsRarity: string | null; 30 | totalQuantity: number; 31 | } 32 | 33 | export interface IHavingWithSumQuery { 34 | params: HavingWithSumParams; 35 | result: IHavingWithSumResult; 36 | } 37 | 38 | export type HavingMultipleConditionsParams = []; 39 | 40 | export interface IHavingMultipleConditionsResult { 41 | avgId: number; 42 | count: number; 43 | rarity: string | null; 44 | } 45 | 46 | export interface IHavingMultipleConditionsQuery { 47 | params: HavingMultipleConditionsParams; 48 | result: IHavingMultipleConditionsResult; 49 | } 50 | -------------------------------------------------------------------------------- /tests/demo/clauses/having.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type HavingBasicParams = []; 2 | 3 | export interface IHavingBasicResult { 4 | count: number; 5 | rarity: string | null; 6 | } 7 | 8 | export interface IHavingBasicQuery { 9 | params: HavingBasicParams; 10 | result: IHavingBasicResult; 11 | } 12 | 13 | export type HavingWithAggregateParams = []; 14 | 15 | export interface IHavingWithAggregateResult { 16 | count: number; 17 | maxId: number; 18 | rarity: string | null; 19 | } 20 | 21 | export interface IHavingWithAggregateQuery { 22 | params: HavingWithAggregateParams; 23 | result: IHavingWithAggregateResult; 24 | } 25 | 26 | export type HavingWithSumParams = []; 27 | 28 | export interface IHavingWithSumResult { 29 | itemsRarity: string | null; 30 | totalQuantity: number; 31 | } 32 | 33 | export interface IHavingWithSumQuery { 34 | params: HavingWithSumParams; 35 | result: IHavingWithSumResult; 36 | } 37 | 38 | export type HavingMultipleConditionsParams = []; 39 | 40 | export interface IHavingMultipleConditionsResult { 41 | avgId: number; 42 | count: number; 43 | rarity: string | null; 44 | } 45 | 46 | export interface IHavingMultipleConditionsQuery { 47 | params: HavingMultipleConditionsParams; 48 | result: IHavingMultipleConditionsResult; 49 | } 50 | -------------------------------------------------------------------------------- /tests/demo/join/multiple_joins.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Mixed JOIN types 4 | const mixedJoinTypes = sql` 5 | -- @name: mixed join types 6 | SELECT items.id, items.name 7 | FROM items 8 | INNER JOIN inventory ON items.inventory_id = inventory.id 9 | LEFT JOIN inventory AS backup ON items.inventory_id = backup.id AND backup.quantity > 0 10 | ` 11 | 12 | // Self JOIN 13 | const selfJoin = sql` 14 | -- @name: self join 15 | SELECT i1.id, i1.name, i2.name AS related_name 16 | FROM items i1 17 | INNER JOIN items i2 ON i1.inventory_id = i2.inventory_id 18 | WHERE i1.id <> i2.id 19 | ` 20 | 21 | // Three-way JOIN 22 | const threeWayJoin = sql` 23 | -- @name: three way join 24 | SELECT items.id, items.name, inventory.quantity 25 | FROM items 26 | INNER JOIN inventory ON items.inventory_id = inventory.id 27 | INNER JOIN characters ON inventory.character_id = characters.id 28 | WHERE characters.level > $1 29 | ` 30 | 31 | // Complex JOIN with parameters 32 | const complexJoinWithParams = sql` 33 | -- @name: complex join with params 34 | SELECT items.id, items.name, inventory.quantity 35 | FROM items 36 | LEFT JOIN inventory ON items.inventory_id = inventory.id 37 | WHERE items.rarity = $1 AND (inventory.quantity IS NULL OR inventory.quantity > $2) 38 | ` 39 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/case_in_clauses.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CaseInWhereParams = []; 2 | 3 | export interface ICaseInWhereResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ICaseInWhereQuery { 10 | params: CaseInWhereParams; 11 | result: ICaseInWhereResult; 12 | } 13 | 14 | export type CaseInOrderByParams = []; 15 | 16 | export interface ICaseInOrderByResult { 17 | id: number; 18 | name: string; 19 | rarity: string | null; 20 | } 21 | 22 | export interface ICaseInOrderByQuery { 23 | params: CaseInOrderByParams; 24 | result: ICaseInOrderByResult; 25 | } 26 | 27 | export type CaseInGroupByHavingParams = []; 28 | 29 | export interface ICaseInGroupByHavingResult { 30 | count: number; 31 | rarityGroup: any; 32 | } 33 | 34 | export interface ICaseInGroupByHavingQuery { 35 | params: CaseInGroupByHavingParams; 36 | result: ICaseInGroupByHavingResult; 37 | } 38 | 39 | export type CaseWithAggregatesParams = []; 40 | 41 | export interface ICaseWithAggregatesResult { 42 | countAbove5: number; 43 | countAtOrBelow5: number; 44 | rarity: string | null; 45 | } 46 | 47 | export interface ICaseWithAggregatesQuery { 48 | params: CaseWithAggregatesParams; 49 | result: ICaseWithAggregatesResult; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/demo/null_handling/coalesce.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CoalesceBasicParams = []; 2 | 3 | export interface ICoalesceBasicResult { 4 | id: number; 5 | name: string; 6 | rarityDisplay: string; 7 | } 8 | 9 | export interface ICoalesceBasicQuery { 10 | params: CoalesceBasicParams; 11 | result: ICoalesceBasicResult; 12 | } 13 | 14 | export type CoalesceMultipleParams = []; 15 | 16 | export interface ICoalesceMultipleResult { 17 | description: string; 18 | id: number; 19 | name: string; 20 | } 21 | 22 | export interface ICoalesceMultipleQuery { 23 | params: CoalesceMultipleParams; 24 | result: ICoalesceMultipleResult; 25 | } 26 | 27 | export type CoalesceNumericParams = []; 28 | 29 | export interface ICoalesceNumericResult { 30 | id: number; 31 | inventoryIdSafe: number; 32 | name: string; 33 | } 34 | 35 | export interface ICoalesceNumericQuery { 36 | params: CoalesceNumericParams; 37 | result: ICoalesceNumericResult; 38 | } 39 | 40 | export type CoalesceWithAggregatesParams = []; 41 | 42 | export interface ICoalesceWithAggregatesResult { 43 | count: number; 44 | rarityGroup: string; 45 | } 46 | 47 | export interface ICoalesceWithAggregatesQuery { 48 | params: CoalesceWithAggregatesParams; 49 | result: ICoalesceWithAggregatesResult; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/demo/postgres/upsert.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type UpsertDoNothingParams = [number, string, string | null]; 2 | 3 | export interface IUpsertDoNothingResult { 4 | 5 | } 6 | 7 | export interface IUpsertDoNothingQuery { 8 | params: UpsertDoNothingParams; 9 | result: IUpsertDoNothingResult; 10 | } 11 | 12 | export type UpsertDoUpdateParams = [number, string, string | null]; 13 | 14 | export interface IUpsertDoUpdateResult { 15 | 16 | } 17 | 18 | export interface IUpsertDoUpdateQuery { 19 | params: UpsertDoUpdateParams; 20 | result: IUpsertDoUpdateResult; 21 | } 22 | 23 | export type UpsertWithWhereParams = [number, string, string | null]; 24 | 25 | export interface IUpsertWithWhereResult { 26 | 27 | } 28 | 29 | export interface IUpsertWithWhereQuery { 30 | params: UpsertWithWhereParams; 31 | result: IUpsertWithWhereResult; 32 | } 33 | 34 | export type UpsertWithReturningParams = [number, string, string | null]; 35 | 36 | export interface IUpsertWithReturningResult { 37 | flavorText: string | null; 38 | id: number; 39 | inventoryId: number | null; 40 | name: string; 41 | rarity: string | null; 42 | } 43 | 44 | export interface IUpsertWithReturningQuery { 45 | params: UpsertWithReturningParams; 46 | result: IUpsertWithReturningResult; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/demo/clauses/limit_offset.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // LIMIT basic 4 | const limitBasic = sql` 5 | -- @name: limit basic 6 | SELECT id, name FROM items 7 | LIMIT 10 8 | ` 9 | 10 | // OFFSET basic 11 | const offsetBasic = sql` 12 | -- @name: offset basic 13 | SELECT id, name FROM items 14 | OFFSET 5 15 | ` 16 | 17 | // LIMIT with OFFSET (pagination) 18 | const limitOffset = sql` 19 | -- @name: limit offset 20 | SELECT id, name FROM items 21 | LIMIT 10 OFFSET 20 22 | ` 23 | 24 | // LIMIT with ORDER BY 25 | const limitWithOrderBy = sql` 26 | -- @name: limit with order by 27 | SELECT id, name FROM items 28 | ORDER BY id DESC 29 | LIMIT 5 30 | ` 31 | 32 | // Pagination with parameters 33 | const paginationWithParams = sql` 34 | -- @name: pagination with params 35 | SELECT id, name, rarity FROM items 36 | WHERE rarity = $1 37 | ORDER BY id ASC 38 | LIMIT $2 OFFSET $3 39 | ` 40 | 41 | // FETCH FIRST (alternative syntax) 42 | const fetchFirst = sql` 43 | -- @name: fetch first 44 | SELECT id, name FROM items 45 | ORDER BY id 46 | FETCH FIRST 10 ROWS ONLY 47 | ` 48 | 49 | // FETCH with OFFSET 50 | const fetchWithOffset = sql` 51 | -- @name: fetch with offset 52 | SELECT id, name FROM items 53 | ORDER BY id 54 | OFFSET 5 ROWS 55 | FETCH NEXT 10 ROWS ONLY 56 | ` 57 | -------------------------------------------------------------------------------- /tests/demo/clauses/order_by.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // ORDER BY single column ASC 4 | const orderByAsc = sql` 5 | -- @name: order by asc 6 | SELECT id, name FROM items 7 | ORDER BY name ASC 8 | ` 9 | 10 | // ORDER BY single column DESC 11 | const orderByDesc = sql` 12 | -- @name: order by desc 13 | SELECT id, name FROM items 14 | ORDER BY id DESC 15 | ` 16 | 17 | // ORDER BY multiple columns 18 | const orderByMultiple = sql` 19 | -- @name: order by multiple 20 | SELECT id, name, rarity FROM items 21 | ORDER BY rarity ASC, name DESC 22 | ` 23 | 24 | // ORDER BY with NULL handling 25 | const orderByNullsFirst = sql` 26 | -- @name: order by nulls first 27 | SELECT id, name, rarity FROM items 28 | ORDER BY rarity NULLS FIRST 29 | ` 30 | 31 | const orderByNullsLast = sql` 32 | -- @name: order by nulls last 33 | SELECT id, name, rarity FROM items 34 | ORDER BY rarity NULLS LAST 35 | ` 36 | 37 | // ORDER BY with expression 38 | const orderByExpression = sql` 39 | -- @name: order by expression 40 | SELECT id, name FROM items 41 | ORDER BY LOWER(name) ASC 42 | ` 43 | 44 | // ORDER BY with parameters in WHERE 45 | const orderByWithParams = sql` 46 | -- @name: order by with params 47 | SELECT id, name, rarity FROM items 48 | WHERE rarity = $1 49 | ORDER BY name ASC 50 | ` 51 | -------------------------------------------------------------------------------- /tests/demo/join/multiple_joins.queries.ts: -------------------------------------------------------------------------------- 1 | export type MixedJoinTypesParams = []; 2 | 3 | export interface IMixedJoinTypesResult { 4 | itemsId: number; 5 | itemsName: string; 6 | } 7 | 8 | export interface IMixedJoinTypesQuery { 9 | params: MixedJoinTypesParams; 10 | result: IMixedJoinTypesResult; 11 | } 12 | 13 | export type SelfJoinParams = []; 14 | 15 | export interface ISelfJoinResult { 16 | itemsId: number; 17 | itemsName: string; 18 | relatedName: string; 19 | } 20 | 21 | export interface ISelfJoinQuery { 22 | params: SelfJoinParams; 23 | result: ISelfJoinResult; 24 | } 25 | 26 | export type ThreeWayJoinParams = [number | null]; 27 | 28 | export interface IThreeWayJoinResult { 29 | inventoryQuantity: number | null; 30 | itemsId: number; 31 | itemsName: string; 32 | } 33 | 34 | export interface IThreeWayJoinQuery { 35 | params: ThreeWayJoinParams; 36 | result: IThreeWayJoinResult; 37 | } 38 | 39 | export type ComplexJoinWithParamsParams = [string | null, number | null]; 40 | 41 | export interface IComplexJoinWithParamsResult { 42 | inventoryQuantity: number | null; 43 | itemsId: number; 44 | itemsName: string; 45 | } 46 | 47 | export interface IComplexJoinWithParamsQuery { 48 | params: ComplexJoinWithParamsParams; 49 | result: IComplexJoinWithParamsResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/join/multiple_joins.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type MixedJoinTypesParams = []; 2 | 3 | export interface IMixedJoinTypesResult { 4 | itemsId: number; 5 | itemsName: string; 6 | } 7 | 8 | export interface IMixedJoinTypesQuery { 9 | params: MixedJoinTypesParams; 10 | result: IMixedJoinTypesResult; 11 | } 12 | 13 | export type SelfJoinParams = []; 14 | 15 | export interface ISelfJoinResult { 16 | itemsId: number; 17 | itemsName: string; 18 | relatedName: string; 19 | } 20 | 21 | export interface ISelfJoinQuery { 22 | params: SelfJoinParams; 23 | result: ISelfJoinResult; 24 | } 25 | 26 | export type ThreeWayJoinParams = [number | null]; 27 | 28 | export interface IThreeWayJoinResult { 29 | inventoryQuantity: number | null; 30 | itemsId: number; 31 | itemsName: string; 32 | } 33 | 34 | export interface IThreeWayJoinQuery { 35 | params: ThreeWayJoinParams; 36 | result: IThreeWayJoinResult; 37 | } 38 | 39 | export type ComplexJoinWithParamsParams = [string | null, number | null]; 40 | 41 | export interface IComplexJoinWithParamsResult { 42 | inventoryQuantity: number | null; 43 | itemsId: number; 44 | itemsName: string; 45 | } 46 | 47 | export interface IComplexJoinWithParamsQuery { 48 | params: ComplexJoinWithParamsParams; 49 | result: IComplexJoinWithParamsResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/aggregate_functions/conditional_aggregates.queries.ts: -------------------------------------------------------------------------------- 1 | export type CountWithFilterParams = []; 2 | 3 | export interface ICountWithFilterResult { 4 | countAbove5: number; 5 | countAtOrBelow5: number; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ICountWithFilterQuery { 10 | params: CountWithFilterParams; 11 | result: ICountWithFilterResult; 12 | } 13 | 14 | export type SumWithFilterParams = []; 15 | 16 | export interface ISumWithFilterResult { 17 | rarity: string | null; 18 | sumAbove5: number; 19 | sumAtOrBelow5: number; 20 | } 21 | 22 | export interface ISumWithFilterQuery { 23 | params: SumWithFilterParams; 24 | result: ISumWithFilterResult; 25 | } 26 | 27 | export type AvgWithFilterParams = []; 28 | 29 | export interface IAvgWithFilterResult { 30 | avgAbove5: number; 31 | rarity: string | null; 32 | } 33 | 34 | export interface IAvgWithFilterQuery { 35 | params: AvgWithFilterParams; 36 | result: IAvgWithFilterResult; 37 | } 38 | 39 | export type MultipleFiltersParams = []; 40 | 41 | export interface IMultipleFiltersResult { 42 | countCommon: number; 43 | countLegendary: number; 44 | countRare: number; 45 | countUnknown: number; 46 | } 47 | 48 | export interface IMultipleFiltersQuery { 49 | params: MultipleFiltersParams; 50 | result: IMultipleFiltersResult; 51 | } 52 | -------------------------------------------------------------------------------- /tests/demo/string_functions/basic_string_functions.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // CONCAT function 4 | const concatFunction = sql` 5 | -- @name: concat function 6 | SELECT 7 | id, 8 | CONCAT(name, ' (', rarity, ')') AS display_name 9 | FROM items 10 | ` 11 | 12 | // UPPER and LOWER functions 13 | const upperLowerFunctions = sql` 14 | -- @name: upper lower functions 15 | SELECT 16 | id, 17 | UPPER(name) AS name_upper, 18 | LOWER(name) AS name_lower 19 | FROM items 20 | ` 21 | 22 | // LENGTH function 23 | const lengthFunction = sql` 24 | -- @name: length function 25 | SELECT 26 | id, 27 | name, 28 | LENGTH(name) AS name_length 29 | FROM items 30 | ` 31 | 32 | // SUBSTRING function 33 | const substringFunction = sql` 34 | -- @name: substring function 35 | SELECT 36 | id, 37 | name, 38 | SUBSTRING(name FROM 1 FOR 3) AS name_prefix 39 | FROM items 40 | ` 41 | 42 | // TRIM functions 43 | const trimFunctions = sql` 44 | -- @name: trim functions 45 | SELECT 46 | id, 47 | TRIM(name) AS name_trimmed, 48 | LTRIM(name) AS name_ltrim, 49 | RTRIM(name) AS name_rtrim 50 | FROM items 51 | ` 52 | 53 | // REPLACE function 54 | const replaceFunction = sql` 55 | -- @name: replace function 56 | SELECT 57 | id, 58 | name, 59 | REPLACE(name, 'a', 'A') AS name_replaced 60 | FROM items 61 | ` 62 | -------------------------------------------------------------------------------- /tests/demo/aggregate_functions/conditional_aggregates.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CountWithFilterParams = []; 2 | 3 | export interface ICountWithFilterResult { 4 | countAbove5: number; 5 | countAtOrBelow5: number; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ICountWithFilterQuery { 10 | params: CountWithFilterParams; 11 | result: ICountWithFilterResult; 12 | } 13 | 14 | export type SumWithFilterParams = []; 15 | 16 | export interface ISumWithFilterResult { 17 | rarity: string | null; 18 | sumAbove5: number; 19 | sumAtOrBelow5: number; 20 | } 21 | 22 | export interface ISumWithFilterQuery { 23 | params: SumWithFilterParams; 24 | result: ISumWithFilterResult; 25 | } 26 | 27 | export type AvgWithFilterParams = []; 28 | 29 | export interface IAvgWithFilterResult { 30 | avgAbove5: number; 31 | rarity: string | null; 32 | } 33 | 34 | export interface IAvgWithFilterQuery { 35 | params: AvgWithFilterParams; 36 | result: IAvgWithFilterResult; 37 | } 38 | 39 | export type MultipleFiltersParams = []; 40 | 41 | export interface IMultipleFiltersResult { 42 | countCommon: number; 43 | countLegendary: number; 44 | countRare: number; 45 | countUnknown: number; 46 | } 47 | 48 | export interface IMultipleFiltersQuery { 49 | params: MultipleFiltersParams; 50 | result: IMultipleFiltersResult; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /book/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "3.7.0", 19 | "@docusaurus/preset-classic": "3.7.0", 20 | "@mdx-js/react": "^3.0.0", 21 | "clsx": "^2.0.0", 22 | "prism-react-renderer": "^2.3.0", 23 | "react": "^19.0.0", 24 | "react-dom": "^19.0.0" 25 | }, 26 | "devDependencies": { 27 | "@docusaurus/module-type-aliases": "3.7.0", 28 | "@docusaurus/tsconfig": "3.7.0", 29 | "@docusaurus/types": "3.7.0", 30 | "typescript": "~5.6.2" 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.5%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 3 chrome version", 40 | "last 3 firefox version", 41 | "last 5 safari version" 42 | ] 43 | }, 44 | "engines": { 45 | "node": ">=18.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/demo/join/left_join.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicLeftJoinParams = []; 2 | 3 | export interface IBasicLeftJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicLeftJoinQuery { 10 | params: BasicLeftJoinParams; 11 | result: IBasicLeftJoinResult; 12 | } 13 | 14 | export type LeftJoinWithWhereParams = [string | null]; 15 | 16 | export interface ILeftJoinWithWhereResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface ILeftJoinWithWhereQuery { 23 | params: LeftJoinWithWhereParams; 24 | result: ILeftJoinWithWhereResult; 25 | } 26 | 27 | export type LeftJoinNullHandlingParams = []; 28 | 29 | export interface ILeftJoinNullHandlingResult { 30 | itemsId: number; 31 | itemsName: string; 32 | quantity: number; 33 | } 34 | 35 | export interface ILeftJoinNullHandlingQuery { 36 | params: LeftJoinNullHandlingParams; 37 | result: ILeftJoinNullHandlingResult; 38 | } 39 | 40 | export type MultipleLeftJoinsParams = []; 41 | 42 | export interface IMultipleLeftJoinsResult { 43 | inventoryQuantity: number | null; 44 | itemsId: number; 45 | itemsName: string; 46 | } 47 | 48 | export interface IMultipleLeftJoinsQuery { 49 | params: MultipleLeftJoinsParams; 50 | result: IMultipleLeftJoinsResult; 51 | } 52 | -------------------------------------------------------------------------------- /tests/demo/join/left_join.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicLeftJoinParams = []; 2 | 3 | export interface IBasicLeftJoinResult { 4 | inventoryQuantity: number | null; 5 | itemsId: number; 6 | itemsName: string; 7 | } 8 | 9 | export interface IBasicLeftJoinQuery { 10 | params: BasicLeftJoinParams; 11 | result: IBasicLeftJoinResult; 12 | } 13 | 14 | export type LeftJoinWithWhereParams = [string | null]; 15 | 16 | export interface ILeftJoinWithWhereResult { 17 | inventoryQuantity: number | null; 18 | itemsId: number; 19 | itemsName: string; 20 | } 21 | 22 | export interface ILeftJoinWithWhereQuery { 23 | params: LeftJoinWithWhereParams; 24 | result: ILeftJoinWithWhereResult; 25 | } 26 | 27 | export type LeftJoinNullHandlingParams = []; 28 | 29 | export interface ILeftJoinNullHandlingResult { 30 | itemsId: number; 31 | itemsName: string; 32 | quantity: number; 33 | } 34 | 35 | export interface ILeftJoinNullHandlingQuery { 36 | params: LeftJoinNullHandlingParams; 37 | result: ILeftJoinNullHandlingResult; 38 | } 39 | 40 | export type MultipleLeftJoinsParams = []; 41 | 42 | export interface IMultipleLeftJoinsResult { 43 | inventoryQuantity: number | null; 44 | itemsId: number; 45 | itemsName: string; 46 | } 47 | 48 | export interface IMultipleLeftJoinsQuery { 49 | params: MultipleLeftJoinsParams; 50 | result: IMultipleLeftJoinsResult; 51 | } 52 | -------------------------------------------------------------------------------- /tests/demo/datetime_functions/time_functions.queries.ts: -------------------------------------------------------------------------------- 1 | export type NowFunctionParams = []; 2 | 3 | export interface INowFunctionResult { 4 | currentTime: string; 5 | currentTimeOnly: string; 6 | id: number; 7 | name: string; 8 | } 9 | 10 | export interface INowFunctionQuery { 11 | params: NowFunctionParams; 12 | result: INowFunctionResult; 13 | } 14 | 15 | export type TimeComparisonParams = []; 16 | 17 | export interface ITimeComparisonResult { 18 | id: number; 19 | loginTime: any | null; 20 | logoutTime: any | null; 21 | name: string; 22 | } 23 | 24 | export interface ITimeComparisonQuery { 25 | params: TimeComparisonParams; 26 | result: ITimeComparisonResult; 27 | } 28 | 29 | export type IntervalOperationsParams = []; 30 | 31 | export interface IIntervalOperationsResult { 32 | createdAt: any | null; 33 | id: number; 34 | name: string; 35 | oneHourLater: number; 36 | thirtyMinutesAgo: number; 37 | } 38 | 39 | export interface IIntervalOperationsQuery { 40 | params: IntervalOperationsParams; 41 | result: IIntervalOperationsResult; 42 | } 43 | 44 | export type DateDifferenceParams = []; 45 | 46 | export interface IDateDifferenceResult { 47 | id: number; 48 | name: string; 49 | sessionDuration: any | null; 50 | } 51 | 52 | export interface IDateDifferenceQuery { 53 | params: DateDifferenceParams; 54 | result: IDateDifferenceResult; 55 | } 56 | -------------------------------------------------------------------------------- /book/docs/connect/environment-variables.md: -------------------------------------------------------------------------------- 1 | # Environment variables 2 | 3 | 4 | | Environment variables | Description | 5 | | --------------------- | ------------------------------------------------------------------------------------------ | 6 | | DB_HOST | Primary DB host | 7 | | DB_PASS | Primary DB password | 8 | | DB_PORT | Primary DB port number | 9 | | DB_TYPE | Type of primary database to connect [default: postgres] [possible values: postgres, mysql] | 10 | | DB_USER | Primary DB user name | 11 | | DB_NAME | Primary DB name | 12 | | PG_SEARCH_PATH | PostgreSQL schema search path (default is "$user,public") [https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) | 13 | 14 | -------------------------------------------------------------------------------- /tests/demo/datetime_functions/time_functions.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type NowFunctionParams = []; 2 | 3 | export interface INowFunctionResult { 4 | currentTime: string; 5 | currentTimeOnly: string; 6 | id: number; 7 | name: string; 8 | } 9 | 10 | export interface INowFunctionQuery { 11 | params: NowFunctionParams; 12 | result: INowFunctionResult; 13 | } 14 | 15 | export type TimeComparisonParams = []; 16 | 17 | export interface ITimeComparisonResult { 18 | id: number; 19 | loginTime: any | null; 20 | logoutTime: any | null; 21 | name: string; 22 | } 23 | 24 | export interface ITimeComparisonQuery { 25 | params: TimeComparisonParams; 26 | result: ITimeComparisonResult; 27 | } 28 | 29 | export type IntervalOperationsParams = []; 30 | 31 | export interface IIntervalOperationsResult { 32 | createdAt: any | null; 33 | id: number; 34 | name: string; 35 | oneHourLater: number; 36 | thirtyMinutesAgo: number; 37 | } 38 | 39 | export interface IIntervalOperationsQuery { 40 | params: IntervalOperationsParams; 41 | result: IIntervalOperationsResult; 42 | } 43 | 44 | export type DateDifferenceParams = []; 45 | 46 | export interface IDateDifferenceResult { 47 | id: number; 48 | name: string; 49 | sessionDuration: any | null; 50 | } 51 | 52 | export interface IDateDifferenceQuery { 53 | params: DateDifferenceParams; 54 | result: IDateDifferenceResult; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /tests/demo/window/row_number.queries.ts: -------------------------------------------------------------------------------- 1 | export type BasicRowNumberParams = []; 2 | 3 | export interface IBasicRowNumberResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | rowNum: any; 8 | } 9 | 10 | export interface IBasicRowNumberQuery { 11 | params: BasicRowNumberParams; 12 | result: IBasicRowNumberResult; 13 | } 14 | 15 | export type RowNumberWithPartitionParams = []; 16 | 17 | export interface IRowNumberWithPartitionResult { 18 | id: number; 19 | name: string; 20 | rarity: string | null; 21 | rowNum: any; 22 | } 23 | 24 | export interface IRowNumberWithPartitionQuery { 25 | params: RowNumberWithPartitionParams; 26 | result: IRowNumberWithPartitionResult; 27 | } 28 | 29 | export type RowNumberWithWhereParams = []; 30 | 31 | export interface IRowNumberWithWhereResult { 32 | id: number; 33 | name: string; 34 | rarity: string | null; 35 | rowNum: any; 36 | } 37 | 38 | export interface IRowNumberWithWhereQuery { 39 | params: RowNumberWithWhereParams; 40 | result: IRowNumberWithWhereResult; 41 | } 42 | 43 | export type RowNumberWithParamsParams = [string | null]; 44 | 45 | export interface IRowNumberWithParamsResult { 46 | id: number; 47 | name: string; 48 | rarity: string | null; 49 | rowNum: any; 50 | } 51 | 52 | export interface IRowNumberWithParamsQuery { 53 | params: RowNumberWithParamsParams; 54 | result: IRowNumberWithParamsResult; 55 | } 56 | -------------------------------------------------------------------------------- /tests/demo/complex_expressions/type_casting.queries.ts: -------------------------------------------------------------------------------- 1 | export type CastFunctionParams = []; 2 | 3 | export interface ICastFunctionResult { 4 | id: number; 5 | idAsBigint: number; 6 | idAsFloat: number; 7 | idAsText: string; 8 | name: string; 9 | } 10 | 11 | export interface ICastFunctionQuery { 12 | params: CastFunctionParams; 13 | result: ICastFunctionResult; 14 | } 15 | 16 | export type PostgresqlCastingParams = []; 17 | 18 | export interface IPostgresqlCastingResult { 19 | id: number; 20 | idAsFloat: number; 21 | idAsText: string; 22 | idAsVarchar: string; 23 | name: string; 24 | } 25 | 26 | export interface IPostgresqlCastingQuery { 27 | params: PostgresqlCastingParams; 28 | result: IPostgresqlCastingResult; 29 | } 30 | 31 | export type CastingWithOperationsParams = []; 32 | 33 | export interface ICastingWithOperationsResult { 34 | id: number; 35 | idDiv3Precise: number; 36 | idFromConcat: number; 37 | name: string; 38 | } 39 | 40 | export interface ICastingWithOperationsQuery { 41 | params: CastingWithOperationsParams; 42 | result: ICastingWithOperationsResult; 43 | } 44 | 45 | export type NullCastingParams = []; 46 | 47 | export interface INullCastingResult { 48 | id: number; 49 | name: string; 50 | nullInt: number; 51 | nullText: string; 52 | } 53 | 54 | export interface INullCastingQuery { 55 | params: NullCastingParams; 56 | result: INullCastingResult; 57 | } 58 | -------------------------------------------------------------------------------- /tests/demo/window/row_number.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type BasicRowNumberParams = []; 2 | 3 | export interface IBasicRowNumberResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | rowNum: any; 8 | } 9 | 10 | export interface IBasicRowNumberQuery { 11 | params: BasicRowNumberParams; 12 | result: IBasicRowNumberResult; 13 | } 14 | 15 | export type RowNumberWithPartitionParams = []; 16 | 17 | export interface IRowNumberWithPartitionResult { 18 | id: number; 19 | name: string; 20 | rarity: string | null; 21 | rowNum: any; 22 | } 23 | 24 | export interface IRowNumberWithPartitionQuery { 25 | params: RowNumberWithPartitionParams; 26 | result: IRowNumberWithPartitionResult; 27 | } 28 | 29 | export type RowNumberWithWhereParams = []; 30 | 31 | export interface IRowNumberWithWhereResult { 32 | id: number; 33 | name: string; 34 | rarity: string | null; 35 | rowNum: any; 36 | } 37 | 38 | export interface IRowNumberWithWhereQuery { 39 | params: RowNumberWithWhereParams; 40 | result: IRowNumberWithWhereResult; 41 | } 42 | 43 | export type RowNumberWithParamsParams = [string | null]; 44 | 45 | export interface IRowNumberWithParamsResult { 46 | id: number; 47 | name: string; 48 | rarity: string | null; 49 | rowNum: any; 50 | } 51 | 52 | export interface IRowNumberWithParamsQuery { 53 | params: RowNumberWithParamsParams; 54 | result: IRowNumberWithParamsResult; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /tests/demo/complex_expressions/mathematical_operations.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // Basic arithmetic operators 4 | const arithmeticOperators = sql` 5 | -- @name: arithmetic operators 6 | SELECT 7 | id, 8 | name, 9 | id + 10 AS id_plus_10, 10 | id - 5 AS id_minus_5, 11 | id * 2 AS id_times_2, 12 | id / 2 AS id_divided_2, 13 | id % 3 AS id_mod_3 14 | FROM items 15 | ` 16 | 17 | // Mathematical functions 18 | const mathFunctions = sql` 19 | -- @name: math functions 20 | SELECT 21 | id, 22 | name, 23 | ABS(id - 10) AS distance_from_10, 24 | POWER(id, 2) AS id_squared, 25 | SQRT(id) AS id_sqrt, 26 | CEIL(id::numeric / 3) AS id_div_3_ceil, 27 | FLOOR(id::numeric / 3) AS id_div_3_floor, 28 | ROUND(id::numeric / 3, 2) AS id_div_3_rounded 29 | FROM items 30 | ` 31 | 32 | // Comparison operators 33 | const comparisonOperators = sql` 34 | -- @name: comparison operators 35 | SELECT 36 | id, 37 | name, 38 | id > 5 AS is_above_5, 39 | id >= 5 AS is_at_least_5, 40 | id < 5 AS is_below_5, 41 | id <= 5 AS is_at_most_5, 42 | id = 5 AS is_exactly_5, 43 | id != 5 AS is_not_5 44 | FROM items 45 | ` 46 | 47 | // BETWEEN and IN operators 48 | const betweenAndIn = sql` 49 | -- @name: between and in 50 | SELECT 51 | id, 52 | name, 53 | rarity, 54 | id BETWEEN 3 AND 7 AS is_in_range, 55 | rarity IN ('common', 'rare') AS is_common_or_rare 56 | FROM items 57 | ` 58 | -------------------------------------------------------------------------------- /tests/demo/complex_expressions/type_casting.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type CastFunctionParams = []; 2 | 3 | export interface ICastFunctionResult { 4 | id: number; 5 | idAsBigint: number; 6 | idAsFloat: number; 7 | idAsText: string; 8 | name: string; 9 | } 10 | 11 | export interface ICastFunctionQuery { 12 | params: CastFunctionParams; 13 | result: ICastFunctionResult; 14 | } 15 | 16 | export type PostgresqlCastingParams = []; 17 | 18 | export interface IPostgresqlCastingResult { 19 | id: number; 20 | idAsFloat: number; 21 | idAsText: string; 22 | idAsVarchar: string; 23 | name: string; 24 | } 25 | 26 | export interface IPostgresqlCastingQuery { 27 | params: PostgresqlCastingParams; 28 | result: IPostgresqlCastingResult; 29 | } 30 | 31 | export type CastingWithOperationsParams = []; 32 | 33 | export interface ICastingWithOperationsResult { 34 | id: number; 35 | idDiv3Precise: number; 36 | idFromConcat: number; 37 | name: string; 38 | } 39 | 40 | export interface ICastingWithOperationsQuery { 41 | params: CastingWithOperationsParams; 42 | result: ICastingWithOperationsResult; 43 | } 44 | 45 | export type NullCastingParams = []; 46 | 47 | export interface INullCastingResult { 48 | id: number; 49 | name: string; 50 | nullInt: number; 51 | nullText: string; 52 | } 53 | 54 | export interface INullCastingQuery { 55 | params: NullCastingParams; 56 | result: INullCastingResult; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /tests/demo/case_expressions/case_in_clauses.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // CASE in WHERE clause 4 | const caseInWhere = sql` 5 | -- @name: case in where 6 | SELECT id, name, rarity 7 | FROM items 8 | WHERE CASE 9 | WHEN rarity = 'legendary' THEN id > 5 10 | WHEN rarity = 'rare' THEN id > 3 11 | ELSE id > 1 12 | END 13 | ` 14 | 15 | // CASE in ORDER BY clause 16 | const caseInOrderBy = sql` 17 | -- @name: case in order by 18 | SELECT id, name, rarity 19 | FROM items 20 | ORDER BY CASE rarity 21 | WHEN 'legendary' THEN 1 22 | WHEN 'rare' THEN 2 23 | WHEN 'common' THEN 3 24 | ELSE 4 25 | END, name 26 | ` 27 | 28 | // CASE in GROUP BY and HAVING 29 | const caseInGroupByHaving = sql` 30 | -- @name: case in group by having 31 | SELECT 32 | CASE 33 | WHEN rarity = 'legendary' THEN 'high' 34 | WHEN rarity = 'rare' THEN 'medium' 35 | ELSE 'low' 36 | END AS rarity_group, 37 | COUNT(*) AS count 38 | FROM items 39 | GROUP BY CASE 40 | WHEN rarity = 'legendary' THEN 'high' 41 | WHEN rarity = 'rare' THEN 'medium' 42 | ELSE 'low' 43 | END 44 | HAVING COUNT(*) > 0 45 | ` 46 | 47 | // CASE with aggregates 48 | const caseWithAggregates = sql` 49 | -- @name: case with aggregates 50 | SELECT 51 | rarity, 52 | SUM(CASE WHEN id > 5 THEN 1 ELSE 0 END) AS count_above_5, 53 | SUM(CASE WHEN id <= 5 THEN 1 ELSE 0 END) AS count_at_or_below_5 54 | FROM items 55 | GROUP BY rarity 56 | ` 57 | -------------------------------------------------------------------------------- /tests/demo/string_functions/pattern_matching.queries.ts: -------------------------------------------------------------------------------- 1 | export type LikeBasicParams = []; 2 | 3 | export interface ILikeBasicResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ILikeBasicQuery { 10 | params: LikeBasicParams; 11 | result: ILikeBasicResult; 12 | } 13 | 14 | export type LikeWithParamParams = [string]; 15 | 16 | export interface ILikeWithParamResult { 17 | id: number; 18 | name: string; 19 | rarity: string | null; 20 | } 21 | 22 | export interface ILikeWithParamQuery { 23 | params: LikeWithParamParams; 24 | result: ILikeWithParamResult; 25 | } 26 | 27 | export type IlikeParams = []; 28 | 29 | export interface IIlikeResult { 30 | id: number; 31 | name: string; 32 | rarity: string | null; 33 | } 34 | 35 | export interface IIlikeQuery { 36 | params: IlikeParams; 37 | result: IIlikeResult; 38 | } 39 | 40 | export type NotLikeParams = []; 41 | 42 | export interface INotLikeResult { 43 | id: number; 44 | name: string; 45 | rarity: string | null; 46 | } 47 | 48 | export interface INotLikeQuery { 49 | params: NotLikeParams; 50 | result: INotLikeResult; 51 | } 52 | 53 | export type SimilarToParams = []; 54 | 55 | export interface ISimilarToResult { 56 | id: number; 57 | name: string; 58 | rarity: string | null; 59 | } 60 | 61 | export interface ISimilarToQuery { 62 | params: SimilarToParams; 63 | result: ISimilarToResult; 64 | } 65 | -------------------------------------------------------------------------------- /tests/demo/delete/delete_returning.queries.ts: -------------------------------------------------------------------------------- 1 | export type DeleteReturningAllParams = [number]; 2 | 3 | export interface IDeleteReturningAllResult { 4 | flavorText: string | null; 5 | id: number; 6 | inventoryId: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IDeleteReturningAllQuery { 12 | params: DeleteReturningAllParams; 13 | result: IDeleteReturningAllResult; 14 | } 15 | 16 | export type DeleteReturningSpecificParams = [number]; 17 | 18 | export interface IDeleteReturningSpecificResult { 19 | id: number; 20 | name: string; 21 | } 22 | 23 | export interface IDeleteReturningSpecificQuery { 24 | params: DeleteReturningSpecificParams; 25 | result: IDeleteReturningSpecificResult; 26 | } 27 | 28 | export type DeleteReturningWithAliasParams = [number]; 29 | 30 | export interface IDeleteReturningWithAliasResult { 31 | deletedId: number; 32 | deletedName: string; 33 | } 34 | 35 | export interface IDeleteReturningWithAliasQuery { 36 | params: DeleteReturningWithAliasParams; 37 | result: IDeleteReturningWithAliasResult; 38 | } 39 | 40 | export type DeleteReturningExpressionParams = [number]; 41 | 42 | export interface IDeleteReturningExpressionResult { 43 | id: number; 44 | upperName: string; 45 | } 46 | 47 | export interface IDeleteReturningExpressionQuery { 48 | params: DeleteReturningExpressionParams; 49 | result: IDeleteReturningExpressionResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/delete/delete_returning.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type DeleteReturningAllParams = [number]; 2 | 3 | export interface IDeleteReturningAllResult { 4 | flavorText: string | null; 5 | id: number; 6 | inventoryId: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IDeleteReturningAllQuery { 12 | params: DeleteReturningAllParams; 13 | result: IDeleteReturningAllResult; 14 | } 15 | 16 | export type DeleteReturningSpecificParams = [number]; 17 | 18 | export interface IDeleteReturningSpecificResult { 19 | id: number; 20 | name: string; 21 | } 22 | 23 | export interface IDeleteReturningSpecificQuery { 24 | params: DeleteReturningSpecificParams; 25 | result: IDeleteReturningSpecificResult; 26 | } 27 | 28 | export type DeleteReturningWithAliasParams = [number]; 29 | 30 | export interface IDeleteReturningWithAliasResult { 31 | deletedId: number; 32 | deletedName: string; 33 | } 34 | 35 | export interface IDeleteReturningWithAliasQuery { 36 | params: DeleteReturningWithAliasParams; 37 | result: IDeleteReturningWithAliasResult; 38 | } 39 | 40 | export type DeleteReturningExpressionParams = [number]; 41 | 42 | export interface IDeleteReturningExpressionResult { 43 | id: number; 44 | upperName: string; 45 | } 46 | 47 | export interface IDeleteReturningExpressionQuery { 48 | params: DeleteReturningExpressionParams; 49 | result: IDeleteReturningExpressionResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/string_functions/pattern_matching.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type LikeBasicParams = []; 2 | 3 | export interface ILikeBasicResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | } 8 | 9 | export interface ILikeBasicQuery { 10 | params: LikeBasicParams; 11 | result: ILikeBasicResult; 12 | } 13 | 14 | export type LikeWithParamParams = [string]; 15 | 16 | export interface ILikeWithParamResult { 17 | id: number; 18 | name: string; 19 | rarity: string | null; 20 | } 21 | 22 | export interface ILikeWithParamQuery { 23 | params: LikeWithParamParams; 24 | result: ILikeWithParamResult; 25 | } 26 | 27 | export type IlikeParams = []; 28 | 29 | export interface IIlikeResult { 30 | id: number; 31 | name: string; 32 | rarity: string | null; 33 | } 34 | 35 | export interface IIlikeQuery { 36 | params: IlikeParams; 37 | result: IIlikeResult; 38 | } 39 | 40 | export type NotLikeParams = []; 41 | 42 | export interface INotLikeResult { 43 | id: number; 44 | name: string; 45 | rarity: string | null; 46 | } 47 | 48 | export interface INotLikeQuery { 49 | params: NotLikeParams; 50 | result: INotLikeResult; 51 | } 52 | 53 | export type SimilarToParams = []; 54 | 55 | export interface ISimilarToResult { 56 | id: number; 57 | name: string; 58 | rarity: string | null; 59 | } 60 | 61 | export interface ISimilarToQuery { 62 | params: SimilarToParams; 63 | result: ISimilarToResult; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /tests/demo/aggregate_functions/basic_aggregates.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // COUNT variants 4 | const countVariants = sql` 5 | -- @name: count variants 6 | SELECT 7 | COUNT(*) AS total_count, 8 | COUNT(id) AS id_count, 9 | COUNT(DISTINCT rarity) AS distinct_rarity_count, 10 | COUNT(rarity) AS non_null_rarity_count 11 | FROM items 12 | ` 13 | 14 | // SUM and AVG 15 | const sumAndAvg = sql` 16 | -- @name: sum and avg 17 | SELECT 18 | rarity, 19 | SUM(id) AS sum_id, 20 | AVG(id) AS avg_id, 21 | AVG(id)::INTEGER AS avg_id_rounded 22 | FROM items 23 | GROUP BY rarity 24 | ` 25 | 26 | // MIN and MAX 27 | const minAndMax = sql` 28 | -- @name: min and max 29 | SELECT 30 | rarity, 31 | MIN(id) AS min_id, 32 | MAX(id) AS max_id, 33 | MIN(name) AS min_name, 34 | MAX(name) AS max_name 35 | FROM items 36 | GROUP BY rarity 37 | ` 38 | 39 | // STDDEV and VARIANCE 40 | const stddevAndVariance = sql` 41 | -- @name: stddev and variance 42 | SELECT 43 | rarity, 44 | STDDEV(id) AS stddev_id, 45 | VARIANCE(id) AS variance_id 46 | FROM items 47 | GROUP BY rarity 48 | HAVING COUNT(*) > 1 49 | ` 50 | 51 | // Multiple aggregates combined 52 | const multipleAggregates = sql` 53 | -- @name: multiple aggregates 54 | SELECT 55 | rarity, 56 | COUNT(*) AS count, 57 | SUM(id) AS sum_id, 58 | AVG(id) AS avg_id, 59 | MIN(id) AS min_id, 60 | MAX(id) AS max_id 61 | FROM items 62 | GROUP BY rarity 63 | ` 64 | -------------------------------------------------------------------------------- /tests/demo/complex_expressions/boolean_logic.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // AND operator 4 | const andOperator = sql` 5 | -- @name: and operator 6 | SELECT id, name, rarity 7 | FROM items 8 | WHERE id > 3 AND rarity = 'common' 9 | ` 10 | 11 | // OR operator 12 | const orOperator = sql` 13 | -- @name: or operator 14 | SELECT id, name, rarity 15 | FROM items 16 | WHERE id < 3 OR rarity = 'legendary' 17 | ` 18 | 19 | // NOT operator 20 | const notOperator = sql` 21 | -- @name: not operator 22 | SELECT id, name, rarity 23 | FROM items 24 | WHERE NOT (rarity = 'common') 25 | ` 26 | 27 | // Combined boolean logic 28 | const combinedBooleanLogic = sql` 29 | -- @name: combined boolean logic 30 | SELECT id, name, rarity 31 | FROM items 32 | WHERE (id > 5 AND rarity = 'common') 33 | OR (id < 3 AND rarity = 'rare') 34 | ` 35 | 36 | // Complex nested conditions 37 | const nestedConditions = sql` 38 | -- @name: nested conditions 39 | SELECT id, name, rarity 40 | FROM items 41 | WHERE ( 42 | (id BETWEEN 1 AND 5 AND rarity IN ('common', 'rare')) 43 | OR 44 | (id > 10 AND rarity IS NOT NULL) 45 | ) 46 | AND name IS NOT NULL 47 | ` 48 | 49 | // Boolean expressions in SELECT 50 | const booleanInSelect = sql` 51 | -- @name: boolean in select 52 | SELECT 53 | id, 54 | name, 55 | rarity, 56 | (id > 5 AND rarity = 'rare') AS is_high_id_rare, 57 | (rarity IN ('legendary', 'epic')) AS is_premium 58 | FROM items 59 | ` 60 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sqlx-ts" 3 | version = "0.35.0" 4 | edition = "2021" 5 | homepage = "https://github.com/JasonShin/sqlx-ts" 6 | authors = ['Jason Shin '] 7 | license = "MIT" 8 | description = "A tool for Javascript/Typescript for compile-time safe SQL queries" 9 | readme = "README.md" 10 | keywords = ["cli", "sql", "sqlx", "typescript", "javascript"] 11 | categories = ["command-line-utilities"] 12 | documentation = "https://jasonshin.github.io/sqlx-ts/" 13 | 14 | [dependencies] 15 | color-eyre = "0.6.5" 16 | thiserror = "2.0.17" 17 | dotenv = "0.15.0" 18 | swc_common = { version = "18.0.0", features = ["tty-emitter"] } 19 | swc_ecma_ast = "19.0.0" 20 | swc_ecma_parser = "28.0.0" 21 | walkdir = "2.5.0" 22 | clap = { version = "3.2.25", features = ["derive"] } 23 | serde = { version = "1.0", features = ["derive"] } 24 | serde_json = { version = "1.0.145" } 25 | sqlparser = { version = "0.59.0" } 26 | regex = { version = "1.12.2" } 27 | convert_case = "0.10.0" 28 | colored = "3.0.0" 29 | mysql_async = { version = "0.36.1", features = ["minimal"] } 30 | tokio-postgres = "0.7.15" 31 | tokio = { version = "1.48.0", features = ["rt-multi-thread", "macros", "default"]} 32 | async-recursion = "1.1.1" 33 | bb8 = "0.9.1" 34 | log = "0.4.22" 35 | 36 | [dev-dependencies] 37 | assert_cmd = "2.1.1" 38 | predicates = "3.1.3" 39 | tempfile = "3.23.0" 40 | test_utils = { path="test-utils" } 41 | pretty_assertions = "1.4.1" 42 | -------------------------------------------------------------------------------- /tests/demo/clauses/group_by.ts: -------------------------------------------------------------------------------- 1 | import { sql } from 'sqlx-ts' 2 | 3 | // GROUP BY single column 4 | const groupBySingle = sql` 5 | -- @name: group by single 6 | SELECT rarity, COUNT(*) AS count 7 | FROM items 8 | GROUP BY rarity 9 | ` 10 | 11 | // GROUP BY multiple columns 12 | const groupByMultiple = sql` 13 | -- @name: group by multiple 14 | SELECT rarity, name, COUNT(*) AS count 15 | FROM items 16 | GROUP BY rarity, name 17 | ` 18 | 19 | // GROUP BY with aggregate functions 20 | const groupByWithAggregates = sql` 21 | -- @name: group by with aggregates 22 | SELECT 23 | rarity, 24 | COUNT(*) AS total_count, 25 | COUNT(inventory_id) AS with_inventory, 26 | MAX(id) AS max_id, 27 | MIN(id) AS min_id 28 | FROM items 29 | GROUP BY rarity 30 | ` 31 | 32 | // GROUP BY with WHERE 33 | const groupByWithWhere = sql` 34 | -- @name: group by with where 35 | SELECT rarity, COUNT(*) AS count 36 | FROM items 37 | WHERE name IS NOT NULL 38 | GROUP BY rarity 39 | ` 40 | 41 | // GROUP BY with parameters 42 | const groupByWithParams = sql` 43 | -- @name: group by with params 44 | SELECT rarity, COUNT(*) AS count 45 | FROM items 46 | WHERE rarity = $1 47 | GROUP BY rarity 48 | ` 49 | 50 | // GROUP BY with JOIN 51 | const groupByWithJoin = sql` 52 | -- @name: group by with join 53 | SELECT items.rarity, SUM(inventory.quantity) AS total_quantity 54 | FROM items 55 | LEFT JOIN inventory ON items.inventory_id = inventory.id 56 | GROUP BY items.rarity 57 | ` 58 | -------------------------------------------------------------------------------- /tests/demo/update/update_returning.queries.ts: -------------------------------------------------------------------------------- 1 | export type UpdateReturningAllParams = [string, number]; 2 | 3 | export interface IUpdateReturningAllResult { 4 | flavorText: string | null; 5 | id: number; 6 | inventoryId: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IUpdateReturningAllQuery { 12 | params: UpdateReturningAllParams; 13 | result: IUpdateReturningAllResult; 14 | } 15 | 16 | export type UpdateReturningSpecificParams = [string, number]; 17 | 18 | export interface IUpdateReturningSpecificResult { 19 | id: number; 20 | name: string; 21 | } 22 | 23 | export interface IUpdateReturningSpecificQuery { 24 | params: UpdateReturningSpecificParams; 25 | result: IUpdateReturningSpecificResult; 26 | } 27 | 28 | export type UpdateReturningWithAliasParams = [string, number]; 29 | 30 | export interface IUpdateReturningWithAliasResult { 31 | updatedId: number; 32 | updatedName: string; 33 | } 34 | 35 | export interface IUpdateReturningWithAliasQuery { 36 | params: UpdateReturningWithAliasParams; 37 | result: IUpdateReturningWithAliasResult; 38 | } 39 | 40 | export type UpdateReturningExpressionParams = [string, number]; 41 | 42 | export interface IUpdateReturningExpressionResult { 43 | id: number; 44 | lowerName: string; 45 | } 46 | 47 | export interface IUpdateReturningExpressionQuery { 48 | params: UpdateReturningExpressionParams; 49 | result: IUpdateReturningExpressionResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/update/update_returning.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type UpdateReturningAllParams = [string, number]; 2 | 3 | export interface IUpdateReturningAllResult { 4 | flavorText: string | null; 5 | id: number; 6 | inventoryId: number | null; 7 | name: string; 8 | rarity: string | null; 9 | } 10 | 11 | export interface IUpdateReturningAllQuery { 12 | params: UpdateReturningAllParams; 13 | result: IUpdateReturningAllResult; 14 | } 15 | 16 | export type UpdateReturningSpecificParams = [string, number]; 17 | 18 | export interface IUpdateReturningSpecificResult { 19 | id: number; 20 | name: string; 21 | } 22 | 23 | export interface IUpdateReturningSpecificQuery { 24 | params: UpdateReturningSpecificParams; 25 | result: IUpdateReturningSpecificResult; 26 | } 27 | 28 | export type UpdateReturningWithAliasParams = [string, number]; 29 | 30 | export interface IUpdateReturningWithAliasResult { 31 | updatedId: number; 32 | updatedName: string; 33 | } 34 | 35 | export interface IUpdateReturningWithAliasQuery { 36 | params: UpdateReturningWithAliasParams; 37 | result: IUpdateReturningWithAliasResult; 38 | } 39 | 40 | export type UpdateReturningExpressionParams = [string, number]; 41 | 42 | export interface IUpdateReturningExpressionResult { 43 | id: number; 44 | lowerName: string; 45 | } 46 | 47 | export interface IUpdateReturningExpressionQuery { 48 | params: UpdateReturningExpressionParams; 49 | result: IUpdateReturningExpressionResult; 50 | } 51 | -------------------------------------------------------------------------------- /tests/demo/window/partition_by.queries.ts: -------------------------------------------------------------------------------- 1 | export type SinglePartitionParams = []; 2 | 3 | export interface ISinglePartitionResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | rarityCount: number; 8 | } 9 | 10 | export interface ISinglePartitionQuery { 11 | params: SinglePartitionParams; 12 | result: ISinglePartitionResult; 13 | } 14 | 15 | export type MultiplePartitionParams = []; 16 | 17 | export interface IMultiplePartitionResult { 18 | countPerGroup: number; 19 | id: number; 20 | name: string; 21 | rarity: string | null; 22 | } 23 | 24 | export interface IMultiplePartitionQuery { 25 | params: MultiplePartitionParams; 26 | result: IMultiplePartitionResult; 27 | } 28 | 29 | export type WindowAggregatesParams = []; 30 | 31 | export interface IWindowAggregatesResult { 32 | avgId: number; 33 | count: number; 34 | id: number; 35 | maxId: number; 36 | minId: number; 37 | name: string; 38 | rarity: string | null; 39 | sumId: number; 40 | } 41 | 42 | export interface IWindowAggregatesQuery { 43 | params: WindowAggregatesParams; 44 | result: IWindowAggregatesResult; 45 | } 46 | 47 | export type WindowWithOrderByParams = []; 48 | 49 | export interface IWindowWithOrderByResult { 50 | id: number; 51 | name: string; 52 | rarity: string | null; 53 | runningSum: number; 54 | } 55 | 56 | export interface IWindowWithOrderByQuery { 57 | params: WindowWithOrderByParams; 58 | result: IWindowWithOrderByResult; 59 | } 60 | -------------------------------------------------------------------------------- /tests/demo/window/partition_by.snapshot.ts: -------------------------------------------------------------------------------- 1 | export type SinglePartitionParams = []; 2 | 3 | export interface ISinglePartitionResult { 4 | id: number; 5 | name: string; 6 | rarity: string | null; 7 | rarityCount: number; 8 | } 9 | 10 | export interface ISinglePartitionQuery { 11 | params: SinglePartitionParams; 12 | result: ISinglePartitionResult; 13 | } 14 | 15 | export type MultiplePartitionParams = []; 16 | 17 | export interface IMultiplePartitionResult { 18 | countPerGroup: number; 19 | id: number; 20 | name: string; 21 | rarity: string | null; 22 | } 23 | 24 | export interface IMultiplePartitionQuery { 25 | params: MultiplePartitionParams; 26 | result: IMultiplePartitionResult; 27 | } 28 | 29 | export type WindowAggregatesParams = []; 30 | 31 | export interface IWindowAggregatesResult { 32 | avgId: number; 33 | count: number; 34 | id: number; 35 | maxId: number; 36 | minId: number; 37 | name: string; 38 | rarity: string | null; 39 | sumId: number; 40 | } 41 | 42 | export interface IWindowAggregatesQuery { 43 | params: WindowAggregatesParams; 44 | result: IWindowAggregatesResult; 45 | } 46 | 47 | export type WindowWithOrderByParams = []; 48 | 49 | export interface IWindowWithOrderByResult { 50 | id: number; 51 | name: string; 52 | rarity: string | null; 53 | runningSum: number; 54 | } 55 | 56 | export interface IWindowWithOrderByQuery { 57 | params: WindowWithOrderByParams; 58 | result: IWindowWithOrderByResult; 59 | } 60 | 61 | --------------------------------------------------------------------------------