Skip to content

Commit 47c427f

Browse files
mysql records work better
1 parent 1ed17c1 commit 47c427f

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

packages/malloy/src/dialect/mysql/mysql.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ export class MySQLDialect extends Dialect {
315315
const child = childName;
316316

317317
if (parentType !== 'table') {
318-
let ret = `${parent}->>'$.${child}'`;
318+
let ret = `JSON_UNQUOTE(JSON_EXTRACT(${parent},'$.${child}'))`;
319319
if (parentType === 'array[scalar]') {
320320
ret = `${parent}.\`value\``;
321321
}

test/src/databases/all/compound-atomic.spec.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ const runtimes = new RuntimeList(databasesFromEnvironmentOr(allDatabases));
2727

2828
describe.each(runtimes.runtimeList)(
2929
'compound atomic datatypes %s',
30-
(databaseName, runtime) => {
30+
(conName, runtime) => {
3131
// mtoy todo dialect flag
32-
const supportsNestedArrays = !['bigquery'].includes(databaseName);
32+
const supportsNestedArrays = !['bigquery'].includes(conName);
3333
const quote = runtime.dialect.sqlMaybeQuoteIdentifier;
3434
function literalNum(num: Number): Expr {
3535
const literal = num.toString();
3636
return {node: 'numberLiteral', literal, sql: literal};
3737
}
38-
const empty = `${databaseName}.sql("SELECT 0 as z")`;
38+
const empty = `${conName}.sql("SELECT 0 as z")`;
3939
function arraySelectVal(...val: Number[]): string {
4040
const literal: ArrayLiteralNode = {
4141
node: 'arrayLiteral',
@@ -78,18 +78,22 @@ describe.each(runtimes.runtimeList)(
7878
function recordSelectVal(fromObj: Record<string, number>): string {
7979
return runtime.dialect.sqlLiteralRecord(recordLiteral(fromObj));
8080
}
81+
const canReadCompoungSchema = conName !== 'mysql' && conName !== 'postgres';
8182

8283
// eslint-disable-next-line @typescript-eslint/no-unused-vars
8384
const ab = recordSelectVal({a: 0, b: 1});
8485

86+
const malloySizes = 'sizes is {s is 0, m is 1, l is 2, xl is 3}';
8587
const sizesObj = {s: 0, m: 1, l: 2, xl: 3};
8688
const sizesSQL = recordSelectVal(sizesObj);
87-
const sizes = `${databaseName}.sql("""
88-
SELECT ${sizesSQL} AS ${quote('sizes')}
89-
""")`;
89+
// Keeping the pipeline simpler makes debugging easier, so don't add
90+
// and extra stage unless you have to
91+
const sizes = canReadCompoungSchema
92+
? `${conName}.sql(""" SELECT ${sizesSQL} AS ${quote('sizes')} """)`
93+
: `${conName}.sql('SELECT 0 AS O') -> { select: ${malloySizes}}`;
9094
const evensObj = [2, 4, 6, 8];
9195
const evensSQL = arraySelectVal(...evensObj);
92-
const evens = `${databaseName}.sql("""
96+
const evens = `${conName}.sql("""
9397
SELECT ${evensSQL} AS ${quote('evens')}
9498
""")`;
9599

@@ -105,7 +109,7 @@ describe.each(runtimes.runtimeList)(
105109
run: ${evens}->{select: nn is evens}
106110
`).malloyResultMatches(runtime, {nn: evensObj});
107111
});
108-
test('array-un-nest on each', async () => {
112+
test('schema read allows array-un-nest on each', async () => {
109113
await expect(`
110114
run: ${evens}->{ select: n is evens.each }
111115
`).malloyResultMatches(
@@ -198,8 +202,16 @@ describe.each(runtimes.runtimeList)(
198202
[`${name}/xl`]: 3,
199203
};
200204
}
201-
test('record literal dialect function', async () => {
202-
await expect(`run: ${sizes}`).malloyResultMatches(runtime, rec_eq());
205+
test('record literal object', async () => {
206+
await expect(`
207+
run: ${conName}.sql("select 0 as o")
208+
-> { select: ${malloySizes}}
209+
`).malloyResultMatches(runtime, rec_eq());
210+
});
211+
test('can read schema of record object', async () => {
212+
await expect(`run: ${conName}.sql("""
213+
SELECT ${sizesSQL} AS ${quote('sizes')}
214+
""")`).malloyResultMatches(runtime, rec_eq());
203215
});
204216
test('simple record.property access', async () => {
205217
await expect(`
@@ -210,7 +222,7 @@ describe.each(runtimes.runtimeList)(
210222
});
211223
test('nested data looks like a record', async () => {
212224
await expect(`
213-
run: ${databaseName}.sql('SELECT 1 as ${quote('o')}') -> {
225+
run: ${conName}.sql('SELECT 1 as ${quote('o')}') -> {
214226
group_by: row is 'one_row'
215227
nest: sizes is {
216228
aggregate:
@@ -237,7 +249,7 @@ describe.each(runtimes.runtimeList)(
237249
test('select record literal from a source', async () => {
238250
await expect(`
239251
run: ${empty} -> {
240-
extend: { dimension: sizes is {s is 0, m is 1, l is 2, xl is 3} }
252+
extend: { dimension: ${malloySizes} }
241253
select: sizes
242254
}
243255
`).malloyResultMatches(runtime, rec_eq());
@@ -325,7 +337,7 @@ describe.each(runtimes.runtimeList)(
325337

326338
test('repeated record from nest', async () => {
327339
await expect(`
328-
run: ${databaseName}.sql("""
340+
run: ${conName}.sql("""
329341
SELECT
330342
10 as ${quote('a')},
331343
11 as ${quote('b')}
@@ -336,7 +348,7 @@ describe.each(runtimes.runtimeList)(
336348
});
337349
test('select repeated record from literal dialect functions', async () => {
338350
await expect(`
339-
run: ${databaseName}.sql(""" ${selectAB('ab')} """)
351+
run: ${conName}.sql(""" ${selectAB('ab')} """)
340352
`).malloyResultMatches(runtime, {ab: ab_eq});
341353
});
342354
test('repeat record from malloy literal', async () => {
@@ -347,7 +359,7 @@ describe.each(runtimes.runtimeList)(
347359
});
348360
test('repeated record can be selected and renamed', async () => {
349361
const src = `
350-
run: ${databaseName}.sql("""
362+
run: ${conName}.sql("""
351363
${selectAB('sqlAB')}
352364
""") -> { select: ab is sqlAB }
353365
`;
@@ -362,7 +374,7 @@ describe.each(runtimes.runtimeList)(
362374
});
363375
test('deref repeat record passed down pipeline', async () => {
364376
await expect(`
365-
run: ${databaseName}.sql("""
377+
run: ${conName}.sql("""
366378
${selectAB('sqlAB')}
367379
""") -> { select: ab is sqlAB }
368380
-> { select: ab.a, ab.b }

0 commit comments

Comments
 (0)