From 4ef9323b1ef2c1980f36b59de5a8c089d87f6d1c Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 8 Nov 2023 16:33:13 +0300 Subject: [PATCH] feat: single exec Signed-off-by: mertmit --- packages/nocodb/src/db/BaseModelSqlv2.ts | 492 +++++++++++------- packages/nocodb/src/db/CustomKnex.ts | 13 +- .../src/db/formulav2/formulaQueryBuilderv2.ts | 10 +- .../src/db/sql-client/lib/KnexClient.ts | 194 ++++--- .../db/sql-client/lib/mysql/MysqlClient.ts | 38 +- .../src/db/sql-client/lib/pg/PgClient.ts | 71 +-- packages/nocodb/src/models/Source.ts | 35 +- .../nocodb/src/services/columns.service.ts | 46 +- .../nocodb/src/services/tables.service.ts | 2 +- .../pages/Dashboard/ProjectView/Metadata.ts | 4 +- .../tests/db/features/metaSync.spec.ts | 2 +- 11 files changed, 542 insertions(+), 365 deletions(-) diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 279aef7868..f88dc4b4e3 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -165,7 +165,7 @@ class BaseModelSqlv2 { let data; try { - data = (await this.execAndParse(qb))?.[0]; + data = await this.execAndParse(qb, null, { first: true }); } catch (e) { if (validateFormula || !haveFormulaColumn(await this.model.getColumns())) throw e; @@ -194,7 +194,7 @@ class BaseModelSqlv2 { return false; } qb.where(_wherePk(pks, id)).first(); - return !!(await qb); + return !!(await this.execAndParse(qb, null, { raw: true, first: true })); } // todo: add support for sortArrJson @@ -240,7 +240,7 @@ class BaseModelSqlv2 { let data; try { - data = await qb.first(); + data = await this.execAndParse(qb, null, { first: true }); } catch (e) { if (validateFormula || !haveFormulaColumn(await this.model.getColumns())) throw e; @@ -452,10 +452,8 @@ class BaseModelSqlv2 { sql = unsanitize(qb.toQuery()); } - const res = (await this.dbDriver.raw(sql)) as any; - - return (this.isPg || this.isSnowflake ? res.rows[0] : res[0][0] ?? res[0]) - .count; + return (await this.execAndParse(sql, null, { raw: true, first: true })) + ?.count; } async groupByAndAggregate( @@ -516,7 +514,7 @@ class BaseModelSqlv2 { qb.orderBy(args.sortBy.column_name, args.sortBy.direction); } applyPaginate(qb, rest); - return await qb; + return await this.execAndParse(qb); } async groupBy(args: { @@ -680,7 +678,7 @@ class BaseModelSqlv2 { qb.groupBy(...groupBySelectors); applyPaginate(qb, rest); - return await qb; + return await this.execAndParse(qb); } async groupByCount(args: { @@ -819,7 +817,8 @@ class BaseModelSqlv2 { .count('*', { as: 'count' }) .from(qb.as('groupby')); - return (await qbP.first())?.count; + return (await this.execAndParse(qbP, null, { raw: true, first: true })) + ?.count; } async multipleHmList( @@ -947,22 +946,26 @@ class BaseModelSqlv2 { const childTn = this.getTnPath(childTable); const parentTn = this.getTnPath(parentTable); - const children = await this.dbDriver.unionAll( - ids.map((p) => { - const query = this.dbDriver(childTn) - .count(`${chilCol?.column_name} as count`) - .whereIn( - chilCol.column_name, - this.dbDriver(parentTn) - .select(parentCol.column_name) - // .where(parentTable.primaryKey.cn, p) - .where(_wherePk(parentTable.primaryKeys, p)), - ) - .first(); + const children = await this.execAndParse( + this.dbDriver.unionAll( + ids.map((p) => { + const query = this.dbDriver(childTn) + .count(`${chilCol?.column_name} as count`) + .whereIn( + chilCol.column_name, + this.dbDriver(parentTn) + .select(parentCol.column_name) + // .where(parentTable.primaryKey.cn, p) + .where(_wherePk(parentTable.primaryKeys, p)), + ) + .first(); - return this.isSqlite ? this.dbDriver.select().from(query) : query; - }), - !this.isSqlite, + return this.isSqlite ? this.dbDriver.select().from(query) : query; + }), + !this.isSqlite, + ), + null, + { raw: true }, ); return children.map(({ count }) => count); @@ -1069,7 +1072,8 @@ class BaseModelSqlv2 { await conditionV2(this, filterObj, query); - return (await query.first())?.count; + return (await this.execAndParse(query, null, { raw: true, first: true })) + ?.count; } catch (e) { console.log(e); throw e; @@ -1249,22 +1253,26 @@ class BaseModelSqlv2 { .count(`${vtn}.${vcn}`, { as: 'count' }); // await childModel.selectObject({ qb }); - const children = await this.dbDriver.unionAll( - parentIds.map((id) => { - const query = qb - .clone() - .whereIn( - `${vtn}.${vcn}`, - this.dbDriver(parentTn) - .select(cn) - // .where(parentTable.primaryKey.cn, id) - .where(_wherePk(parentTable.primaryKeys, id)), - ) - .select(this.dbDriver.raw('? as ??', [id, GROUP_COL])); - // this._paginateAndSort(query, { sort, limit, offset }, null, true); - return this.isSqlite ? this.dbDriver.select().from(query) : query; - }), - !this.isSqlite, + const children = await this.execAndParse( + this.dbDriver.unionAll( + parentIds.map((id) => { + const query = qb + .clone() + .whereIn( + `${vtn}.${vcn}`, + this.dbDriver(parentTn) + .select(cn) + // .where(parentTable.primaryKey.cn, id) + .where(_wherePk(parentTable.primaryKeys, id)), + ) + .select(this.dbDriver.raw('? as ??', [id, GROUP_COL])); + // this._paginateAndSort(query, { sort, limit, offset }, null, true); + return this.isSqlite ? this.dbDriver.select().from(query) : query; + }), + !this.isSqlite, + ), + null, + { raw: true }, ); const gs = groupBy(children, GROUP_COL); @@ -1312,7 +1320,8 @@ class BaseModelSqlv2 { const filterObj = extractFilterFromXwhere(where, aliasColObjMap); await conditionV2(this, filterObj, qb); - return (await qb.first())?.count; + return (await this.execAndParse(qb, null, { raw: true, first: true })) + ?.count; } // todo: naming & optimizing @@ -1363,7 +1372,8 @@ class BaseModelSqlv2 { const filterObj = extractFilterFromXwhere(where, aliasColObjMap); await conditionV2(this, filterObj, qb); - return (await qb.first())?.count; + return (await this.execAndParse(qb, null, { raw: true, first: true })) + ?.count; } // todo: naming & optimizing @@ -1486,7 +1496,8 @@ class BaseModelSqlv2 { await conditionV2(this, filterObj, qb); - return (await qb.first())?.count; + return (await this.execAndParse(qb, null, { raw: true, first: true })) + ?.count; } // todo: naming & optimizing @@ -1601,7 +1612,8 @@ class BaseModelSqlv2 { const filterObj = extractFilterFromXwhere(where, aliasColObjMap); await conditionV2(this, filterObj, qb); - return (await qb.first())?.count; + return (await this.execAndParse(qb, null, { raw: true, first: true })) + ?.count; } // todo: naming & optimizing @@ -2256,16 +2268,24 @@ class BaseModelSqlv2 { if (this.isSqlite) { // sqlite doesnt return id after insert id = ( - await this.dbDriver(this.tnPath) - .select(ai.column_name) - .max(ai.column_name, { as: 'id' }) + await this.execAndParse( + this.dbDriver(this.tnPath) + .select(ai.column_name) + .max(ai.column_name, { as: 'id' }), + null, + { raw: true }, + ) )[0].id; } else if (this.isSnowflake) { id = ( - (await this.dbDriver(this.tnPath).max(ai.column_name, { - as: 'id', - })) as any - )[0].id; + await this.execAndParse( + this.dbDriver(this.tnPath).max(ai.column_name, { + as: 'id', + }), + null, + { raw: true, first: true }, + ) + ).id; } response = await this.readByPk( id, @@ -2399,23 +2419,31 @@ class BaseModelSqlv2 { let cnt = 0; if (colOptions.type === RelationTypes.HAS_MANY) { cnt = +( - await this.dbDriver(this.getTnPath(childModel.table_name)) - .count(childColumn.column_name, { as: 'cnt' }) - .where(childColumn.column_name, rowId) - )[0].cnt; + await this.execAndParse( + this.dbDriver(this.getTnPath(childModel.table_name)) + .count(childColumn.column_name, { as: 'cnt' }) + .where(childColumn.column_name, rowId), + null, + { raw: true, first: true }, + ) + ).cnt; } else if (colOptions.type === RelationTypes.MANY_TO_MANY) { const mmModel = await colOptions.getMMModel(); const mmChildColumn = await colOptions.getMMChildColumn(); cnt = +( - await this.dbDriver(this.getTnPath(mmModel.table_name)) - .where( - `${this.getTnPath(mmModel.table_name)}.${ - mmChildColumn.column_name - }`, - rowId, - ) - .count(mmChildColumn.column_name, { as: 'cnt' }) - )[0].cnt; + await this.execAndParse( + this.dbDriver(this.getTnPath(mmModel.table_name)) + .where( + `${this.getTnPath(mmModel.table_name)}.${ + mmChildColumn.column_name + }`, + rowId, + ) + .count(mmChildColumn.column_name, { as: 'cnt' }), + null, + { first: true }, + ) + ).cnt; } if (cnt) { res.push( @@ -2569,7 +2597,7 @@ class BaseModelSqlv2 { query.returning( `${this.model.primaryKey.column_name} as ${this.model.primaryKey.title}`, ); - response = await query; + response = await this.execAndParse(query); } const ai = this.model.columns.find((c) => c.ai); @@ -2580,23 +2608,37 @@ class BaseModelSqlv2 { if (response?.length) { rowId = response[0]; } else { - rowId = (await query)[0]; + rowId = await this.execAndParse(query, null, { + raw: true, + first: true, + }); } if (ai) { if (this.isSqlite) { // sqlite doesnt return id after insert rowId = ( - await this.dbDriver(this.tnPath) - .select(ai.column_name) - .max(ai.column_name, { as: 'id' }) - )[0].id; + await this.execAndParse( + this.dbDriver(this.tnPath) + .select(ai.column_name) + .max(ai.column_name, { as: 'id' }), + null, + { + raw: true, + first: true, + }, + ) + )?.id; } else if (this.isSnowflake) { rowId = ( - (await this.dbDriver(this.tnPath).max(ai.column_name, { - as: 'id', - })) as any - ).rows[0].id; + await this.execAndParse( + this.dbDriver(this.tnPath).max(ai.column_name, { + as: 'id', + }), + null, + { raw: true, first: true }, + ) + )?.id; } // response = await this.readByPk( // id, @@ -2921,7 +2963,7 @@ class BaseModelSqlv2 { for (const insertData of insertDatas) { const query = trx(this.tnPath).insert(insertData); - const id = (await query)[0]; + const id = await query; response.push(aiPkCol ? { [aiPkCol.title]: id } : id); } } else { @@ -3115,9 +3157,16 @@ class BaseModelSqlv2 { await conditionV2(this, conditionObj, qb); + count = ( + await this.execAndParse(qb.clone().count(), null, { + raw: true, + first: true, + }) + )?.count; + qb.update(updateData); - count = (await qb) as any; + await this.execAndParse(qb, null, { raw: true }); } await this.afterBulkUpdate(null, count, this.dbDriver, cookie, true); @@ -3704,52 +3753,68 @@ class BaseModelSqlv2 { .where(_wherePk(childTable.primaryKeys, rowId)) .first(); - await this.dbDriver.raw( - `INSERT INTO ?? (??, ??) SELECT (${parentPK.toQuery()}), (${childPK.toQuery()})`, - [vTn, vParentCol.column_name, vChildCol.column_name], + await this.execAndParse( + this.dbDriver.raw( + `INSERT INTO ?? (??, ??) SELECT (${parentPK.toQuery()}), (${childPK.toQuery()})`, + [vTn, vParentCol.column_name, vChildCol.column_name], + ) as any, + null, + { raw: true }, ); } else { - await this.dbDriver(vTn).insert({ - [vParentCol.column_name]: this.dbDriver(parentTn) - .select(parentColumn.column_name) - .where(_wherePk(parentTable.primaryKeys, childId)) - .first(), - [vChildCol.column_name]: this.dbDriver(childTn) - .select(childColumn.column_name) - .where(_wherePk(childTable.primaryKeys, rowId)) - .first(), - }); + await this.execAndParse( + this.dbDriver(vTn).insert({ + [vParentCol.column_name]: this.dbDriver(parentTn) + .select(parentColumn.column_name) + .where(_wherePk(parentTable.primaryKeys, childId)) + .first(), + [vChildCol.column_name]: this.dbDriver(childTn) + .select(childColumn.column_name) + .where(_wherePk(childTable.primaryKeys, rowId)) + .first(), + }), + null, + { raw: true }, + ); } } break; case RelationTypes.HAS_MANY: { - await this.dbDriver(childTn) - .update({ - [childColumn.column_name]: this.dbDriver.from( - this.dbDriver(parentTn) - .select(parentColumn.column_name) - .where(_wherePk(parentTable.primaryKeys, rowId)) - .first() - .as('___cn_alias'), - ), - }) - .where(_wherePk(childTable.primaryKeys, childId)); + await this.execAndParse( + this.dbDriver(childTn) + .update({ + [childColumn.column_name]: this.dbDriver.from( + this.dbDriver(parentTn) + .select(parentColumn.column_name) + .where(_wherePk(parentTable.primaryKeys, rowId)) + .first() + .as('___cn_alias'), + ), + }) + .where(_wherePk(childTable.primaryKeys, childId)), + null, + { raw: true }, + ); } break; case RelationTypes.BELONGS_TO: { - await this.dbDriver(childTn) - .update({ - [childColumn.column_name]: this.dbDriver.from( - this.dbDriver(parentTn) - .select(parentColumn.column_name) - .where(_wherePk(parentTable.primaryKeys, childId)) - .first() - .as('___cn_alias'), - ), - }) - .where(_wherePk(childTable.primaryKeys, rowId)); + await this.execAndParse( + this.dbDriver(childTn) + .update({ + [childColumn.column_name]: this.dbDriver.from( + this.dbDriver(parentTn) + .select(parentColumn.column_name) + .where(_wherePk(parentTable.primaryKeys, childId)) + .first() + .as('___cn_alias'), + ), + }) + .where(_wherePk(childTable.primaryKeys, rowId)), + null, + { raw: true }, + ); } break; } @@ -3827,44 +3892,56 @@ class BaseModelSqlv2 { const vTn = this.getTnPath(vTable); - await this.dbDriver(vTn) - .where({ - [vParentCol.column_name]: this.dbDriver(parentTn) - .select(parentColumn.column_name) - .where(_wherePk(parentTable.primaryKeys, childId)) - .first(), - [vChildCol.column_name]: this.dbDriver(childTn) - .select(childColumn.column_name) - .where(_wherePk(childTable.primaryKeys, rowId)) - .first(), - }) - .delete(); + await this.execAndParse( + this.dbDriver(vTn) + .where({ + [vParentCol.column_name]: this.dbDriver(parentTn) + .select(parentColumn.column_name) + .where(_wherePk(parentTable.primaryKeys, childId)) + .first(), + [vChildCol.column_name]: this.dbDriver(childTn) + .select(childColumn.column_name) + .where(_wherePk(childTable.primaryKeys, rowId)) + .first(), + }) + .delete(), + null, + { raw: true }, + ); } break; case RelationTypes.HAS_MANY: { - await this.dbDriver(childTn) - // .where({ - // [childColumn.cn]: this.dbDriver(parentTable.tn) - // .select(parentColumn.cn) - // .where(parentTable.primaryKey.cn, rowId) - // .first() - // }) - .where(_wherePk(childTable.primaryKeys, childId)) - .update({ [childColumn.column_name]: null }); + await this.execAndParse( + this.dbDriver(childTn) + // .where({ + // [childColumn.cn]: this.dbDriver(parentTable.tn) + // .select(parentColumn.cn) + // .where(parentTable.primaryKey.cn, rowId) + // .first() + // }) + .where(_wherePk(childTable.primaryKeys, childId)) + .update({ [childColumn.column_name]: null }), + null, + { raw: true }, + ); } break; case RelationTypes.BELONGS_TO: { - await this.dbDriver(childTn) - // .where({ - // [childColumn.cn]: this.dbDriver(parentTable.tn) - // .select(parentColumn.cn) - // .where(parentTable.primaryKey.cn, childId) - // .first() - // }) - .where(_wherePk(childTable.primaryKeys, rowId)) - .update({ [childColumn.column_name]: null }); + await this.execAndParse( + this.dbDriver(childTn) + // .where({ + // [childColumn.cn]: this.dbDriver(parentTable.tn) + // .select(parentColumn.cn) + // .where(parentTable.primaryKey.cn, childId) + // .first() + // }) + .where(_wherePk(childTable.primaryKeys, rowId)) + .update({ [childColumn.column_name]: null }), + null, + { raw: true }, + ); } break; } @@ -3931,9 +4008,11 @@ class BaseModelSqlv2 { } else { groupingValues = new Set( ( - await this.dbDriver(this.tnPath) - .select(column.column_name) - .distinct() + await this.execAndParse( + this.dbDriver(this.tnPath).select(column.column_name).distinct(), + null, + { raw: true }, + ) ).map((row) => row[column.column_name]), ); groupingValues.add(null); @@ -4132,13 +4211,36 @@ class BaseModelSqlv2 { columns: [new Column({ ...column, title: 'key' })], }); - return await qb; + return await this.execAndParse(qb); } - protected async execAndParse(qb: Knex.QueryBuilder, childTable?: Model) { - let query = qb.toQuery(); + public async execAndParse( + qb: Knex.QueryBuilder | string, + childTable?: Model, + options: { + skipDateConversion?: boolean; + skipAttachmentConversion?: boolean; + raw?: boolean; // alias for skipDateConversion and skipAttachmentConversion + first?: boolean; + } = { + skipDateConversion: false, + skipAttachmentConversion: false, + raw: false, + first: false, + }, + ) { + if (options.raw) { + options.skipDateConversion = true; + options.skipAttachmentConversion = true; + } + + if (options.first && typeof qb !== 'string') { + qb = qb.limit(1); + } + + let query = typeof qb === 'string' ? qb : qb.toQuery(); if (!this.isPg && !this.isMssql && !this.isSnowflake) { - query = unsanitize(qb.toQuery()); + query = unsanitize(query); } else { query = sanitize(query); } @@ -4153,10 +4255,18 @@ class BaseModelSqlv2 { : await this.dbDriver.raw(query); // update attachment fields - data = await this.convertAttachmentType(data, childTable); + if (!options.skipAttachmentConversion) { + data = await this.convertAttachmentType(data, childTable); + } // update date time fields - data = this.convertDateFormat(data, childTable); + if (!options.skipDateConversion) { + data = this.convertDateFormat(data, childTable); + } + + if (options.first) { + return data?.[0]; + } return data; } @@ -4543,7 +4653,9 @@ class BaseModelSqlv2 { } // todo: use bulk insert - await this.dbDriver(vTn).insert(insertData); + await this.execAndParse(this.dbDriver(vTn).insert(insertData), null, { + raw: true, + }); } break; case RelationTypes.HAS_MANY: @@ -4613,7 +4725,7 @@ class BaseModelSqlv2 { : childIds, ); } - await updateQb; + await this.execAndParse(updateQb, null, { raw: true }); } break; case RelationTypes.BELONGS_TO: @@ -4634,18 +4746,22 @@ class BaseModelSqlv2 { } } - await this.dbDriver(childTn) - .update({ - [childColumn.column_name]: this.dbDriver.from( - this.dbDriver(parentTn) - .select(parentColumn.column_name) - .where(_wherePk(parentTable.primaryKeys, childIds[0])) - // .whereIn(parentTable.primaryKey.column_name, childIds) - .first() - .as('___cn_alias'), - ), - }) - .where(_wherePk(childTable.primaryKeys, rowId)); + await this.execAndParse( + this.dbDriver(childTn) + .update({ + [childColumn.column_name]: this.dbDriver.from( + this.dbDriver(parentTn) + .select(parentColumn.column_name) + .where(_wherePk(parentTable.primaryKeys, childIds[0])) + // .whereIn(parentTable.primaryKey.column_name, childIds) + .first() + .as('___cn_alias'), + ), + }) + .where(_wherePk(childTable.primaryKeys, rowId)), + null, + { raw: true }, + ); } break; } @@ -4777,7 +4893,7 @@ class BaseModelSqlv2 { ) : childIds, ); - await delQb; + await this.execAndParse(delQb, null, { raw: true }); } break; case RelationTypes.HAS_MANY: @@ -4823,7 +4939,11 @@ class BaseModelSqlv2 { ); } - await childRowsQb.update({ [childColumn.column_name]: null }); + await this.execAndParse( + childRowsQb.update({ [childColumn.column_name]: null }), + null, + { raw: true }, + ); } break; case RelationTypes.BELONGS_TO: @@ -4849,16 +4969,20 @@ class BaseModelSqlv2 { } } - await this.dbDriver(childTn) - // .where({ - // [childColumn.cn]: this.dbDriver(parentTable.tn) - // .select(parentColumn.cn) - // .where(parentTable.primaryKey.cn, childId) - // .first() - // }) - // .where(_wherePk(childTable.primaryKeys, rowId)) - .where(childTable.primaryKey.column_name, rowId) - .update({ [childColumn.column_name]: null }); + await this.execAndParse( + this.dbDriver(childTn) + // .where({ + // [childColumn.cn]: this.dbDriver(parentTable.tn) + // .select(parentColumn.cn) + // .where(parentTable.primaryKey.cn, childId) + // .first() + // }) + // .where(_wherePk(childTable.primaryKeys, rowId)) + .where(childTable.primaryKey.column_name, rowId) + .update({ [childColumn.column_name]: null }), + null, + { raw: true }, + ); } break; } @@ -4887,9 +5011,11 @@ class BaseModelSqlv2 { (c) => c.id === colId, ); - const row = await this.dbDriver(this.tnPath) - .where(await this._wherePk(id)) - .first(); + const row = await this.execAndParse( + this.dbDriver(this.tnPath).where(await this._wherePk(id)), + null, + { raw: true, first: true }, + ); // validate rowId if (!row) { @@ -4927,7 +5053,9 @@ class BaseModelSqlv2 { await parentModel.selectObject({ qb, fieldsSet: args.fieldSet }); - const parent = (await this.execAndParse(qb, childTable))?.[0]; + const parent = await this.execAndParse(qb, childTable, { + first: true, + }); const proto = await parentModel.getProto(); diff --git a/packages/nocodb/src/db/CustomKnex.ts b/packages/nocodb/src/db/CustomKnex.ts index 11264c026f..077d158c1a 100644 --- a/packages/nocodb/src/db/CustomKnex.ts +++ b/packages/nocodb/src/db/CustomKnex.ts @@ -1020,7 +1020,10 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) { type CustomKnex = Knex; -function CustomKnex(arg: string | Knex.Config | any): CustomKnex { +function CustomKnex( + arg: string | Knex.Config | any, + extDb?: any, +): CustomKnex { // sqlite does not support inserting default values and knex fires a warning without this flag if (arg?.client === 'sqlite3') { arg.useNullAsDefault = true; @@ -1065,6 +1068,14 @@ function CustomKnex(arg: string | Knex.Config | any): CustomKnex { return arg?.searchPath?.[0]; }, }, + extDb: { + enumerable: true, + value: extDb, + }, + isExternal: { + enumerable: false, + value: !!extDb && process.env.NC_DISABLE_MUX !== 'true', + }, }); /** diff --git a/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts index 8057345b48..b7d1fbac65 100644 --- a/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts @@ -948,9 +948,13 @@ export default async function formulaQueryBuilderv2( try { // dry run qb.builder to see if it will break the grid view or not // if so, set formula error and show empty selectQb instead - await knex(baseModelSqlv2.getTnPath(model, tableAlias)) - .select(knex.raw(`?? as ??`, [qb.builder, '__dry_run_alias'])) - .as('dry-run-only'); + await baseModelSqlv2.execAndParse( + knex(baseModelSqlv2.getTnPath(model, tableAlias)) + .select(knex.raw(`?? as ??`, [qb.builder, '__dry_run_alias'])) + .as('dry-run-only'), + null, + { raw: true }, + ); // if column is provided, i.e. formula has been created if (column) { diff --git a/packages/nocodb/src/db/sql-client/lib/KnexClient.ts b/packages/nocodb/src/db/sql-client/lib/KnexClient.ts index bf700c33cf..f617f5b981 100644 --- a/packages/nocodb/src/db/sql-client/lib/KnexClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/KnexClient.ts @@ -1157,7 +1157,7 @@ class KnexClient extends SqlClient { migrationInit(_args) {} async selectAll(tn) { - return await this.sqlClient(tn).select(); + return await this.sqlClient.raw(this.sqlClient(tn).select().toQuery()); } /** @@ -1180,15 +1180,19 @@ class KnexClient extends SqlClient { const result = new Result(); try { - const countResult = await this.sqlClient(args.tn).count(); + const countResult = await this.sqlClient.raw( + this.sqlClient(args.tn).count().toQuery(), + ); result.data.count = Object.values(countResult[0])[0]; const query = this.sqlClient(args.tn) .select() .limit(size) .offset((page - 1) * size); if (orderBy && orderBy.length) - result.data.list = await query.orderBy(orderBy); - else result.data.list = await query; + result.data.list = await this.sqlClient.raw( + query.orderBy(orderBy).toQuery(), + ); + else result.data.list = await this.sqlClient.raw(query.toQuery()); } catch (e) { console.log(e); result.data.list = []; @@ -1226,26 +1230,32 @@ class KnexClient extends SqlClient { // Todo: error handling async insert(args) { const { tn, data } = args; - const res = await this.sqlClient(tn).insert(data); + const res = await this.sqlClient.raw( + this.sqlClient(tn).insert(data).toQuery(), + ); log.debug(res); return res; } async update(args) { const { tn, data, whereConditions } = args; - const res = await this.sqlClient(tn).where(whereConditions).update(data); + const res = await this.sqlClient.raw( + this.sqlClient(tn).where(whereConditions).update(data).toQuery(), + ); return res; } async delete(args) { const { tn, whereConditions } = args; - const res = await this.sqlClient(tn).where(whereConditions).del(); + const res = await this.sqlClient.raw( + this.sqlClient(tn).where(whereConditions).del().toQuery(), + ); log.debug(res); return res; } async remove(tn, where) { - await this.sqlClient(tn).del().where(where); + await this.sqlClient.raw(this.sqlClient(tn).del().where(where).toQuery()); } hasTable(_tn) {} @@ -1712,31 +1722,36 @@ class KnexClient extends SqlClient { args.sqlClient = this.sqlClient; /** ************** create table *************** */ - await this.sqlClient.schema.createTable(args.table, function (table) { - const multiplePks = []; - const columns = JSON.parse(JSON.stringify(args.columns)); - - // copy PKs to new array and set PK metadata to false in original columns - for (let i = 0; i < columns.length; ++i) { - if (columns[i].pk) { - multiplePks.push(i); - columns[i].pk = false; - columns[i].ai = false; - } - } + const query = this.sqlClient.schema.createTable( + args.table, + function (table) { + const multiplePks = []; + const columns = JSON.parse(JSON.stringify(args.columns)); - if (multiplePks.length > 1) { + // copy PKs to new array and set PK metadata to false in original columns for (let i = 0; i < columns.length; ++i) { - columnCreate(args.sqlClient, table, columns[i]); + if (columns[i].pk) { + multiplePks.push(i); + columns[i].pk = false; + columns[i].ai = false; + } } - createPks(table, args.columns, multiplePks); - } else { - for (let i = 0; i < args.columns.length; ++i) { - columnCreate(args.sqlClient, table, args.columns[i]); + if (multiplePks.length > 1) { + for (let i = 0; i < columns.length; ++i) { + columnCreate(args.sqlClient, table, columns[i]); + } + + createPks(table, args.columns, multiplePks); + } else { + for (let i = 0; i < args.columns.length; ++i) { + columnCreate(args.sqlClient, table, args.columns[i]); + } } - } - }); + }, + ); + + await this.sqlClient.raw(query.toQuery()); /** ************** create up & down statements *************** */ const upStatement = this.sqlClient.schema @@ -1799,7 +1814,9 @@ class KnexClient extends SqlClient { args.table = args.tn; /** ************** create table *************** */ - await this.sqlClient.schema.renameTable(args.tn_old, args.tn); + await this.sqlClient.raw( + this.sqlClient.schema.renameTable(args.tn_old, args.tn).toQuery(), + ); /** ************** create up & down statements *************** */ const upStatement = @@ -2013,41 +2030,46 @@ class KnexClient extends SqlClient { /** ************** END : has PK changed *************** */ /** ************** update table *************** */ - await this.sqlClient.schema.alterTable(args.table, function (table) { - if (pksChanged) { - pkUpdate(table, args.columns, args.originalColumns); - } else { - for (let i = 0; i < args.columns.length; ++i) { - const column = find(originalColumns, { - cn: args.columns[i].cno, - }); - - if (args.columns[i].altered & 8) { - // TODO: If a column is getting renamed then - // any change to column data type - // or changes to other columns are ignored - renamed = true; - renamedUpDownStatement = renameColumn( - args.sqlClient, - args.connectionConfig, - table, - column, - args.columns[i], - ); - result.data.object = renamedUpDownStatement; - } else if (args.columns[i].altered & 4) { - // col remove - removeColumn(table, args.columns[i], column); - } else if (args.columns[i].altered & 2) { - // col edit - columnUpdate(args.sqlClient, table, args.columns[i], column); - } else if (args.columns[i].altered & 1) { - // col addition - columnUpdate(args.sqlClient, table, args.columns[i], null); + const query = this.sqlClient.schema.alterTable( + args.table, + function (table) { + if (pksChanged) { + pkUpdate(table, args.columns, args.originalColumns); + } else { + for (let i = 0; i < args.columns.length; ++i) { + const column = find(originalColumns, { + cn: args.columns[i].cno, + }); + + if (args.columns[i].altered & 8) { + // TODO: If a column is getting renamed then + // any change to column data type + // or changes to other columns are ignored + renamed = true; + renamedUpDownStatement = renameColumn( + args.sqlClient, + args.connectionConfig, + table, + column, + args.columns[i], + ); + result.data.object = renamedUpDownStatement; + } else if (args.columns[i].altered & 4) { + // col remove + removeColumn(table, args.columns[i], column); + } else if (args.columns[i].altered & 2) { + // col edit + columnUpdate(args.sqlClient, table, args.columns[i], column); + } else if (args.columns[i].altered & 1) { + // col addition + columnUpdate(args.sqlClient, table, args.columns[i], null); + } } } - } - }); + }, + ); + + await this.sqlClient.raw(query.toQuery()); // log.debug('after column change', r); @@ -2199,7 +2221,9 @@ class KnexClient extends SqlClient { this.emit(`Success : ${upStatement}`); /** ************** drop tn *************** */ - await this.sqlClient.schema.dropTable(args.tn); + await this.sqlClient.raw( + this.sqlClient.schema.dropTable(args.tn).toQuery(), + ); /** ************** return files *************** */ result.data.object = { @@ -2234,7 +2258,7 @@ class KnexClient extends SqlClient { args.table = args.tn; // s = await this.sqlClient.schema.index(Object.keys(args.columns)); - await this.sqlClient.schema.table(args.table, function (table) { + const query = this.sqlClient.schema.table(args.table, function (table) { if (args.non_unique) { table.index(args.columns, indexName); } else { @@ -2242,6 +2266,8 @@ class KnexClient extends SqlClient { } }); + await this.sqlClient.raw(query.toQuery()); + const upStatement = this.querySeparator() + this.sqlClient.schema @@ -2305,7 +2331,7 @@ class KnexClient extends SqlClient { args.table = args.tn; // s = await this.sqlClient.schema.index(Object.keys(args.columns)); - await this.sqlClient.schema.table(args.table, function (table) { + const query = this.sqlClient.schema.table(args.table, function (table) { if (args.non_unique_original) { table.dropIndex(args.columns, indexName); } else { @@ -2313,6 +2339,8 @@ class KnexClient extends SqlClient { } }); + await this.sqlClient.raw(query.toQuery()); + const upStatement = this.querySeparator() + this.sqlClient.schema @@ -2385,7 +2413,7 @@ class KnexClient extends SqlClient { }, ); - await upQb; + await this.sqlClient.raw(upQb.toQuery()); const upStatement = this.querySeparator() + upQb.toQuery(); @@ -2444,9 +2472,14 @@ class KnexClient extends SqlClient { try { // const self = this; - await this.sqlClient.schema.table(args.childTable, function (table) { - table.dropForeign(args.childColumn, foreignKeyName); - }); + const query = this.sqlClient.schema.table( + args.childTable, + function (table) { + table.dropForeign(args.childColumn, foreignKeyName); + }, + ); + + await this.sqlClient.raw(query.toQuery()); const upStatement = this.querySeparator() + @@ -2456,16 +2489,19 @@ class KnexClient extends SqlClient { }) .toQuery(); - const downStatement = - this.querySeparator() + - (await this.sqlClient.schema - .table(args.childTable, function (table) { - table - .foreign(args.childColumn, foreignKeyName) - .references(args.parentColumn) - .on(args.parentTable); - }) - .toQuery()); + const downQuery = this.sqlClient.schema.table( + args.childTable, + function (table) { + table + .foreign(args.childColumn, foreignKeyName) + .references(args.parentColumn) + .on(args.parentTable); + }, + ); + + await this.sqlClient.raw(downQuery.toQuery()); + + const downStatement = this.querySeparator() + downQuery.toQuery(); // let files = this.evolutionFilesCreate(args, upStatement, downStatement); // diff --git a/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts b/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts index 4b5726d170..3aaa794ee4 100644 --- a/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts @@ -355,20 +355,26 @@ class MysqlClient extends KnexClient { try { /** ************** START : create _evolution table if not exists *************** */ - const exists = await this.sqlClient.schema.hasTable(args.tn); + const exists = await this.sqlClient.raw( + this.sqlClient.schema.hasTable(args.tn).toQuery(), + ); if (!exists) { - await this.sqlClient.schema.createTable(args.tn, function (table) { - table.increments(); - table.string('title').notNullable(); - table.string('titleDown').nullable(); - table.string('description').nullable(); - table.integer('batch').nullable(); - table.string('checksum').nullable(); - table.integer('status').nullable(); - table.dateTime('created'); - table.timestamps(); - }); + await this.sqlClient.raw( + this.sqlClient.schema + .createTable(args.tn, function (table) { + table.increments(); + table.string('title').notNullable(); + table.string('titleDown').nullable(); + table.string('description').nullable(); + table.integer('batch').nullable(); + table.string('checksum').nullable(); + table.integer('status').nullable(); + table.dateTime('created'); + table.timestamps(); + }) + .toQuery(), + ); log.debug('Table created:', `${args.tn}`); } else { log.debug(`${args.tn} tables exists`); @@ -411,7 +417,9 @@ class MysqlClient extends KnexClient { log.api(`${func}:args:`, args); try { - const response = await this.sqlClient.schema.hasTable(args.tn); + const response = await this.sqlClient.raw( + this.sqlClient.schema.hasTable(args.tn).toQuery(), + ); result.data.value = response; } catch (e) { log.ppe(e, func); @@ -2205,7 +2213,9 @@ class MysqlClient extends KnexClient { this.emit(`Success : ${upStatement}`); /** ************** drop table_name *************** */ - await this.sqlClient.schema.dropTable(args.table_name); + await this.sqlClient.raw( + this.sqlClient.schema.dropTable(args.table_name).toQuery(), + ); /** ************** return files *************** */ result.data.object = { diff --git a/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts b/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts index cefce1e6cb..379aa57e49 100644 --- a/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts @@ -575,9 +575,8 @@ class PGClient extends KnexClient { ); if (exists.rows.length === 0) { - const data = await this.sqlClient.schema.createTable( - args.tn, - function (table) { + const data = await this.sqlClient.raw( + this.sqlClient.schema.createTable(args.tn, function (table) { table.increments(); table.string('title').notNullable(); table.string('titleDown').nullable(); @@ -587,7 +586,7 @@ class PGClient extends KnexClient { table.integer('status').nullable(); table.dateTime('created'); table.timestamps(); - }, + }), ); log.debug('Table created:', `${args.tn}`, data); } else { @@ -1039,11 +1038,13 @@ class PGClient extends KnexClient { try { // const self = this; - await this.sqlClient.schema.table( - args.childTableWithSchema, - function (table) { - table.dropForeign(args.childColumn, foreignKeyName); - }, + await this.sqlClient.raw( + this.sqlClient.schema.table( + args.childTableWithSchema, + function (table) { + table.dropForeign(args.childColumn, foreignKeyName); + }, + ), ); const upStatement = @@ -1056,14 +1057,14 @@ class PGClient extends KnexClient { const downStatement = this.querySeparator() + - (await this.sqlClient.schema + this.sqlClient.schema .table(args.childTableWithSchema, function (table) { table .foreign(args.childColumn, foreignKeyName) .references(args.parentColumn) .on(args.parentTableWithSchema); }) - .toQuery()); + .toQuery(); result.data.object = { upStatement: [{ sql: upStatement }], @@ -2507,23 +2508,25 @@ class PGClient extends KnexClient { relationsList = relationsList.data.list; for (const relation of relationsList) { - downQuery += - this.querySeparator() + - (await this.sqlClient.schema - .table(relation.tn, function (table) { - table = table - .foreign(relation.cn, null) - .references(relation.rcn) - .on(relation.rtn); - - if (relation.ur) { - table = table.onUpdate(relation.ur); - } - if (relation.dr) { - table.onDelete(relation.dr); - } - }) - .toQuery()); + const query = this.sqlClient.raw( + this.sqlClient.schema.table(relation.tn, function (table) { + table = table + .foreign(relation.cn, null) + .references(relation.rcn) + .on(relation.rtn); + + if (relation.ur) { + table = table.onUpdate(relation.ur); + } + if (relation.dr) { + table.onDelete(relation.dr); + } + }), + ); + + downQuery += this.querySeparator() + query; + + await query; } let indexList: any = await this.indexList(args); @@ -2565,7 +2568,9 @@ class PGClient extends KnexClient { this.emit(`Success : ${upStatement}`); /** ************** drop tn *************** */ - await this.sqlClient.schema.dropTable(args.tn); + await this.sqlClient.raw( + this.sqlClient.schema.dropTable(args.tn).toQuery(), + ); /** ************** return files *************** */ result.data.object = { @@ -2989,9 +2994,11 @@ class PGClient extends KnexClient { args.table = args.tn; /** ************** create table *************** */ - await this.sqlClient.schema.renameTable( - this.sqlClient.raw('??.??', [this.schema, args.tn_old]), - args.tn, + await this.sqlClient.raw( + this.sqlClient.schema.renameTable( + this.sqlClient.raw('??.??', [this.schema, args.tn_old]), + args.tn, + ), ); /** ************** create up & down statements *************** */ diff --git a/packages/nocodb/src/models/Source.ts b/packages/nocodb/src/models/Source.ts index 2ad9ba8679..3b9dd09108 100644 --- a/packages/nocodb/src/models/Source.ts +++ b/packages/nocodb/src/models/Source.ts @@ -80,15 +80,15 @@ export default class Source implements SourceType { insertObj, ); + // call before reorder to update cache + const returnBase = await this.get(id, false, ncMeta); + await NocoCache.appendToList( CacheScope.BASE, [source.baseId], `${CacheScope.BASE}:${id}`, ); - // call before reorder to update cache - const returnBase = await this.get(id, false, ncMeta); - await this.reorderBases(source.baseId); return returnBase; @@ -101,6 +101,7 @@ export default class Source implements SourceType { skipReorder?: boolean; meta?: any; deleted?: boolean; + fk_sql_executor_id?: string; }, ncMeta = Noco.ncMeta, ) { @@ -108,12 +109,6 @@ export default class Source implements SourceType { if (!oldBase) NcError.badRequest('Wrong source id!'); - await NocoCache.deepDel( - CacheScope.BASE, - `${CacheScope.BASE}:${sourceId}`, - CacheDelDirection.CHILD_TO_PARENT, - ); - const updateObj = extractProps(source, [ 'alias', 'config', @@ -125,6 +120,7 @@ export default class Source implements SourceType { 'enabled', 'meta', 'deleted', + 'fk_sql_executor_id', ]); if (updateObj.config) { @@ -151,17 +147,14 @@ export default class Source implements SourceType { oldBase.id, ); - await NocoCache.appendToList( - CacheScope.BASE, - [source.baseId], - `${CacheScope.BASE}:${oldBase.id}`, - ); + await NocoCache.del(`${CacheScope.BASE}:${sourceId}`); // call before reorder to update cache const returnBase = await this.get(oldBase.id, false, ncMeta); - if (!source.skipReorder) + if (!source.skipReorder && source.order && source.order !== oldBase.order) { await this.reorderBases(source.baseId, returnBase.id, ncMeta); + } return returnBase; } @@ -312,12 +305,6 @@ export default class Source implements SourceType { // update order for sources for (const [i, b] of Object.entries(sources)) { - await NocoCache.deepDel( - CacheScope.BASE, - `${CacheScope.BASE}:${b.id}`, - CacheDelDirection.CHILD_TO_PARENT, - ); - b.order = parseInt(i) + 1; await ncMeta.metaUpdate( @@ -330,12 +317,6 @@ export default class Source implements SourceType { b.id, ); - await NocoCache.appendToList( - CacheScope.BASE, - [b.base_id], - `${CacheScope.BASE}:${b.id}`, - ); - await NocoCache.set(`${CacheScope.BASE}:${b.id}`, b); } } diff --git a/packages/nocodb/src/services/columns.service.ts b/packages/nocodb/src/services/columns.service.ts index 18bacbd890..62a1e6ae29 100644 --- a/packages/nocodb/src/services/columns.service.ts +++ b/packages/nocodb/src/services/columns.service.ts @@ -293,7 +293,7 @@ export class ColumnsService { ) { // MultiSelect to SingleSelect if (driverType === 'mysql' || driverType === 'mysql2') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = SUBSTRING_INDEX(??, ',', 1) WHERE ?? LIKE '%,%';`, [ baseModel.getTnPath(table.table_name), @@ -303,13 +303,13 @@ export class ColumnsService { ], ); } else if (driverType === 'pg') { - await dbDriver.raw(`UPDATE ?? SET ?? = split_part(??, ',', 1);`, [ + await sqlClient.raw(`UPDATE ?? SET ?? = split_part(??, ',', 1);`, [ baseModel.getTnPath(table.table_name), column.column_name, column.column_name, ]); } else if (driverType === 'mssql') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = LEFT(cast(?? as varchar(max)), CHARINDEX(',', ??) - 1) WHERE CHARINDEX(',', ??) > 0;`, [ baseModel.getTnPath(table.table_name), @@ -320,7 +320,7 @@ export class ColumnsService { ], ); } else if (driverType === 'sqlite3') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = substr(??, 1, instr(??, ',') - 1) WHERE ?? LIKE '%,%';`, [ baseModel.getTnPath(table.table_name), @@ -352,7 +352,7 @@ export class ColumnsService { ); const data = await baseModel.execAndParse( - dbDriver.raw('SELECT DISTINCT ?? FROM ??', [ + sqlClient.raw('SELECT DISTINCT ?? FROM ??', [ column.column_name, baseModel.getTnPath(table.table_name), ]), @@ -535,7 +535,7 @@ export class ColumnsService { } if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [ + await sqlClient.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [ baseModel.getTnPath(table.table_name), column.column_name, column.column_name, @@ -551,7 +551,7 @@ export class ColumnsService { } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { if (colBody.dt === 'set') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ',')) WHERE FIND_IN_SET(?, ??)`, [ baseModel.getTnPath(table.table_name), @@ -563,7 +563,7 @@ export class ColumnsService { ], ); } else { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ','))`, [ baseModel.getTnPath(table.table_name), @@ -574,7 +574,7 @@ export class ColumnsService { ); } } else if (driverType === 'pg') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = array_to_string(array_remove(string_to_array(??, ','), ?), ',')`, [ baseModel.getTnPath(table.table_name), @@ -584,7 +584,7 @@ export class ColumnsService { ], ); } else if (driverType === 'mssql') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), ','), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), ',')) - 2)`, [ baseModel.getTnPath(table.table_name), @@ -596,7 +596,7 @@ export class ColumnsService { ], ); } else if (driverType === 'sqlite3') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ','), ',')`, [ baseModel.getTnPath(table.table_name), @@ -716,7 +716,7 @@ export class ColumnsService { if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [ + await sqlClient.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [ baseModel.getTnPath(table.table_name), column.column_name, newOp.title, @@ -733,7 +733,7 @@ export class ColumnsService { } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { if (colBody.dt === 'set') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [ baseModel.getTnPath(table.table_name), @@ -746,7 +746,7 @@ export class ColumnsService { ], ); } else { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ',')))`, [ baseModel.getTnPath(table.table_name), @@ -758,7 +758,7 @@ export class ColumnsService { ); } } else if (driverType === 'pg') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [ baseModel.getTnPath(table.table_name), @@ -769,7 +769,7 @@ export class ColumnsService { ], ); } else if (driverType === 'mssql') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [ baseModel.getTnPath(table.table_name), @@ -783,7 +783,7 @@ export class ColumnsService { ], ); } else if (driverType === 'sqlite3') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [ baseModel.getTnPath(table.table_name), @@ -802,7 +802,7 @@ export class ColumnsService { const newOp = ch.def_option; if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [ + await sqlClient.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [ baseModel.getTnPath(table.table_name), column.column_name, newOp.title, @@ -819,7 +819,7 @@ export class ColumnsService { } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { if (colBody.dt === 'set') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [ baseModel.getTnPath(table.table_name), @@ -832,7 +832,7 @@ export class ColumnsService { ], ); } else { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ',')))`, [ baseModel.getTnPath(table.table_name), @@ -846,7 +846,7 @@ export class ColumnsService { ); } } else if (driverType === 'pg') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [ baseModel.getTnPath(table.table_name), @@ -857,7 +857,7 @@ export class ColumnsService { ], ); } else if (driverType === 'mssql') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [ baseModel.getTnPath(table.table_name), @@ -871,7 +871,7 @@ export class ColumnsService { ], ); } else if (driverType === 'sqlite3') { - await dbDriver.raw( + await sqlClient.raw( `UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [ baseModel.getTnPath(table.table_name), diff --git a/packages/nocodb/src/services/tables.service.ts b/packages/nocodb/src/services/tables.service.ts index 3ccd278b0d..1e1f43b2e1 100644 --- a/packages/nocodb/src/services/tables.service.ts +++ b/packages/nocodb/src/services/tables.service.ts @@ -491,7 +491,7 @@ export class TablesService { system?: boolean; } > = ( - await sqlClient.columnList({ + await sqlMgr.sqlOpPlus(source, 'columnList', { tn: tableCreatePayLoad.table_name, schema: source.getConfig()?.schema, }) diff --git a/tests/playwright/pages/Dashboard/ProjectView/Metadata.ts b/tests/playwright/pages/Dashboard/ProjectView/Metadata.ts index fb821c4897..cbddf82810 100644 --- a/tests/playwright/pages/Dashboard/ProjectView/Metadata.ts +++ b/tests/playwright/pages/Dashboard/ProjectView/Metadata.ts @@ -18,7 +18,7 @@ export class MetaDataPage extends BasePage { // todo: Remove this wait await this.rootPage.waitForTimeout(100); // await this.get().locator(`.animate-spin`).waitFor({state: 'visible'}); - await this.get().locator(`.animate-spin`).waitFor({ state: 'detached' }); + await this.get().locator(`.animate-spin`).waitFor({ state: 'detached', timeout: 10000 }); } async close() { @@ -32,7 +32,7 @@ export class MetaDataPage extends BasePage { await this.get().locator(`button:has-text("Sync Now")`).click(); await this.verifyToast({ message: 'Table metadata recreated successfully' }); await this.get().locator(`.animate-spin`).waitFor({ state: 'visible' }); - await this.get().locator(`.animate-spin`).waitFor({ state: 'detached' }); + await this.get().locator(`.animate-spin`).waitFor({ state: 'detached', timeout: 10000 }); } async verifyRow({ index, model, state }: { index: number; model: string; state: string }) { diff --git a/tests/playwright/tests/db/features/metaSync.spec.ts b/tests/playwright/tests/db/features/metaSync.spec.ts index 7e342abfdf..61517f1fbd 100644 --- a/tests/playwright/tests/db/features/metaSync.spec.ts +++ b/tests/playwright/tests/db/features/metaSync.spec.ts @@ -43,7 +43,7 @@ test.describe('Meta sync', () => { await dbExec(`CREATE TABLE table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`); await metaData.clickReload(); - await dashboard.rootPage.waitForTimeout(1000); + await dashboard.rootPage.waitForTimeout(5000); await metaData.verifyRow({ index: isPg(context) ? 21 : 16,