diff --git a/packages/mongo/src/utils.ts b/packages/mongo/src/utils.ts index aa29388f..59c200c3 100644 --- a/packages/mongo/src/utils.ts +++ b/packages/mongo/src/utils.ts @@ -112,7 +112,6 @@ export class Transformer { } else if (this.refTables.includes(expr.$[0])) { return `$$${expr.$[0]}.` + this.getActualKey(expr.$[1], expr.$[0]) } else { - console.log(this.tables, this.refTables) throw new Error(`$ not transformed: ${JSON.stringify(expr)}`) } } diff --git a/packages/mysql/src/index.ts b/packages/mysql/src/index.ts index 86bec85e..2ef462d7 100644 --- a/packages/mysql/src/index.ts +++ b/packages/mysql/src/index.ts @@ -172,11 +172,13 @@ class MySQLBuilder extends Builder { const { args: [expr], ref, table, tables } = sel const thisTables = this.tables, thisState = this.state this.tables = { ...tables } - this.state = { group: true, wrappedSubquery: true, refTables: { ...(this.state.refTables || {}), ...(thisTables || {}) } } - const output = this.parseEval(expr) + this.state = { wrappedSubquery: true, refTables: { ...(this.state.refTables || {}), ...(thisTables || {}) } } const inner = this.get(table as Selection, true) as string + this.state.group = true + const output = this.parseEval(expr, false) const refFields = this.state.refFields this.tables = thisTables + thisState.sqlType = this.state.sqlType this.state = thisState let query: string if (!(sel.args[0] as any).$) { @@ -193,12 +195,12 @@ class MySQLBuilder extends Builder { } if (Object.keys(refFields ?? {}).length) { const funcname = `minato_tfunc_${randomId()}` - const keys = Object.keys(refFields ?? {}).map(x => `${x} JSON`).join(',') + const decls = Object.values(refFields ?? {}).map(x => `${x} JSON`).join(',') + const args = Object.keys(refFields ?? {}).map(x => this.state.refFields?.[x] ?? x).map(x => this.jsonQuote(x, true)).join(',') this.prequeries.push(`DROP FUNCTION IF EXISTS ${funcname}`) - this.prequeries.push(`CREATE FUNCTION ${funcname} (${keys}) RETURNS JSON DETERMINISTIC RETURN ${this.jsonQuote(query)}`) - query = `${funcname}(${Object.values(refFields ?? {}).map(x => this.jsonQuote(x, true)).join(',')})` + this.prequeries.push(`CREATE FUNCTION ${funcname} (${decls}) RETURNS JSON DETERMINISTIC RETURN ${this.jsonQuote(query)}`) this.state.sqlType = 'json' - return query + return `${funcname}(${args})` } else return query } diff --git a/packages/sql-utils/src/index.ts b/packages/sql-utils/src/index.ts index 9f50cfb8..a1b7e629 100644 --- a/packages/sql-utils/src/index.ts +++ b/packages/sql-utils/src/index.ts @@ -211,12 +211,13 @@ export class Builder { const { args: [expr], ref, table, tables } = sel const thisTables = this.tables, thisState = this.state this.tables = { ...tables } - this.state = { group: true, refTables: { ...(this.state.refTables || {}), ...(thisTables || {}) } } - const output = this.parseEval(expr) + this.state = { refTables: { ...(this.state.refTables || {}), ...(thisTables || {}) } } const inner = this.get(table as Selection, true) as string + this.state.group = true + const output = this.parseEval(expr, false) this.tables = thisTables + thisState.sqlType = this.state.sqlType this.state = thisState - console.log(inner) if (!(sel.args[0] as any).$) { this.state.sqlType = 'raw' if (inner.startsWith('(') && inner.endsWith(')')) { @@ -380,10 +381,11 @@ export class Builder { const res = (fields[key]?.expr) ? this.parseEvalExpr(fields[key]?.expr) : this.transformKey(key, fields, `${escapeId(table)}.`, `${table}.${key}`) if (this.state.wrappedSubquery) { + if (res in (this.state.refFields ?? {})) return this.state.refFields![res] const key = `minato_tvar_${randomId()}` - ;(this.state.refFields ??= {})[key] = res + ;(this.state.refFields ??= {})[res] = key this.state.sqlType = 'json' - return this.jsonUnquote(escapeId(key)) + return escapeId(key) } else return res } diff --git a/packages/tests/src/selection.ts b/packages/tests/src/selection.ts index 9f2162ab..010cbecf 100644 --- a/packages/tests/src/selection.ts +++ b/packages/tests/src/selection.ts @@ -444,6 +444,26 @@ namespace SelectionTests { { x: [4] }, ]) }) + + it('return nested array', async () => { + await expect(database.select('foo') + .project({ + x: r => database.select('bar') + .where(row => $.and($.gte(row.pid, r.id), $.lt(row.uid, r.id))) + .project({ + id: _ => database.select('foo').project({ + id: row => $.add(row.id, r.id), + }).evaluate('id') + }) + .evaluate('id') + }) + .execute()) + .to.eventually.deep.equal([ + { x: [] }, + { x: [[3, 4, 5], [3, 4, 5]] }, + { x: [[4, 5, 6]] }, + ]) + }) } }