Browse Source

Merge pull request #7970 from nocodb/nc-feat/2600

fix: type issues with SqlClient
pull/7983/head
Mert E 8 months ago committed by GitHub
parent
commit
08cd1240cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 52
      packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue
  2. 7
      packages/nc-gui/components/dlg/TableCreate.vue
  3. 3
      packages/nc-gui/composables/useTableNew.ts
  4. 5
      packages/nc-gui/store/base.ts
  5. 12
      packages/nc-gui/utils/baseCreateUtils.ts
  6. 4
      packages/nocodb-sdk/src/lib/Api.ts
  7. 1
      packages/nocodb/.gitignore
  8. 3
      packages/nocodb/src/db/CustomKnex.ts
  9. 6
      packages/nocodb/src/db/sql-client/lib/SqlClient.ts
  10. 5
      packages/nocodb/src/db/sql-client/lib/SqlClientFactory.ts
  11. 2
      packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts
  12. 2
      packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts
  13. 2621
      packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts
  14. 5
      packages/nocodb/src/db/sql-client/lib/snowflake/snowflake.queries.ts
  15. 3
      packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts
  16. 8
      packages/nocodb/src/db/sql-mgr/SqlMgr.ts
  17. 6
      packages/nocodb/src/db/sql-mgr/v2/SqlMgrv2.ts
  18. 12
      packages/nocodb/src/db/sql-migrator/lib/KnexMigrator.ts
  19. 8
      packages/nocodb/src/db/sql-migrator/lib/KnexMigratorv2Tans.ts
  20. 4
      packages/nocodb/src/services/columns.service.ts

52
packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue

@ -2,7 +2,7 @@
import type { SourceType } from 'nocodb-sdk' import type { SourceType } from 'nocodb-sdk'
import { Form, message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue'
import type { SelectHandler } from 'ant-design-vue/es/vc-select/Select' import type { SelectHandler } from 'ant-design-vue/es/vc-select/Select'
import type { DefaultConnection, ProjectCreateForm, SQLiteConnection } from '#imports' import type { DefaultConnection, ProjectCreateForm, SQLiteConnection, SnowflakeConnection } from '#imports'
import { import {
CertTypes, CertTypes,
ClientType, ClientType,
@ -387,6 +387,56 @@ onMounted(async () => {
<a-input v-model:value="(formState.dataSource.connection as SQLiteConnection).connection.filename" /> <a-input v-model:value="(formState.dataSource.connection as SQLiteConnection).connection.filename" />
</a-form-item> </a-form-item>
<template v-else-if="formState.dataSource.client === ClientType.SNOWFLAKE">
<!-- Account -->
<a-form-item :label="$t('labels.account')" v-bind="validateInfos['dataSource.connection.account']">
<a-input
v-model:value="(formState.dataSource.connection as SnowflakeConnection).account"
class="nc-extdb-host-address"
/>
</a-form-item>
<!-- Username -->
<a-form-item :label="$t('labels.username')" v-bind="validateInfos['dataSource.connection.username']">
<a-input
v-model:value="(formState.dataSource.connection as SnowflakeConnection).username"
class="nc-extdb-host-user"
/>
</a-form-item>
<!-- Password -->
<a-form-item :label="$t('labels.password')" v-bind="validateInfos['dataSource.connection.password']">
<a-input-password
v-model:value="(formState.dataSource.connection as SnowflakeConnection).password"
class="nc-extdb-host-password"
/>
</a-form-item>
<!-- Warehouse -->
<a-form-item label="Warehouse" v-bind="validateInfos['dataSource.connection.warehouse']">
<a-input
v-model:value="(formState.dataSource.connection as SnowflakeConnection).warehouse"
class="nc-extdb-host-database"
/>
</a-form-item>
<!-- Database -->
<a-form-item :label="$t('labels.database')" v-bind="validateInfos['dataSource.connection.database']">
<a-input
v-model:value="(formState.dataSource.connection as SnowflakeConnection).database"
class="nc-extdb-host-database"
/>
</a-form-item>
<!-- Schema -->
<a-form-item label="Schema" v-bind="validateInfos['dataSource.connection.schema']">
<a-input
v-model:value="(formState.dataSource.connection as SnowflakeConnection).schema"
class="nc-extdb-host-database"
/>
</a-form-item>
</template>
<template v-else> <template v-else>
<!-- Host Address --> <!-- Host Address -->
<a-form-item :label="$t('labels.hostAddress')" v-bind="validateInfos['dataSource.connection.host']"> <a-form-item :label="$t('labels.hostAddress')" v-bind="validateInfos['dataSource.connection.host']">

7
packages/nc-gui/components/dlg/TableCreate.vue

@ -30,7 +30,7 @@ const inputEl = ref<HTMLInputElement>()
const { addTab } = useTabs() const { addTab } = useTabs()
const { isMysql, isMssql, isPg } = useBase() const { isMysql, isMssql, isPg, isSnowflake } = useBase()
const { loadProjectTables, addTable } = useTablesStore() const { loadProjectTables, addTable } = useTablesStore()
@ -145,7 +145,7 @@ onMounted(() => {
</template> </template>
<div class="flex flex-col mt-2"> <div class="flex flex-col mt-2">
<a-form :model="table" name="create-new-table-form" @keydown.enter="_createTable" @keydown.esc="dialogShow = false"> <a-form :model="table" name="create-new-table-form" @keydown.enter="_createTable" @keydown.esc="dialogShow = false">
<a-form-item v-bind="validateInfos.title"> <a-form-item v-bind="validateInfos.title" :class="{ '!mb-1': isSnowflake(props.sourceId) }">
<a-input <a-input
ref="inputEl" ref="inputEl"
v-model:value="table.title" v-model:value="table.title"
@ -155,6 +155,9 @@ onMounted(() => {
:placeholder="$t('msg.info.enterTableName')" :placeholder="$t('msg.info.enterTableName')"
/> />
</a-form-item> </a-form-item>
<template v-if="isSnowflake(props.sourceId)">
<a-checkbox v-model:checked="table.is_hybrid" class="!flex flex-row items-center"> Hybrid Table </a-checkbox>
</template>
<div class="nc-table-advanced-options" :class="{ active: isAdvanceOptVisible }"> <div class="nc-table-advanced-options" :class="{ active: isAdvanceOptVisible }">
<div> <div>
<div class="mb-1"> <div class="mb-1">

3
packages/nc-gui/composables/useTableNew.ts

@ -23,10 +23,11 @@ import {
} from '#imports' } from '#imports'
export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => void; baseId: string; sourceId?: string }) { export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => void; baseId: string; sourceId?: string }) {
const table = reactive<{ title: string; table_name: string; columns: string[] }>({ const table = reactive<{ title: string; table_name: string; columns: string[]; is_hybrid: boolean }>({
title: '', title: '',
table_name: '', table_name: '',
columns: SYSTEM_COLUMNS, columns: SYSTEM_COLUMNS,
is_hybrid: true,
}) })
const { t } = useI18n() const { t } = useI18n()

5
packages/nc-gui/store/base.ts

@ -104,6 +104,10 @@ export const useBase = defineStore('baseStore', () => {
return getBaseType(sourceId) === 'pg' return getBaseType(sourceId) === 'pg'
} }
function isSnowflake(sourceId?: string) {
return getBaseType(sourceId) === 'snowflake'
}
function isXcdbBase(sourceId?: string) { function isXcdbBase(sourceId?: string) {
const source = sources.value.find((source) => source.id === sourceId) const source = sources.value.find((source) => source.id === sourceId)
return (source?.is_meta as boolean) || (source?.is_local as boolean) || false return (source?.is_meta as boolean) || (source?.is_local as boolean) || false
@ -284,6 +288,7 @@ export const useBase = defineStore('baseStore', () => {
isMssql, isMssql,
isPg, isPg,
isSqlite, isSqlite,
isSnowflake,
sqlUis, sqlUis,
isSharedBase, isSharedBase,
isSharedErd, isSharedErd,

12
packages/nc-gui/utils/baseCreateUtils.ts

@ -137,12 +137,12 @@ const sampleConnectionData: { [key in ConnectionClientType]: DefaultConnection }
useNullAsDefault: true, useNullAsDefault: true,
}, },
[ClientType.SNOWFLAKE]: { [ClientType.SNOWFLAKE]: {
account: 'account', account: 'LOCATOR.REGION',
username: 'username', username: 'USERNAME',
password: 'password', password: 'PASSWORD',
warehouse: 'warehouse', warehouse: 'COMPUTE_WH',
database: 'database', database: 'DATABASE',
schema: 'schema', schema: 'PUBLIC',
}, },
tidb: { tidb: {
host: defaultHost, host: defaultHost,

4
packages/nocodb-sdk/src/lib/Api.ts

@ -11100,7 +11100,7 @@ export class Api<
* @tags DB Data Table Row * @tags DB Data Table Row
* @name Update * @name Update
* @summary Update Table Rows * @summary Update Table Rows
* @request PUT:/api/v2/tables/{tableId}/records * @request PATCH:/api/v2/tables/{tableId}/records
* @response `200` `any` OK * @response `200` `any` OK
* @response `400` `{ * @response `400` `{
\** @example BadRequest [Error]: <ERROR MESSAGE> *\ \** @example BadRequest [Error]: <ERROR MESSAGE> *\
@ -11125,7 +11125,7 @@ export class Api<
} }
>({ >({
path: `/api/v2/tables/${tableId}/records`, path: `/api/v2/tables/${tableId}/records`,
method: 'PUT', method: 'PATCH',
query: query, query: query,
body: data, body: data,
type: ContentType.Json, type: ContentType.Json,

1
packages/nocodb/.gitignore vendored

@ -45,5 +45,6 @@ test_sakila_?.db
# nc-gui dir is copied for building local docker. # nc-gui dir is copied for building local docker.
/docker/main.js /docker/main.js
/docker/nc-gui/ /docker/nc-gui/
/docker/public/
/tests/unit/.env /tests/unit/.env

3
packages/nocodb/src/db/CustomKnex.ts

@ -1,5 +1,4 @@
import { Knex, knex } from 'knex'; import { Knex, knex } from 'knex';
import { SnowflakeClient } from 'nc-help';
import { defaults, types } from 'pg'; import { defaults, types } from 'pg';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import type { FilterType } from 'nocodb-sdk'; import type { FilterType } from 'nocodb-sdk';
@ -1029,8 +1028,6 @@ function CustomKnex(
arg.useNullAsDefault = true; arg.useNullAsDefault = true;
} }
if (arg?.client === 'snowflake') arg.client = SnowflakeClient;
const kn: any = knex(arg); const kn: any = knex(arg);
const knexRaw = kn.raw; const knexRaw = kn.raw;

6
packages/nocodb/src/db/sql-client/lib/SqlClient.ts

@ -1,6 +1,8 @@
class SqlClient { class SqlClient {
protected connectionConfig: any; protected connectionConfig: any;
protected sqlClient: any; protected sqlClient: any;
protected queries: any;
protected _version: any;
constructor(connectionConfig) { constructor(connectionConfig) {
this.connectionConfig = connectionConfig; this.connectionConfig = connectionConfig;
@ -108,7 +110,9 @@ class SqlClient {
async tableSelectStatement(_args): Promise<any> {} async tableSelectStatement(_args): Promise<any> {}
async totalRecords(_args): Promise<any> {} async totalRecords(_args?): Promise<any> {}
async getDefaultByteaOutputFormat(_args = {}): Promise<any> {}
} }
export default SqlClient; export default SqlClient;

5
packages/nocodb/src/db/sql-client/lib/SqlClientFactory.ts

@ -71,11 +71,6 @@ export default class {
} }
} }
// todo: tobe done
// if (Noco.isEE()) {
// return SqlClientFactoryEE.create(connectionConfig);
// }
return SqlClientFactory.create(connectionConfig); return SqlClientFactory.create(connectionConfig);
} }
} }

2
packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts

@ -20,8 +20,6 @@ const log = new Debug('MysqlClient');
const evt = new Emit(); const evt = new Emit();
class MysqlClient extends KnexClient { class MysqlClient extends KnexClient {
protected queries: any;
protected _version: any;
protected types: any; protected types: any;
constructor(connectionConfig) { constructor(connectionConfig) {

2
packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts

@ -11,8 +11,6 @@ import queries from '~/db/sql-client/lib/pg/pg.queries';
const log = new Debug('PGClient'); const log = new Debug('PGClient');
class PGClient extends KnexClient { class PGClient extends KnexClient {
protected queries: any;
protected _version: any;
constructor(connectionConfig) { constructor(connectionConfig) {
super(connectionConfig); super(connectionConfig);
// this.sqlClient = null; // this.sqlClient = null;

2621
packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts

File diff suppressed because it is too large Load Diff

5
packages/nocodb/src/db/sql-client/lib/snowflake/snowflake.queries.ts

@ -1,5 +0,0 @@
// Snowflake queries
const sfQueries = {};
export default sfQueries;

3
packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts

@ -15,9 +15,6 @@ const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 6);
const log = new Debug('SqliteClient'); const log = new Debug('SqliteClient');
class SqliteClient extends KnexClient { class SqliteClient extends KnexClient {
private queries: any;
private _version: any;
constructor(connectionConfig) { constructor(connectionConfig) {
// sqlite does not support inserting default values and knex fires a warning without this flag // sqlite does not support inserting default values and knex fires a warning without this flag
connectionConfig.connection.useNullAsDefault = true; connectionConfig.connection.useNullAsDefault = true;

8
packages/nocodb/src/db/sql-mgr/SqlMgr.ts

@ -12,7 +12,6 @@ import type MssqlClient from '~/db/sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '~/db/sql-client/lib/mysql/MysqlClient'; import type MysqlClient from '~/db/sql-client/lib/mysql/MysqlClient';
import type OracleClient from '~/db/sql-client/lib/oracle/OracleClient'; import type OracleClient from '~/db/sql-client/lib/oracle/OracleClient';
import type PGClient from '~/db/sql-client/lib/pg/PgClient'; import type PGClient from '~/db/sql-client/lib/pg/PgClient';
import type SnowflakeClient from '~/db/sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '~/db/sql-client/lib/sqlite/SqliteClient'; import type SqliteClient from '~/db/sql-client/lib/sqlite/SqliteClient';
import Result from '~/db/util/Result'; import Result from '~/db/util/Result';
import Debug from '~/db/util/Debug'; import Debug from '~/db/util/Debug';
@ -344,12 +343,7 @@ export default class SqlMgr {
public async baseGetSqlClient( public async baseGetSqlClient(
args, args,
): Promise< ): Promise<
| SnowflakeClient MysqlClient | SqliteClient | MssqlClient | OracleClient | PGClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> { > {
const func = this.baseGetSqlClient.name; const func = this.baseGetSqlClient.name;
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);

6
packages/nocodb/src/db/sql-mgr/v2/SqlMgrv2.ts

@ -1,11 +1,11 @@
// import debug from 'debug'; // import debug from 'debug';
// import {XKnex} from "../sql-data-mapper"; // import {XKnex} from "../sql-data-mapper";
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
import KnexMigratorv2 from '../../sql-migrator/lib/KnexMigratorv2';
import Debug from '../../util/Debug';
import type { MetaService } from '~/meta/meta.service'; import type { MetaService } from '~/meta/meta.service';
import type Source from '~/models/Source'; import type Source from '~/models/Source';
import SqlClientFactory from '~/db/sql-client/lib/SqlClientFactory';
import KnexMigratorv2 from '~/db/sql-migrator/lib/KnexMigratorv2';
import Debug from '~/db/util/Debug';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
const log = new Debug('SqlMgr'); const log = new Debug('SqlMgr');

12
packages/nocodb/src/db/sql-migrator/lib/KnexMigrator.ts

@ -5,12 +5,12 @@ import glob from 'glob';
import Handlebars from 'handlebars'; import Handlebars from 'handlebars';
import mkdirp from 'mkdirp'; import mkdirp from 'mkdirp';
import rmdir from 'rmdir'; import rmdir from 'rmdir';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory'; import SqlClientFactory from '~/db/sql-client/lib/SqlClientFactory';
import Debug from '../../util/Debug'; import Debug from '~/db/util/Debug';
import Emit from '../../util/emit'; import Emit from '~/db/util/emit';
import Result from '../../util/Result'; import Result from '~/db/util/Result';
import * as fileHelp from '../../util/file.help'; import * as fileHelp from '~/db/util/file.help';
import SqlMigrator from './SqlMigrator'; import SqlMigrator from '~/db/sql-migrator/lib/SqlMigrator';
import { getToolDir, NcConfig } from '~/utils/nc-config'; import { getToolDir, NcConfig } from '~/utils/nc-config';
const evt = new Emit(); const evt = new Emit();

8
packages/nocodb/src/db/sql-migrator/lib/KnexMigratorv2Tans.ts

@ -11,7 +11,6 @@ import type MssqlClient from '~/db/sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '~/db/sql-client/lib/mysql/MysqlClient'; import type MysqlClient from '~/db/sql-client/lib/mysql/MysqlClient';
import type OracleClient from '~/db/sql-client/lib/oracle/OracleClient'; import type OracleClient from '~/db/sql-client/lib/oracle/OracleClient';
import type PGClient from '~/db/sql-client/lib/pg/PgClient'; import type PGClient from '~/db/sql-client/lib/pg/PgClient';
import type SnowflakeClient from '~/db/sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '~/db/sql-client/lib/sqlite/SqliteClient'; import type SqliteClient from '~/db/sql-client/lib/sqlite/SqliteClient';
import Noco from '~/Noco'; import Noco from '~/Noco';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
@ -33,12 +32,7 @@ export default class KnexMigratorv2Tans extends KnexMigratorv2 {
protected async getSqlClient( protected async getSqlClient(
source: Source, source: Source,
): Promise< ): Promise<
| SnowflakeClient MysqlClient | SqliteClient | MssqlClient | OracleClient | PGClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> { > {
return this.sqlClient || NcConnectionMgrv2.getSqlClient(source); return this.sqlClient || NcConnectionMgrv2.getSqlClient(source);
} }

4
packages/nocodb/src/services/columns.service.ts

@ -2592,7 +2592,7 @@ export class ColumnsService {
(param.column as LinkToAnotherColumnReqType).type === 'bt'; (param.column as LinkToAnotherColumnReqType).type === 'bt';
// if xcdb base then treat as virtual relation to avoid creating foreign key // if xcdb base then treat as virtual relation to avoid creating foreign key
if (param.source.isMeta()) { if (param.source.isMeta() || param.source.type === 'snowflake') {
(param.column as LinkToAnotherColumnReqType).virtual = true; (param.column as LinkToAnotherColumnReqType).virtual = true;
} }
@ -3004,6 +3004,8 @@ export class ColumnsService {
indexName?: string; indexName?: string;
nonUnique?: boolean; nonUnique?: boolean;
}) { }) {
// TODO: implement for snowflake (right now create index does not work with identifier quoting in snowflake - bug?)
if (source.type === 'snowflake') return;
const model = await column.getModel(); const model = await column.getModel();
const indexArgs = { const indexArgs = {
columns: [column.column_name], columns: [column.column_name],

Loading…
Cancel
Save