From 9dce09e0bb8cca2cecfcb261f55f94864a457db8 Mon Sep 17 00:00:00 2001 From: Michael Toy <66150587+mtoy-googly-moogly@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:51:18 -0800 Subject: [PATCH] fix mysql not and snowflake test --- packages/malloy/src/dialect/dialect.ts | 5 +++-- packages/malloy/src/dialect/mysql/mysql.ts | 4 ++-- .../malloy/src/lang/ast/expressions/expr-not.ts | 5 +++++ test/src/databases/all/expr.spec.ts | 17 +++++++++-------- test/src/databases/all/nomodel.spec.ts | 17 ----------------- 5 files changed, 19 insertions(+), 29 deletions(-) diff --git a/packages/malloy/src/dialect/dialect.ts b/packages/malloy/src/dialect/dialect.ts index df475c029..308bb5cd7 100644 --- a/packages/malloy/src/dialect/dialect.ts +++ b/packages/malloy/src/dialect/dialect.ts @@ -173,13 +173,14 @@ export abstract class Dialect { // MYSQL doesn't have full join, maybe others. supportsFullJoin = true; - nativeBoolean = true; - // Can have arrays of arrays nestedArrays = true; // An array or record will reveal type of contents on schema read compoundObjectInSchema = true; + // No true boolean type, e.g. true=1 and false=0, set this to true + booleanAsNumbers = false; + abstract getDialectFunctionOverrides(): { [name: string]: DialectFunctionOverloadDef[]; }; diff --git a/packages/malloy/src/dialect/mysql/mysql.ts b/packages/malloy/src/dialect/mysql/mysql.ts index de2e5b646..cb9a784ef 100644 --- a/packages/malloy/src/dialect/mysql/mysql.ts +++ b/packages/malloy/src/dialect/mysql/mysql.ts @@ -107,7 +107,7 @@ export class MySQLDialect extends Dialect { defaultDecimalType = 'DECIMAL'; udfPrefix = 'ms_temp.__udf'; hasFinalStage = false; - // TODO: this may not be enough for lager casts. + // TODO: this may not be enough for larger casts. stringTypeName = 'VARCHAR(255)'; divisionIsInteger = true; supportsSumDistinctFunction = true; @@ -121,13 +121,13 @@ export class MySQLDialect extends Dialect { supportsQualify = false; supportsNesting = true; experimental = false; - nativeBoolean = false; supportsFullJoin = false; supportsPipelinesInViews = false; readsNestedData = false; supportsComplexFilteredSources = false; supportsArraysInData = false; compoundObjectInSchema = false; + booleanAsNumbers = true; malloyTypeToSQLType(malloyType: AtomicTypeDef): string { switch (malloyType.type) { diff --git a/packages/malloy/src/lang/ast/expressions/expr-not.ts b/packages/malloy/src/lang/ast/expressions/expr-not.ts index d89270952..aabdb78df 100644 --- a/packages/malloy/src/lang/ast/expressions/expr-not.ts +++ b/packages/malloy/src/lang/ast/expressions/expr-not.ts @@ -36,6 +36,11 @@ export class ExprNot extends Unary { getExpression(fs: FieldSpace): ExprValue { const notThis = this.expr.getExpression(fs); + if (fs.dialectObj()?.booleanAsNumbers) { + if (this.legalChildTypes.find(t => t.type === 'number') === undefined) { + this.legalChildTypes.push(TDU.numberT); + } + } const doNot = this.typeCheck(this.expr, notThis); return { ...notThis, diff --git a/test/src/databases/all/expr.spec.ts b/test/src/databases/all/expr.spec.ts index aef24361e..43ee85b34 100644 --- a/test/src/databases/all/expr.spec.ts +++ b/test/src/databases/all/expr.spec.ts @@ -839,14 +839,15 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => { describe('null safe booleans', () => { const nulls = `${databaseName}.sql(""" SELECT - 0 as null_cnt, + 0 as ${q`n`}, 1 as ${q`x`}, 2 as ${q`y`}, 'a' as ${q`a`}, 'b' as ${q`b`}, (1 = 1) as ${q`tf`} UNION ALL SELECT 5, null, null, null, null, null - """) extend { where: null_cnt > 0 }`; + """) extend { where: n > 0 }`; + const is_true = databaseName === 'mysql' ? 1 : true; it('select boolean', async () => { await expect(`run: ${nulls} -> { @@ -858,32 +859,32 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => { await expect(`run: ${nulls} -> { select: not_null_boolean is not tf - }`).malloyResultMatches(runtime, {not_null_boolean: true}); + }`).malloyResultMatches(runtime, {not_null_boolean: is_true}); }); it('numeric != non-null to null', async () => { await expect( `run: ${nulls} -> { select: val_ne_null is x != 9 }` - ).malloyResultMatches(runtime, {val_ne_null: true}); + ).malloyResultMatches(runtime, {val_ne_null: is_true}); }); it('string !~ non-null to null', async () => { await expect( `run: ${nulls} -> { select: val_ne_null is a !~ 'z' }` - ).malloyResultMatches(runtime, {val_ne_null: true}); + ).malloyResultMatches(runtime, {val_ne_null: is_true}); }); it('regex !~ non-null to null', async () => { await expect( `run: ${nulls} -> { select: val_ne_null is a !~ r'z' }` - ).malloyResultMatches(runtime, {val_ne_null: true}); + ).malloyResultMatches(runtime, {val_ne_null: is_true}); }); it('numeric != null-to-null', async () => { await expect( `run: ${nulls} -> { select: null_ne_null is x != y }` - ).malloyResultMatches(runtime, {null_ne_null: true}); + ).malloyResultMatches(runtime, {null_ne_null: is_true}); }); it('string !~ null-to-null', async () => { await expect( `run: ${nulls} -> { select: null_ne_null is a !~ b }` - ).malloyResultMatches(runtime, {null_ne_null: true}); + ).malloyResultMatches(runtime, {null_ne_null: is_true}); }); }); diff --git a/test/src/databases/all/nomodel.spec.ts b/test/src/databases/all/nomodel.spec.ts index 07183384e..8b858f94a 100644 --- a/test/src/databases/all/nomodel.spec.ts +++ b/test/src/databases/all/nomodel.spec.ts @@ -63,23 +63,6 @@ afterAll(async () => { runtimes.runtimeMap.forEach((runtime, databaseName) => { const q = runtime.getQuoter(); - // Issue #1824 - it.when(runtime.dialect.nativeBoolean)( - `not boolean field with null - ${databaseName}`, - async () => { - await expect(` - run: ${databaseName}.sql(""" - SELECT - CASE WHEN 1=1 THEN NULL ELSE false END as ${q`n`} - """) -> { - select: - is_true is not n - } - `).malloyResultMatches(runtime, { - is_true: true, - }); - } - ); // Issue: #1284 it(`parenthesize output field values - ${databaseName}`, async () => {