diff --git a/src/expr-library/decimal/acos.ts b/src/expr-library/decimal/acos.ts.deprecated similarity index 100% rename from src/expr-library/decimal/acos.ts rename to src/expr-library/decimal/acos.ts.deprecated diff --git a/src/expr-library/decimal/asin.ts b/src/expr-library/decimal/asin.ts.deprecated similarity index 100% rename from src/expr-library/decimal/asin.ts rename to src/expr-library/decimal/asin.ts.deprecated diff --git a/src/expr-library/decimal/atan.ts b/src/expr-library/decimal/atan.ts.deprecated similarity index 100% rename from src/expr-library/decimal/atan.ts rename to src/expr-library/decimal/atan.ts.deprecated diff --git a/src/expr-library/decimal/atan2.ts b/src/expr-library/decimal/atan2.ts.deprecated similarity index 100% rename from src/expr-library/decimal/atan2.ts rename to src/expr-library/decimal/atan2.ts.deprecated diff --git a/src/expr-library/decimal/cbrt.ts b/src/expr-library/decimal/cbrt.ts.deprecated similarity index 100% rename from src/expr-library/decimal/cbrt.ts rename to src/expr-library/decimal/cbrt.ts.deprecated diff --git a/src/expr-library/decimal/cos.ts b/src/expr-library/decimal/cos.ts.deprecated similarity index 100% rename from src/expr-library/decimal/cos.ts rename to src/expr-library/decimal/cos.ts.deprecated diff --git a/src/expr-library/decimal/cot.ts b/src/expr-library/decimal/cot.ts.deprecated similarity index 100% rename from src/expr-library/decimal/cot.ts rename to src/expr-library/decimal/cot.ts.deprecated diff --git a/src/expr-library/decimal/degrees.ts b/src/expr-library/decimal/degrees.ts.deprecated similarity index 100% rename from src/expr-library/decimal/degrees.ts rename to src/expr-library/decimal/degrees.ts.deprecated diff --git a/src/expr-library/decimal/fractional-div.ts b/src/expr-library/decimal/fractional-div.ts index f92740e8..89e5eff2 100644 --- a/src/expr-library/decimal/fractional-div.ts +++ b/src/expr-library/decimal/fractional-div.ts @@ -5,7 +5,7 @@ import {Decimal} from "../../decimal"; import {makeOperator2} from "../factory"; /** - * Performs regular floating-point division + * Performs regular fixed-point division */ export const fractionalDiv = makeOperator2( OperatorType.FRACTIONAL_DIVISION, diff --git a/src/expr-library/decimal/index.ts b/src/expr-library/decimal/index.ts index f70f12bc..14f347ec 100644 --- a/src/expr-library/decimal/index.ts +++ b/src/expr-library/decimal/index.ts @@ -1,16 +1,16 @@ export * from "./aggregate"; export * from "./abs"; -export * from "./acos"; +//export * from "./acos"; export * from "./add"; -export * from "./asin"; -export * from "./atan"; -export * from "./atan2"; -export * from "./cbrt"; +//export * from "./asin"; +//export * from "./atan"; +//export * from "./atan2"; +//export * from "./cbrt"; export * from "./ceiling"; -export * from "./cos"; -export * from "./cot"; -export * from "./degrees"; +//export * from "./cos"; +//export * from "./cot"; +//export * from "./degrees"; export * from "./exp"; export * from "./floor"; export * from "./fractional-div"; @@ -18,22 +18,22 @@ export * from "./fractional-div"; * PostgreSQL and SQLite do not support fractional remainder `frem(x, y)` */ //export * from "./fractional-remainder"; -export * from "./integer-div"; -export * from "./integer-remainder"; +//export * from "./integer-div"; +//export * from "./integer-remainder"; export * from "./ln"; export * from "./log"; export * from "./log2"; export * from "./log10"; export * from "./mul"; export * from "./neg"; -export * from "./pi"; +//export * from "./pi"; export * from "./power"; -export * from "./radians"; +//export * from "./radians"; export * from "./random"; //export * from "./round"; export * from "./sign"; -export * from "./sin"; +//export * from "./sin"; export * from "./sqrt"; export * from "./sub"; -export * from "./tan"; +//export * from "./tan"; //export * from "./truncate"; diff --git a/src/expr-library/decimal/integer-div.ts b/src/expr-library/decimal/integer-div.ts.deprecated similarity index 100% rename from src/expr-library/decimal/integer-div.ts rename to src/expr-library/decimal/integer-div.ts.deprecated diff --git a/src/expr-library/decimal/integer-remainder.ts b/src/expr-library/decimal/integer-remainder.ts.deprecated similarity index 100% rename from src/expr-library/decimal/integer-remainder.ts rename to src/expr-library/decimal/integer-remainder.ts.deprecated diff --git a/src/expr-library/decimal/pi.ts b/src/expr-library/decimal/pi.ts.deprecated similarity index 100% rename from src/expr-library/decimal/pi.ts rename to src/expr-library/decimal/pi.ts.deprecated diff --git a/src/expr-library/decimal/radians.ts b/src/expr-library/decimal/radians.ts.deprecated similarity index 100% rename from src/expr-library/decimal/radians.ts rename to src/expr-library/decimal/radians.ts.deprecated diff --git a/src/expr-library/decimal/sin.ts b/src/expr-library/decimal/sin.ts.deprecated similarity index 100% rename from src/expr-library/decimal/sin.ts rename to src/expr-library/decimal/sin.ts.deprecated diff --git a/src/expr-library/decimal/tan.ts b/src/expr-library/decimal/tan.ts.deprecated similarity index 100% rename from src/expr-library/decimal/tan.ts rename to src/expr-library/decimal/tan.ts.deprecated diff --git a/src/expr-library/double/aggregate/avg.ts b/src/expr-library/double/aggregate/avg.ts index db8f481e..0c0dde40 100644 --- a/src/expr-library/double/aggregate/avg.ts +++ b/src/expr-library/double/aggregate/avg.ts @@ -5,14 +5,33 @@ import {makeAggregateOperator2, AggregateOperator1} from "../../aggregate-factor import {BuiltInExpr_NonAggregate} from "../../../built-in-expr"; import {ExprUtil} from "../../../expr"; -const avgImpl = makeAggregateOperator2( +const avgImpl = makeAggregateOperator2( OperatorType.AGGREGATE_AVERAGE, tm.mysql.double().orNull(), TypeHint.DOUBLE ); -export const avgDistinct : AggregateOperator1 = < - ArgT extends BuiltInExpr_NonAggregate +/** + * Returns the average value of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_avg + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#avg + * + * ----- + * + * + MySQL : `AVG(DISTINCT x)` + * + PostgreSQL : `AVG(DISTINCT x)` + * + SQLite : `AVG(DISTINCT x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ +export const avgDistinct : AggregateOperator1 = < + ArgT extends BuiltInExpr_NonAggregate >( arg : ArgT ) : ( @@ -21,8 +40,27 @@ export const avgDistinct : AggregateOperator1 = < return avgImpl(true, arg) as ExprUtil.AggregateIntersect; }; -export const avgAll : AggregateOperator1 = < - ArgT extends BuiltInExpr_NonAggregate +/** + * Returns the average value of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_avg + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#avg + * + * ----- + * + * + MySQL : `AVG(x)` + * + PostgreSQL : `AVG(x)` + * + SQLite : `AVG(x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ +export const avgAll : AggregateOperator1 = < + ArgT extends BuiltInExpr_NonAggregate >( arg : ArgT ) : ( @@ -31,4 +69,23 @@ export const avgAll : AggregateOperator1 = < return avgImpl(false, arg) as ExprUtil.AggregateIntersect; }; +/** + * Returns the average value of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_avg + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#avg + * + * ----- + * + * + MySQL : `AVG(x)` + * + PostgreSQL : `AVG(x)` + * + SQLite : `AVG(x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ export const avg = avgAll; diff --git a/src/expr-library/double/aggregate/sum.ts b/src/expr-library/double/aggregate/sum.ts index 334637cc..62712a3f 100644 --- a/src/expr-library/double/aggregate/sum.ts +++ b/src/expr-library/double/aggregate/sum.ts @@ -5,14 +5,33 @@ import {makeAggregateOperator2, AggregateOperator1} from "../../aggregate-factor import {BuiltInExpr_NonAggregate} from "../../../built-in-expr"; import {ExprUtil} from "../../../expr"; -const sumImpl = makeAggregateOperator2( +const sumImpl = makeAggregateOperator2( OperatorType.AGGREGATE_SUM, tm.mysql.double().orNull(), TypeHint.DOUBLE ); -export const sumDistinct : AggregateOperator1 = < - ArgT extends BuiltInExpr_NonAggregate +/** + * Returns the total sum of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_sum + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#sumunc + * + * ----- + * + * + MySQL : `SUM(DISTINCT x)` + * + PostgreSQL : `SUM(DISTINCT x)` + * + SQLite : `SUM(DISTINCT x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ +export const sumDistinct : AggregateOperator1 = < + ArgT extends BuiltInExpr_NonAggregate >( arg : ArgT ) : ( @@ -21,8 +40,27 @@ export const sumDistinct : AggregateOperator1 = < return sumImpl(true, arg) as ExprUtil.AggregateIntersect; }; -export const sumAll : AggregateOperator1 = < - ArgT extends BuiltInExpr_NonAggregate +/** + * Returns the total sum of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_sum + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#sumunc + * + * ----- + * + * + MySQL : `SUM(x)` + * + PostgreSQL : `SUM(x)` + * + SQLite : `SUM(x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ +export const sumAll : AggregateOperator1 = < + ArgT extends BuiltInExpr_NonAggregate >( arg : ArgT ) : ( @@ -31,4 +69,23 @@ export const sumAll : AggregateOperator1 = < return sumImpl(false, arg) as ExprUtil.AggregateIntersect; }; +/** + * Returns the total sum of non-`NULL` values from a group. + * + * It returns `NULL` if there are no non-`NULL` values. + * + * + https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_sum + * + https://www.postgresql.org/docs/9.2/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE + * + https://www.sqlite.org/lang_aggfunc.html#sumunc + * + * ----- + * + * + MySQL : `SUM(x)` + * + PostgreSQL : `SUM(x)` + * + SQLite : `SUM(x)` + * + * ----- + * + * No guarantees are made about the precision of the return type. + */ export const sum = sumAll; diff --git a/unified-test/input/expr-library/cast/bigint-signed-literal/from-number.ts b/unified-test/input/expr-library/cast/bigint-signed-literal/from-number.ts new file mode 100644 index 00000000..8bc7e3fa --- /dev/null +++ b/unified-test/input/expr-library/cast/bigint-signed-literal/from-number.ts @@ -0,0 +1,55 @@ +import {Test} from "../../../../test"; +import * as tsql from "../../../../../dist"; + +export const test : Test = ({tape, pool}) => { + tape(__filename, async (t) => { + await pool.acquire(async (connection) => { + await tsql.selectValue(() => tsql.bigIntSignedLiteral(9001)) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt(9001)); + }); + + /** + * MAX_SAFE_INTEGER + */ + await tsql.selectValue(() => tsql.bigIntSignedLiteral(Number.MAX_SAFE_INTEGER)) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt(Number.MAX_SAFE_INTEGER)); + }); + + /** + * -MAX_SAFE_INTEGER + */ + await tsql.selectValue(() => tsql.bigIntSignedLiteral(-Number.MAX_SAFE_INTEGER)) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt(-Number.MAX_SAFE_INTEGER)); + }); + + t.throws(() => { + /** + * Too small + */ + tsql.selectValue(() => tsql.bigIntSignedLiteral(-1e300)); + }); + + t.throws(() => { + /** + * Too big + */ + tsql.selectValue(() => tsql.bigIntSignedLiteral(1e300)); + }); + + t.throws(() => { + /** + * Fractional + */ + tsql.selectValue(() => tsql.bigIntSignedLiteral(9001.1)); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/cast/bigint-signed-literal/from-string.ts b/unified-test/input/expr-library/cast/bigint-signed-literal/from-string.ts new file mode 100644 index 00000000..ce784277 --- /dev/null +++ b/unified-test/input/expr-library/cast/bigint-signed-literal/from-string.ts @@ -0,0 +1,48 @@ +import {Test} from "../../../../test"; +import * as tsql from "../../../../../dist"; + +export const test : Test = ({tape, pool}) => { + tape(__filename, async (t) => { + await pool.acquire(async (connection) => { + await tsql.selectValue(() => tsql.bigIntSignedLiteral("9001")) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt(9001)); + }); + + /** + * MAX BIGINT SIGNED VALUE + */ + await tsql.selectValue(() => tsql.bigIntSignedLiteral("9223372036854775807")) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt("9223372036854775807")); + }); + + /** + * MIN BIGINT SIGNED VALUE + */ + await tsql.selectValue(() => tsql.bigIntSignedLiteral("-9223372036854775808")) + .fetchValue(connection) + .then((value) => { + t.deepEqual(value, BigInt("-9223372036854775808")); + }); + + t.throws(() => { + /** + * Too small + */ + tsql.selectValue(() => tsql.bigIntSignedLiteral("-9223372036854775809")); + }); + + t.throws(() => { + /** + * Too big + */ + tsql.selectValue(() => tsql.bigIntSignedLiteral("9223372036854775808")); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/cast/unsafe-cast-as-binary/basic.ts b/unified-test/input/expr-library/cast/unsafe-cast-as-binary/basic.ts index e35973dc..a419500e 100644 --- a/unified-test/input/expr-library/cast/unsafe-cast-as-binary/basic.ts +++ b/unified-test/input/expr-library/cast/unsafe-cast-as-binary/basic.ts @@ -1,4 +1,3 @@ -import * as tm from "type-mapping"; import {Test} from "../../../../test"; import * as tsql from "../../../../../dist"; @@ -6,18 +5,18 @@ export const test : Test = ({tape, pool}) => { tape(__filename, async (t) => { await pool.acquire(async (connection) => { const arr = [ - "-123e0", - "-1.456", + "abcd", + "123", "123e0", "1.456", - tm.BigInt(876), - tm.BigInt(-999), + "hello, world", + "case-SENSITIVE", ]; for (const a of arr) { - await tsql.selectValue(() => tsql.unsafeCastAsDouble(a)) + await tsql.selectValue(() => tsql.unsafeCastAsBinary(a)) .fetchValue(connection) .then((value) => { - t.deepEqual(value, Number(a)); + t.deepEqual(value, Buffer.from(a)); }) .catch((err) => { t.fail(err.message); diff --git a/unified-test/input/expr-library/double/aggregate/avg-all/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/avg-all/all-non-null.ts new file mode 100644 index 00000000..bc1ecde2 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-all/all-non-null.ts @@ -0,0 +1,105 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(10+i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-all/all-null.ts b/unified-test/input/expr-library/double/aggregate/avg-all/all-null.ts new file mode 100644 index 00000000..37e6d80c --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-all/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-all/empty-table.ts b/unified-test/input/expr-library/double/aggregate/avg-all/empty-table.ts new file mode 100644 index 00000000..0757f438 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-all/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-all/mix-null.ts b/unified-test/input/expr-library/double/aggregate/avg-all/mix-null.ts new file mode 100644 index 00000000..cc0f8c33 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-all/mix-null.ts @@ -0,0 +1,117 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(10+i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-distinct/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/avg-distinct/all-non-null.ts new file mode 100644 index 00000000..af121a88 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-distinct/all-non-null.ts @@ -0,0 +1,105 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + //Insert duplicate rows, but `DISTINCT` will filter them out + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/10)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-distinct/all-null.ts b/unified-test/input/expr-library/double/aggregate/avg-distinct/all-null.ts new file mode 100644 index 00000000..82bec01e --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-distinct/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-distinct/empty-table.ts b/unified-test/input/expr-library/double/aggregate/avg-distinct/empty-table.ts new file mode 100644 index 00000000..dd1c4bd4 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-distinct/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/avg-distinct/mix-null.ts b/unified-test/input/expr-library/double/aggregate/avg-distinct/mix-null.ts new file mode 100644 index 00000000..927a8bf7 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/avg-distinct/mix-null.ts @@ -0,0 +1,117 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/(i+1))); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + //Insert duplicate rows, but `DISTINCT` will filter them out + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.avgDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total/10)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/max/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/max/all-non-null.ts new file mode 100644 index 00000000..b912293a --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/max/all-non-null.ts @@ -0,0 +1,80 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(i)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(9)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/max/all-null.ts b/unified-test/input/expr-library/double/aggregate/max/all-null.ts new file mode 100644 index 00000000..8ae20429 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/max/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/max/empty-table.ts b/unified-test/input/expr-library/double/aggregate/max/empty-table.ts new file mode 100644 index 00000000..54d9dd68 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/max/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/max/mix-null.ts b/unified-test/input/expr-library/double/aggregate/max/mix-null.ts new file mode 100644 index 00000000..ed381d34 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/max/mix-null.ts @@ -0,0 +1,92 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(i)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.max(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(9)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/min/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/min/all-non-null.ts new file mode 100644 index 00000000..530f2654 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/min/all-non-null.ts @@ -0,0 +1,80 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(0)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(0)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/min/all-null.ts b/unified-test/input/expr-library/double/aggregate/min/all-null.ts new file mode 100644 index 00000000..291fa80a --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/min/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/min/empty-table.ts b/unified-test/input/expr-library/double/aggregate/min/empty-table.ts new file mode 100644 index 00000000..b8404009 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/min/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/min/mix-null.ts b/unified-test/input/expr-library/double/aggregate/min/mix-null.ts new file mode 100644 index 00000000..39aa03cb --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/min/mix-null.ts @@ -0,0 +1,92 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(0)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.min(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, Number(0)); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-all/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/sum-all/all-non-null.ts new file mode 100644 index 00000000..893f0efb --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-all/all-non-null.ts @@ -0,0 +1,105 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-all/all-null.ts b/unified-test/input/expr-library/double/aggregate/sum-all/all-null.ts new file mode 100644 index 00000000..99a4e74a --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-all/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-all/empty-table.ts b/unified-test/input/expr-library/double/aggregate/sum-all/empty-table.ts new file mode 100644 index 00000000..212fc271 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-all/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-all/mix-null.ts b/unified-test/input/expr-library/double/aggregate/sum-all/mix-null.ts new file mode 100644 index 00000000..8e08ce72 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-all/mix-null.ts @@ -0,0 +1,117 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumAll(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-distinct/all-non-null.ts b/unified-test/input/expr-library/double/aggregate/sum-distinct/all-non-null.ts new file mode 100644 index 00000000..2d622854 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-distinct/all-non-null.ts @@ -0,0 +1,104 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-distinct/all-null.ts b/unified-test/input/expr-library/double/aggregate/sum-distinct/all-null.ts new file mode 100644 index 00000000..24e5db0b --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-distinct/all-null.ts @@ -0,0 +1,57 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + for (let i=0; i<10; ++i) { + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + } + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-distinct/empty-table.ts b/unified-test/input/expr-library/double/aggregate/sum-distinct/empty-table.ts new file mode 100644 index 00000000..42619d39 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-distinct/empty-table.ts @@ -0,0 +1,49 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + t.deepEqual(value, null); + }) + .catch((err) => { + t.fail(err.message); + }); + }); + + t.end(); + }); +}; diff --git a/unified-test/input/expr-library/double/aggregate/sum-distinct/mix-null.ts b/unified-test/input/expr-library/double/aggregate/sum-distinct/mix-null.ts new file mode 100644 index 00000000..1a2cc6d0 --- /dev/null +++ b/unified-test/input/expr-library/double/aggregate/sum-distinct/mix-null.ts @@ -0,0 +1,116 @@ +import * as tm from "type-mapping"; +import {Test} from "../../../../../test"; +import * as tsql from "../../../../../../dist"; + +export const test : Test = ({tape, pool, createTemporarySchema}) => { + tape(__filename, async (t) => { + const myTable = tsql.table("myTable") + .addColumns({ + myTableVal : tm.mysql.double().orNull(), + }); + + await pool.acquire(async (connection) => { + await createTemporarySchema( + connection, + { + tables : [ + { + tableAlias : "myTable", + columns : [ + { + columnAlias : "myTableVal", + dataType : { + typeHint : tsql.TypeHint.DOUBLE, + }, + nullable : true, + }, + ], + }, + ] + } + ); + + let total = 0; + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + total += i; + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + + for (let i=0; i<10; ++i) { + await myTable.insertOne( + connection, + { + myTableVal : Number(i), + } + ); + await myTable.insertOne( + connection, + { + myTableVal : null, + } + ); + + await myTable + .where(() => true) + .fetchValue( + connection, + columns => tsql.double.sumDistinct(columns.myTableVal) + ) + .then((value) => { + const expected = tm.FixedPointUtil.tryParse(String(total)); + if (expected == undefined) { + t.notDeepEqual(expected, undefined); + return; + } + t.true( + Math.abs( + Number(value) - + Number(expected.getFixedPointString()) + ) < 0.01, + `Total = ${total}, value=${value}, expected=${expected.getFixedPointString()}` + ); + }) + .catch((err) => { + t.fail(err.message); + }); + } + }); + + t.end(); + }); +};