diff --git a/docs/docs/about.md b/docs/docs/about.md index 06de478..5be2483 100644 --- a/docs/docs/about.md +++ b/docs/docs/about.md @@ -59,4 +59,4 @@ sq.from('book') { text: 'select * from book where (title in ($1, $2, $3)) or (genre = $4)', args: ['1984', 'Moby Dick', 'Oathbringer', 'Fantasy'] } -``` \ No newline at end of file +``` diff --git a/docs/docs/expressions.md b/docs/docs/expressions.md index 032f892..d2db47e 100644 --- a/docs/docs/expressions.md +++ b/docs/docs/expressions.md @@ -4,14 +4,14 @@ title: Expressions sidebar_label: Expressions --- -* **Values** [`e`](#values), [`e.raw`](#values), [`e.row`](#values), [`e.array`](#values) +* **Values** [`e`](#data), [`e.raw`](#raw), [`e.array`](#array), [`e.json`](#json) * **Logical** [`e.and`](#and), [`e.or`](#or), [`e.not`](#not) * **Comparison** - * **Operators** [`e.eq`](#comparison-operators), [`e.neq`](#comparison-operators), [`e.lt`](#comparison-operators), [`e.gt`](#comparison-operators), [`e.lte`](#comparison-operators), [`e.gte`](#comparison-operators) - * **Between** [`e.between`](#between-not-between), [`e.notBetween`](#not-between) - * **Distinct** [`e.isDistinct`](#is-distinct-is-not-distinct), [`e.isNotDistinct`](#is-distinct-is-not-distinct) - * **Null** [`e.isNull`](#is-null-is-not-null), [`e.isNotNull`](#is-null-is-not-null) - * **Boolean** [`e.true`](#true-not-true-false-not-false-unknown-not-unknown), [`e.notTrue`](#true-not-true-false-not-false-unknown-not-unknown), [`e.false`](#true-not-true-false-not-false-unknown-not-unknown), [`e.notFalse`](#true-not-true-false-not-false-unknown-not-unknown), [`e.unknown`](#true-not-true-false-not-false-unknown-not-unknown), [`e.notUnknown`](#true-not-true-false-not-false-unknown-not-unknown) + * **Operators** [`e.eq`](#operators), [`e.neq`](#operators), [`e.lt`](#operators), [`e.gt`](#operators), [`e.lte`](#operators), [`e.gte`](#operators) + * **Between** [`e.between`](#between), [`e.notBetween`](#between) + * **Distinct** [`e.isDistinctFrom`](#is-distinct-from), [`e.isNotDistinctFrom`](#is-distinct-from) + * **Null** [`e.isNull`](#is-null), [`e.isNotNull`](#is-null) + * **Boolean** [`e.isTrue`](#is-true-is-false-is-unknown), [`e.isNotTrue`](#is-true-is-false-is-unknown), [`e.isFalse`](#is-true-is-false-is-unknown), [`e.isNotFalse`](#is-true-is-false-is-unknown), [`e.isUnknown`](#is-true-is-false-is-unknown), [`e.isNotUnknown`](#is-true-is-false-is-unknown) * **Subquery** [`e.exists`](#exists), [`e.notExists`](#not-exists), [`e.in`](#in), [`e.notIn`](#not-in), [`e.any`](#any), [`e.some`](#some), [`e.all`](#all) * **Row and Array** [`e.in`](#in), [`e.notIn`](#not-in`), [`e.any`](#any), [`e.some`](#some), [`e.all`](#all), [`e.row`](#row), [`e.array`](#array) * **Math** @@ -22,63 +22,153 @@ sidebar_label: Expressions * **String** [`e.concat`](#string-concatenation), [`e.substring`](#substring), [`e.length`](#length), [`e.bitLength`](#bit-length), [`e.charLength`](#charLength), [`e.lower`](#lower), [`e.upper`](#upper), [`e.like`](#like), [`e.notLike`](#not-like), [`e.iLike`](#case-insensitive-like), [`e.notILike`](#case-insensitive-not-like), [`e.similarTo`](#similarTo), [`e.notSimilarTo`](#not-similar-to), [`e.match`](#match), [`e.iMatch`](#case-insensitive-match), [`e.notMatch`](#not-match), [`e.notIMatch`](#case-insensitive-not-match) * **Date/Time** [`e.age`](#age), [`e.now`](#now), [`e.extract`](#extract) +## Introduction + +Builds complex expressions with Sqorn's Expression Builder. + +Access the expression API at `sq.e`. + +Expressions can be nested. + +```js +const { e } = sq + +sq.sql( + e.and( + e.or( + e.lt(3, 4), + e.gt(5, 6) + ), + e.neq(7, 8) + ) + ) + .query + +{ text: '(($1 < $2) or ($3 > $4)) and ($5 <> $6)', + args: [3, 4, 5, 6, 7, 8] } +``` + +Expressions can be chained, curried and called as tagged templates. + +A chained expression's first argument is the previous expression. + +```js +sq.sql( + e(3).lt(4).or(e(5).gt(6)).and(e`7`.neq`8`) + ) + .query + +{ text: '(($1 < $2) or ($3 > $4)) and (7 <> 8)', + args: [3, 4, 5, 6, 7, 8] } +``` + +Expressions are functions that accept values, expressions, fragments and subqueries. + +```js +sq.sql( + e('hello'), + e(e(1)), + e(sq.txt`2`), + e(sq.return`3`) + ) + .query + +{ text: '($1, $2, 2, (select 3))', + args: ['hello', 1] } +``` + +Unless otherwise noted, all expression function can be curried and called as template tags. + +```js +sq.sql( + e.eq(1)(2), + e.gte`count`(3), + e.and(true)`false`(false) + ) + .query + +{ text: '(($1 = $2), (count >= $3), ($4 and (false) and $5))', + args: [1, 2, 3, true, false] } +``` + ## Values -Create expressions from string, number, boolean, null, or JSON values with `.e`. +### Argument + +Create expressions from string, number, boolean, null, or objects with `e`. ```js sq.return( - sq.e('hi'), - sq.e(8), - sq.e(true), - sq.e(null), - sq.e({ a: 1 }) + e('hi'), + e(8), + e(true), + e(null), + e({ a: 1 }) ).query { text: 'select $1, $2, $3, $4', args: ['hi', 8, true, null] } ``` -`.e` accepts raw values, expressions, fragments, and subqueries. +Pass `e` multiple arguments to build a row. ```js -sq.return( - sq.e(sq.raw('1 + 1')), - sq.e(sq.e(7)), - sq.e(sq.txt`'bye'`), - sq.e(sq.sql`select ${8}`), - sq.e(sq.return(sq.e(9))), -).query +sq.sql(e('hello', e.raw('world'), 2)).query -{ text: "select 1 + 1, $1, 'bye', (select $2), (select $3)", - args: [7, 8, 9] } +{ text: '($1, world, $2)', + args: ['hello', 2] } ``` -`.e.eq` builds an equality expression. It accepts two arguments of the same type that `.e` accepts. +Curry `e`. ```js -sq.return( - sq.e.eq(sq.raw('genre'), 'fantasy'), - sq.e.eq('genre', 'history') -).query +sq.sql(e('c')`is``for`('cookies')).query -{ text: 'select genre = $1, $2 = $3' - args: ['fantasy', 'genre', 'history']} +{ text: '($1, is, for, $2)', + args: ['c', 'cookies'] } ``` -`.e.eq` can be curried. Give each argument its own function call or template tag. +### Raw + +`e.raw` interprets its arguments as unparameterized values. ```js -sq.return( - sq.e.eq(sq.raw('genre'))('fantasy'), - sq.e.eq`genre`('history'), - sq.e.eq`genre``${'art'}`, -).query +sq.sql(e.raw('hi')).query -{ text: 'select genre = $1, genre = $2, genre = $3', - args: ['fantasy', 'history', 'art'] } +{ text: 'hi', + args: [] } ``` +Pass `e.raw` multiple arguments to build a row. + +```js +sq.sql(e.raw('hello', e('world'), 2)).query + +{ text: '(hello, $1, 2)', + args: ['world'] } +``` + +Curry `e.raw`. + +```js +sq.sql(e.raw('c')`is``for`('cookies')).query + +{ text: '(c, is, for, cookies)', + args: [] } +``` + +### Array + +`e.array` + +TODO + +### JSON + +`e.json` + +TODO + ## Logical ### And @@ -164,40 +254,132 @@ sq.sql(e.not(e.and(true, true))).query ## Comparison -### Comparison Operators +### Operators + +Build =, <>, <, >, <=, and >= operations with `e.eq`, `e.neq`, `e.lt`, `e.gt`, `e.lte`, `e.gte`. + +Pass two arguments. -Sqorn supports binary comparison operators: +```js +sq.sql( + e.eq(e.raw`title`, 'The Way of Kings'), + e.neq(true, false), + e.lt(4, 8), + e.gt(e.raw('likes'), 1000), + e.lte(3, 4), + e.gte(6, 9), +).query -Method | Operator | Operation ---------|----------|---------------------- -`e.eq` | = | Equal -`e.neq` | <>, != | Not Equal -`e.lt` | < | Less Than -`e.gt` | > | Greater Than -`e.lte` | <= | Less Than or Equal -`e.gte` | >= | Greater Than or Equal +{ text: '((title = $1), ($2 <> $3), ($4 < $5), (likes > $6), ($7 <= $8), ($9 >= $10))', + args: ['The Way of Kings', true, false, 4, 8, 1000, 3, 4, 6, 9] } +``` -Pass exactly two arguments +Curry arguments. -### Between, Not Between +```js +sq.return( + e.eq(sq.raw('genre'))('fantasy'), + e.eq`genre`('history'), + e.eq`genre``${'art'}`, +).query -TODO +{ text: 'select genre = $1, genre = $2, genre = $3', + args: ['fantasy', 'history', 'art'] } +``` -### Is Distinct, Is Not Distinct +### Between -TODO +`e.between` and `e.notBetween` check if a value is between two others. -### Is Null, Is Not Null +```js +sq.sql(e.between(5, 1, 10)).query -TODO +{ text: '$1 between $2 and $3', + args: [5, 1, 10] } +``` -### True, Not True, False, Not False, Unknown, Not Unknown +Curry arguments. -TODO +```js +sq.sql(e(5).notBetween`7`(10)).query + +{ text: '$1 not between 7 and $3', + args: [5, 10] } +``` + +### Is Distinct From + +`e.isDistinctFrom` and `e.isNotDistinctFrom` compare two arguments for equivalence. + +Expression | Result +-|- +null = null | null +null <> null | null +null is distinct from null | false +null is not distinct from null | true + +```js +sq.sql(e.isDistinctFrom(null, null)).query + +{ text: '$1 is distinct from $1', + args: [null, null] } +``` + +Curry arguments. + +```js +sq.sql(e(3).isNotDistinctFrom`4`) + +{ text: '$1 is not distinct from 4', + args: [3] } +``` + +### Is Null + +`e.isNull` and `e.isNotNull` check if a value is null. If the argument is a row, they check if the row is null or all of its fields are null. + + +```js +sq.sql(e.isNull(null), e`moo`.isNotNull) + +{ text: '($1 is null, moo is not null)', + args: [null] } +``` + +### Is True, Is False, Is Unknown + +`e.isTrue`, `.isNotTrue`, `e.isNotFalse`, `e.isNotFalse`, `e.isUnknown`, and `e.isNotUnknown` are unary comparison expressions. + +```js +sq.sql( + e.isTrue(true), + e(true).isNotTrue, + e.isFalse(null) + e.isNotFalse`moo`, + e(null).isUnknown, + e`moo`.isNotUnknown + ) + .query + +{ text: '($1 is true, $2 is not true, $3 is false, moo is not false, $4 is unknown, moo is not unknown)', + args: [true, true, null, null] } +``` + +`e.isUnknown` and `e.isNotUnknown` require boolean arguments but are otherwise equivalent to `e.isNull` and `e.isNotNull`. ## Math -TODO +### Operators + +Build +, -, *, /, and % (modulus) operations with `e.add`, `e.subtract`, `e.multiply`, and `e.divide`. + +```js + +{ text: '', + args: [] } +``` + + ## String diff --git a/docs/docs/manual_queries.md b/docs/docs/manual_queries.md index 00dd6c4..c300afd 100644 --- a/docs/docs/manual_queries.md +++ b/docs/docs/manual_queries.md @@ -7,7 +7,7 @@ sidebar_label: Manual Queries * **Build** [`.sql`](#sql-queries), [`.raw`](#sql-queries), [`.txt`](#text-fragments), [`.extend`](#extend), [`.link`](#link) * **Compile** [`.query`](#sql-queries), [`.unparameterized`](#sql-queries). -## SQL Queries +## Queries Build SQL queries manually with `.sql`. @@ -118,9 +118,18 @@ sq.sql`select * from` args: [20] } ``` +TODO: Pass `.sql` multiple arguments to build a row. + +```js +sq.sql`select`.sql(2, 4, 8).query + +{ text: 'select ($1, $2, $3)', + args: [2, 4, 8] } +``` + Use `.sql` to build *complete* queries, not fragments. -## Text Fragments +## Fragments Build query fragments with `.txt`. Sqorn does not automatically paranthesize embedded fragments. diff --git a/packages/sqorn-pg/types/expressions.d.ts b/packages/sqorn-pg/types/expressions.d.ts new file mode 100644 index 0000000..94e45e7 --- /dev/null +++ b/packages/sqorn-pg/types/expressions.d.ts @@ -0,0 +1,364 @@ +type TypeExpressionMap = { + new: NewExpression + unknown: UnknownExpression + boolean: BooleanExpression + number: NumberExpression + row: RowExpression + subquery: SubqueryExpression +} +type TypePrimitiveMap = { + new: never + unknown: null + boolean: boolean + number: number + row: never + subquery: never +} +type TypeInferenceMap = { + [key in Types]: TypeExpressionMap[key] | TypePrimitiveMap[key] +} +type TypeCompatibilityMap = { + new: never + unknown: Arg + boolean: null | TypeInferenceMap['boolean'] + number: null | TypeInferenceMap['number'] + row: null | TypeInferenceMap['row'] + subquery: TypeInferenceMap['subquery'] +} +type Types = keyof TypeExpressionMap +type ExpressionTypes = TypeExpressionMap[Types] +type PrimitiveTypes = TypePrimitiveMap[Types] +type Arg = ExpressionTypes | PrimitiveTypes + +type Compatible = TypeCompatibilityMap[T] +type Infer = + T extends TypeInferenceMap['new'] ? 'new' : + T extends TypeInferenceMap['unknown'] ? 'unknown' : + T extends TypeInferenceMap['boolean'] ? 'boolean' : + T extends TypeInferenceMap['number'] ? 'number' : + T extends TypeInferenceMap['row'] ? 'row' : + T extends TypeInferenceMap['subquery'] ? 'subquery' : + never +type InferCompatible = Compatible> +type InferExpression = TypeExpressionMap[Infer] +type tmp = Infer +type UnknownArgument = TypeCompatibilityMap['unknown'] +type BooleanArgument = TypeCompatibilityMap['boolean'] +type NumberArgument = TypeCompatibilityMap['number'] +type RowArgument = TypeCompatibilityMap['row'] +type SubqueryArgument = TypeCompatibilityMap['subquery'] + +interface Expression { + type: Types + _build(): string +} + +// +// Expressions +// + +interface AnyExpression extends + Expression, + ArgOperators, + LogicalOperators, + ComparisonOperators, + NumberOperators, + SubqueryOperators { type: T } + +interface NewExpression extends AnyExpression<'new'> {} + +interface UnknownExpression extends AnyExpression<'unknown'> {} + +interface BooleanExpression extends + Expression, + LogicalOperators<'boolean'>, + ComparisonOperators<'boolean'> { type: 'boolean' } + +interface NumberExpression extends + Expression, + NumberOperators<'number'>, + ComparisonOperators<'number'> { type: 'number' } + +interface RowExpression extends + Expression { type: 'row' } + +interface SubqueryExpression extends + Expression, + SubqueryOperators<'subquery'> { type: 'subquery' } + +// +// Operators +// + +interface ArgOperators { + (arg: T): InferExpression + (strings: TemplateStringsArray, ...args: any[]): UnknownExpression + // (...args: any): RowExpression +} + +// +// Logical Operators +// + +interface LogicalOperators { + and: T extends 'new' ? And : AndChain + or: T extends 'new' ? Or : OrChain + not: T extends 'new' ? Not : BooleanExpression +} + +interface And { + (...args: BooleanArgument[]): AndChain +} +interface AndChain extends And, BooleanExpression {} + +interface Or { + (...args: BooleanArgument[]): OrChain +} +interface OrChain extends Or, BooleanExpression {} + +interface Not { + (arg: BooleanArgument): BooleanExpression +} + +// +// Comparison Operators +// + +interface ComparisonOperators { + // binary + eq: T extends 'new' ? Eq : EqChain + neq: T extends 'new' ? Neq : NeqChain + lt: T extends 'new' ? Lt : LtChain + gt: T extends 'new' ? Gt : GtChain + lte: T extends 'new' ? Lte : LteChain + gte: T extends 'new' ? Gte : GteChain + // ternary + between: T extends 'new' ? Between : BetweenChain1 + notBetween: T extends 'new' ? NotBetween : NotBetweenChain1 + // subquery / row / array + in: T extends 'new' ? In : InChain + notIn: T extends 'new' ? NotIn : NotInChain + any: T extends 'new' ? Any : AnyChain + some: T extends 'new' ? Some : SomeChain + all: T extends 'new' ? All : AllChain +} + +interface Eq { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): EqChain> + (text: TemplateStringsArray, ...args: any[]): EqChain<'unknown'> +} +interface EqChain { + (arg2: Compatible): BooleanExpression + (text: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Neq { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): NeqChain> + (strings: TemplateStringsArray, ...args: any[]): NeqChain<'unknown'> +} +interface NeqChain { + (arg2: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Lt { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): LtChain> + (strings: TemplateStringsArray, ...args: any[]): LtChain<'unknown'> +} +interface LtChain { + (arg2: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Gt { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): GtChain> + (strings: TemplateStringsArray, ...args: any[]): GtChain<'unknown'> +} +interface GtChain { + (arg2: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Lte { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): LteChain> + (strings: TemplateStringsArray, ...args: any[]): LteChain<'unknown'> +} +interface LteChain { + (arg2: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Gte { + (arg1: T, arg2: InferCompatible): BooleanExpression + (arg1: T): GteChain> + (strings: TemplateStringsArray, ...args: any[]): GteChain<'unknown'> +} +interface GteChain { + (arg2: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface Between { + (arg1: T, arg2: InferCompatible, arg3: InferCompatible): BooleanExpression + (arg1: T, arg2: InferCompatible): BetweenChain2> + (arg1: T): BetweenChain1> + (strings: TemplateStringsArray, ...args: any[]): BetweenChain1<'unknown'> +} +interface BetweenChain1 { + (arg2: Compatible, arg3: Compatible): BooleanExpression + (arg2: Compatible): BetweenChain2 + (strings: TemplateStringsArray, ...args: any[]): BetweenChain2 +} +interface BetweenChain2 { + (arg3: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface NotBetween { + (arg1: T, arg2: InferCompatible, arg3: InferCompatible): BooleanExpression + (arg1: T, arg2: InferCompatible): NotBetweenChain2> + (arg1: T): NotBetweenChain1> + (strings: TemplateStringsArray, ...args: any[]): NotBetweenChain1<'unknown'> +} +interface NotBetweenChain1 { + (arg2: Compatible, arg3: Compatible): BooleanExpression + (arg2: Compatible): NotBetweenChain2 + (strings: TemplateStringsArray, ...args: any[]): NotBetweenChain2 +} +interface NotBetweenChain2 { + (arg3: Compatible): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface In { + // Subquery + (arg1: T, arg2: SubqueryArgument): BooleanExpression + (arg1: T): InChain> + (text: TemplateStringsArray, ...args: any[]): InChain<'unknown'> + // Values List + (arg1: T, arg2: InferCompatible[]): BooleanExpression +} +interface InChain { + // Subquery + (arg2: SubqueryArgument): BooleanExpression + (text: TemplateStringsArray, ...args: any[]): BooleanExpression + // Values List + (arg2: Compatible[]): BooleanExpression +} + +interface NotIn { + // Subquery + (arg1: T, arg2: SubqueryArgument): BooleanExpression + (arg1: T): NotInChain> + (text: TemplateStringsArray, ...args: any[]): NotInChain<'unknown'> + // Values List + (arg1: T, arg2: InferCompatible[]): BooleanExpression +} +interface NotInChain { + // Subquery + (arg2: SubqueryArgument): BooleanExpression + (text: TemplateStringsArray, ...args: any[]): BooleanExpression + // Values List + (arg2: Compatible[]): BooleanExpression +} + +interface Any { + // Subquery + (arg1: T, arg2: SubqueryArgument): BooleanExpression + (arg1: T): AnyChain> + (text: TemplateStringsArray, ...args: any[]): AnyChain<'unknown'> + // Values List +} +interface AnyChain { + // Subquery + (arg2: SubqueryArgument): BooleanExpression + (text: TemplateStringsArray, ...args: any[]): BooleanExpression + // Values List +} + +interface Some { + // Subquery + (arg1: T, arg2: SubqueryArgument): BooleanExpression + (arg1: T): SomeChain> + (text: TemplateStringsArray, ...args: Some[]): SomeChain<'unknown'> + // Values List +} +interface SomeChain { + // Subquery + (arg2: SubqueryArgument): BooleanExpression + (text: TemplateStringsArray, ...args: Some[]): BooleanExpression + // Values List +} + +interface All { + // Subquery + (arg1: T, arg2: SubqueryArgument): BooleanExpression + (arg1: T): AllChain> + (text: TemplateStringsArray, ...args: All[]): AllChain<'unknown'> + // Values List +} +interface AllChain { + // Subquery + (arg2: SubqueryArgument): BooleanExpression + (text: TemplateStringsArray, ...args: All[]): BooleanExpression + // Values List +} + +// +// Number Operators +// + +interface NumberOperators { + add: T extends 'new' ? Add : AddChain + subtract: T extends 'new' ? Subtract : SubtractChain + multiply: T extends 'new' ? Multiply : MultiplyChain + divide: T extends 'new' ? Divide : DivideChain +} + +interface Add { + (...args: NumberArgument[]): AddChain + (strings: TemplateStringsArray, ...args: any[]): AddChain +} +interface AddChain extends Add, NumberExpression {} + +interface Subtract { + (...args: NumberArgument[]): SubtractChain + (strings: TemplateStringsArray, ...args: any[]): SubtractChain +} +interface SubtractChain extends Subtract, NumberExpression {} + +interface Multiply { + (...args: NumberArgument[]): MultiplyChain + (strings: TemplateStringsArray, ...args: any[]): MultiplyChain +} +interface MultiplyChain extends Multiply, NumberExpression {} + +interface Divide { + (...args: NumberArgument[]): DivideChain + (strings: TemplateStringsArray, ...args: any[]): DivideChain +} +interface DivideChain extends Divide, NumberExpression {} + +// +// Subquery Operators +// + +interface SubqueryOperators { + exists: T extends 'new' ? ExistsSubquery : BooleanExpression + notExists: T extends 'new' ? NotExistsSubquery : BooleanExpression +} + +interface ExistsSubquery { + (arg: SubqueryArgument): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} + +interface NotExistsSubquery { + (arg: SubqueryArgument): BooleanExpression + (strings: TemplateStringsArray, ...args: any[]): BooleanExpression +} diff --git a/packages/sqorn-pg/types/test.ts b/packages/sqorn-pg/types/test.ts new file mode 100644 index 0000000..956ba61 --- /dev/null +++ b/packages/sqorn-pg/types/test.ts @@ -0,0 +1,58 @@ +declare let e: NewExpression; + +const a1 = e.and(true) +const a2 = a1(true) +const b1 = e.or(true, false) +const b2 = e.or(true, null) +const b3 = e.not(true) + +const c1 = e(true).and(e.not(true).or(false)) +const c2 = e(true).and(false).eq(true) +const c3 = e.add + +const d1 = e.add(null)(true).eq(null) +const d2 = e.eq(1, 8) +const d3 = e.eq(e.not(true), e.and(true, false)) +const d4 = e.eq(true, e.not(true)) + +const e1 = e.eq(null, null) +const e2 = e.eq(null, 2) +const e3 = e.eq(2, null) +const e4 = e.eq(1) + +const f1 = e.subtract(e.add(3, 4), 23).add(23).divide(null) +const f2 = e.add(2, 3, 4).subtract(4, 5, 6) + +const g1 = e.and(true, false)(true)(false)(e.eq(2,3), null) + +const h1 = e.lt(3, 4).and(true).gt(false) +const h2 = e(true).gt(false).and(true) +const h3 = e(1).gt(3) + +const i1 = e.neq(null, 2) + +const j1 = e.between(3, 4, 5) +const j2 = j1.notBetween(true, false).between(true)(false).gte(false) +const j3 = e.between`b`(2, true) +const j4 = e.between(2)`b`(false); + +const k1 = e.eq(98)`n` +const k2 = e.eq`n`(98) + + +declare let subquery: SubqueryExpression +const l1 = e.exists(subquery) +const l2 = e(subquery).exists +const l3 = e(null) +const l4 = e(null).notExists + +const m1 = e(3).in(subquery) +const m2 = e.notIn(null, subquery) +const m3 = e.any(3, subquery).some(subquery) +const m4 = e.all(2, subquery).all(23) + +const n1 = e.in(3, [1, e.add(3, 4), null, 34]) +const n2 = e(true).in([null, true, false, e.eq(1, 2)]) +const n3 = e(null).in([1, 2, 3, null, false]).in([]).notIn([true]) +const n4 = e.notIn(3, [1, 2, 3]) +const n5 = e(true).notIn([false, e(true), null]) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b4ef1f4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "compilerOptions": {"strictNullChecks":true} +} \ No newline at end of file