zoukankan      html  css  js  c++  java
  • cube.js 对于sql 方言支持的处理

    sql 方言主要是为了进行不通数据库sql 兼容的支持,一般我们是不需要做的,但是一些特殊情况下我们
    可能需要自己开发sql 方言处理

    参考方法

    server 初始化
    packages/cubejs-server-core/src/core/server.ts

     
    const options: ServerCoreInitializedOptions = {
          dbType,
          externalDbType,
          devServer,
          driverFactory: () => typeof dbType === 'string' && CubejsServerCore.createDriver(dbType),
          dialectFactory: (ctx) => CubejsServerCore.lookupDriverClass(ctx.dbType).dialectClass &&
            CubejsServerCore.lookupDriverClass(ctx.dbType).dialectClass(),
          externalDriverFactory: externalDbType && (
            () => new (CubejsServerCore.lookupDriverClass(externalDbType))({
              host: process.env.CUBEJS_EXT_DB_HOST,
              database: process.env.CUBEJS_EXT_DB_NAME,
              port: process.env.CUBEJS_EXT_DB_PORT,
              user: process.env.CUBEJS_EXT_DB_USER,
              password: process.env.CUBEJS_EXT_DB_PASS,
            })
          ),
          externalDialectFactory: () => typeof externalDbType === 'string' &&
            CubejsServerCore.lookupDriverClass(externalDbType).dialectClass &&
            CubejsServerCore.lookupDriverClass(externalDbType).dialectClass(),
          apiSecret: process.env.CUBEJS_API_SECRET,
          telemetry: process.env.CUBEJS_TELEMETRY !== 'false',
          scheduledRefreshTimeZones: process.env.CUBEJS_SCHEDULED_REFRESH_TIMEZONES &&
            process.env.CUBEJS_SCHEDULED_REFRESH_TIMEZONES.split(',').map(t => t.trim()),
          scheduledRefreshContexts: async () => [null],
          basePath: '/cubejs-api',
          dashboardAppPath: 'dashboard-app',
          dashboardAppPort: 3000,
          scheduledRefreshConcurrency: parseInt(process.env.CUBEJS_SCHEDULED_REFRESH_CONCURRENCY, 10),
          preAggregationsSchema: getEnv('preAggregationsSchema') || (
            devServer ? 'dev_pre_aggregations' : 'prod_pre_aggregations'
          ),
          schemaPath: process.env.CUBEJS_SCHEMA_PATH || 'schema',
          logger: opts.logger || process.env.NODE_ENV !== 'production'
            ? devLogger(process.env.CUBEJS_LOG_LEVEL)
            : prodLogger(process.env.CUBEJS_LOG_LEVEL),
          ...opts,
        };
        if (opts.contextToAppId && !opts.scheduledRefreshContexts) {
          options.logger('Multitenancy Without ScheduledRefreshContexts', {
            warning: (
              'You are using multitenancy without configuring scheduledRefreshContexts, which can lead to issues where the ' +
              'security context will be undefined while Cube.js will do background refreshing: ' +
              'https://cube.dev/docs/config#options-reference-scheduled-refresh-contexts'
            ),
          });
        }
     

    编译api 对于方言的处理
    packages/cubejs-server-core/src/core/server.ts

     
    public getCompilerApi(context: RequestContext) {
        const appId = this.contextToAppId(context);
        let compilerApi = this.compilerCache.get(appId);
        const currentSchemaVersion = this.options.schemaVersion && (() => this.options.schemaVersion(context));
        if (!compilerApi) {
          compilerApi = this.createCompilerApi(
            this.repositoryFactory(context), {
              dbType: (dataSourceContext) => this.contextToDbType({ ...context, ...dataSourceContext }),
              externalDbType: this.contextToExternalDbType(context),
              dialectClass: (dialectContext) => this.options.dialectFactory &&
                this.options.dialectFactory({ ...context, ...dialectContext }),
              externalDialectClass: this.options.externalDialectFactory && this.options.externalDialectFactory(context),
              schemaVersion: currentSchemaVersion,
              preAggregationsSchema: this.preAggregationsSchema(context),
              context,
              allowJsDuplicatePropsInSchema: this.options.allowJsDuplicatePropsInSchema
            }
          );
          this.compilerCache.set(appId, compilerApi);
        }
        compilerApi.schemaVersion = currentSchemaVersion;
        return compilerApi;
      }
     
     

    方法处理部分(主要是进行了一个判断,没有的使用默认的)
    packages/cubejs-schema-compiler/src/adapter/QueryBuilder.js

    export const createQuery = (compilers, dbType, queryOptions) => {
      if (!queryOptions.dialectClass && !ADAPTERS[dbType]) {
        return null;
      }
      let externalQueryClass = queryOptions.externalDialectClass;
      if (!externalQueryClass && queryOptions.externalDbType) {
        if (!ADAPTERS[queryOptions.externalDbType]) {
          throw new Error(`Dialect for '${queryOptions.externalDbType}' is not found`);
        }
        externalQueryClass = ADAPTERS[queryOptions.externalDbType];
      }
      // 有使用方言,没有的使用默认的driver 基于BaseQuery的实现
      return new (queryOptions.dialectClass || ADAPTERS[dbType])(compilers, {
        ...queryOptions,
        externalQueryClass
      });
    };
     

    默认提供的adapter
    packages/cubejs-schema-compiler/src/adapter/QueryBuilder.js

     
    const ADAPTERS = {
      postgres: PostgresQuery,
      redshift: RedshiftQuery,
      mysql: MysqlQuery,
      mysqlauroraserverless: MysqlQuery,
      mongobi: MongoBiQuery,
      mssql: MssqlQuery,
      bigquery: BigqueryQuery,
      prestodb: PrestodbQuery,
      qubole_prestodb: PrestodbQuery,
      athena: PrestodbQuery,
      vertica: VerticaQuery,
      snowflake: SnowflakeQuery,
      clickhouse: ClickHouseQuery,
      hive: HiveQuery,
      oracle: OracleQuery,
      sqlite: SqliteQuery,
      awselasticsearch: AWSElasticSearchQuery,
      elasticsearch: ElasticSearchQuery
    };

    参考方言的编写

    可以参考druid,参考格式
    packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
    packages/cubejs-query-orchestrator/src/driver/BaseDriver.js
    packages/cubejs-druid-driver/src/DruidDriver.ts

     
    export class DruidDriver extends BaseDriver {
      protected readonly config: DruidDriverConfiguration;
      protected readonly client: DruidClient;
      // 此处比较重要
      public static dialectClass() {
        return DruidQuery;
      }
    ....

    DruidQuery 的实现继承自BaseQuery

    说明

    官方提供方言支持的核心也是让大家方便的进行driver的开发,因为一些内置的driver 是直接打包在
    packages/cubejs-schema-compiler中了,修改此包是不明智的选择,同时也不利于社区参与贡献
    如果关注代码会发现有一个直接使用基于npm 包模式的驱动依赖管理,处理参考代码

     
     public static driverDependencies(dbType: DatabaseType) {
        if (DriverDependencies[dbType]) {
          return DriverDependencies[dbType];
        } else if (fs.existsSync(path.join('node_modules', `${dbType}-cubejs-driver`))) {
          return `${dbType}-cubejs-driver`;
        }
        throw new Error(`Unsupported db type: ${dbType}`);
      }

    所以只要我们的格式符合${dbType}-cubejs-driver 并且是通过npm 包发布的,也就是一个合格的driver

    参考资料

    https://github.com/cube-js/cube.js/blob/master/CONTRIBUTING.md#implementing-sql-dialect

  • 相关阅读:
    overlapped
    overlapped编程
    Oracle DB 使用子查询来解决查询
    OCP-1Z0-051-V9.02-132题
    OCP-1Z0-051-V9.02-131题
    OCP-1Z0-051-V9.02-130题
    OCP-1Z0-051-V9.02-129题
    OCP-1Z0-051-V9.02-128题
    OCP-1Z0-051-V9.02-127题
    OCP-1Z0-051-V9.02-126题
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/14369545.html
Copyright © 2011-2022 走看看