后端数据库【免费下载链接】calciteApache Calcite项目地址https://gitcode.com/gh_mirrors/ca/calcite点击查看免费下载Apache Calcite 允许用户用 JSON 或 YAML 两种格式的模型model文件来描述数据源的逻辑结构——包括 Schema、表、视图、函数、自定义类型乃至用于自动物化的 Lattice 与 Materialization。本指南以官方文档 site/_docs/model.md 为骨架结合core模块中org.apache.calcite.model包的源码实现与仓库内的真实示例模型逐一讲解模型文件的每个元素、参数含义与底层加载机制。读完本文你将能够独立编写可运行的 JSON/YAML 模型通过jdbc:calcite:model...连接 Calcite并为 CSV、MongoDB 等外部数据源配置自定义 Schema、视图与物化策略。模型是什么声明式描述 Calcite SchemaCalcite 的模型文件是一个纯声明式的配置它不包含任何执行逻辑只描述连接到这个 Calcite 实例时根 Schema 下应该有哪些子 Schema、每个 Schema 里有哪些表、视图、函数、类型以及哪些查询结果需要被物化。模型可以被保存为.json或.yaml/.yml文件在 JDBC 连接字符串中通过model参数引用通过inline:前缀直接内联在连接字符串或测试代码里用编程方式调用org.apache.calcite.schema.SchemaSPI 等价地构建本指南聚焦声明式模型。从源码结构看模型文件被反序列化为org.apache.calcite.model包下的一组 POJO如 JsonRoot.java、JsonSchema.java、JsonTable.java 等再由 ModelHandler.java 逐个访问visit并创建对应的 Schema 对象。其对象层次结构在JsonRoot的类注释中有清晰的树状描述Root ├── Schema (JsonRoot.schemas) │ ├── Type (JsonMapSchema.types) │ ├── Table (JsonMapSchema.tables) │ │ ├── Column (JsonTable.columns) │ │ └── Stream (JsonTable.stream) │ ├── View │ ├── Function (JsonMapSchema.functions) │ ├── Lattice (JsonSchema.lattices) │ │ ├── Measure (JsonLattice.defaultMeasures) │ │ └── Tile (JsonLattice.tiles) │ │ └── Measure (JsonTile.measures) │ └── Materialization (JsonSchema.materializations) └── Type (JsonRoot.types全局共享)JSON 与 YAML 两种写法以及宽松 JSON语法同一个模型可以写成 JSON 或 YAML。官方文档中的示例大量使用了不带引号的字段名和单引号字符串例如{ version: 1.0, defaultSchema: mongo, schemas: [ Schema... ], types: [ Type... ] }这并非笔误。查看 ModelHandler.java 可以看到Calcite 使用的ObjectMapper显式开启了三个宽松特性private static final ObjectMapper JSON_MAPPER new ObjectMapper() .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) .configure(JsonParser.Feature.ALLOW_COMMENTS, true);即模型 JSON 允许字段名不加引号、字符串使用单引号、文件内允许注释。对应的 YAML 解析则使用独立的YAMLMapper。两种格式完全等价选择哪一种只取决于个人偏好与工具链。模型如何被加载格式自动检测与路径安全ModelHandler.java 展示了模型的加载流程若 URI 以inline:开头则去掉前缀并去除首尾空白后按内容判断以/*或{开头按 JSON 解析否则按 YAML 解析。这一点在 ModelTest.java 中有专门测试包括注释开头、{开头被强制按 JSON 解析等边界情况若 URI 是文件路径则按扩展名判断以.yaml或.yml结尾使用 YAML 解析器其余使用 JSON 解析器模型文件还可以通过系统属性calcite.model.baseDirectory限制读取目录——相对路径会基于该目录解析任何越界解析的路径都会被拒绝ModelHandler.java这是防止任意文件读取的安全措施。解析后的JsonRoot会被遍历先处理根级全局types再逐个schema。如果模型指定了defaultSchema连接建立后会自动切换为该 Schema。根元素 Rootversion、defaultSchema、schemas、types根元素是模型文件的唯一顶层对象包含四个字段字段必填类型说明version是string模型版本号必须为1.0源码中该属性标记为required true且requireNonNulldefaultSchema否string模型中某个 Schema 的大小写敏感名称指定后使用该模型的连接会默认进入此 Schemaschemas否listSchema 元素列表可为空types否listType 元素列表位于根级、被模型中所有 Schema 共享JSON 与 YAML 写法对比JSON 字段可省引号YAML 直接缩进{ version: 1.0, defaultSchema: mongo, schemas: [ ], types: [ ] }version: 1.0 defaultSchema: mongo schemas: - [] types: - []Schema三种子类型的公共基类Schema 出现在root.schemas中。除name外它的大部分属性由三种子类型Map / Custom / JDBC继承共享{ name: foodmart, path: [lib], cache: true, materializations: [ Materialization... ] }字段必填类型 / 默认值说明name是stringSchema 名称type否string默认map子类型mapMap Schema、customCustom Schema、jdbcJDBC Schema。源码 JsonSchema.java 通过 Jackson 的JsonSubTypes把type字段映射到三个具体类未指定时默认JsonMapSchemapath否list用于解析本 Schema 中函数UDF的 SQL 路径。每个元素必须是字符串或字符串列表。例如path: [ [usr, lib], lib ]声明了/usr/lib与/lib两个路径元素大多数顶层 Schema 直接用字符串即可cache否boolean默认true是否缓存 Schema 生成的元数据表、函数、子 Schemamaterializations否list本 Schema 中查询结果物化表的 Materialization 列表cache 的权衡cache: falseCalcite 每次需要元数据例如校验查询时列出表都会回源访问 Schema 实现cache: true首次读取时缓存元数据可显著提升性能尤其是名称匹配大小写不敏感的场景见 JsonSchema.java 注释。缓存带来的问题是陈旧stalenessSchema 实现可以通过覆写Schema.contentsHaveChangedSince方法主动告知 Calcite 缓存何时过期。需要强调的是在 Schema 中显式创建的表、函数、类型和子 Schema 不受缓存机制影响——它们总是立即出现永不会被刷新。Map Schema纯声明式的表与函数集合Map Schema 是最简单的 Schema 形式它不连接任何外部数据源只是把模型中声明的表、函数、类型直接装进一个AbstractSchema对应源码 ModelHandler.java 的visit(JsonMapSchema)。name: foodmart type: map tables: - [ Table... ] functions: - [ Function... ] types: - [ Type... ]tables可选本 Schema 中的 Table 列表functions可选本 Schema 中的 Function 列表types可选本 Schema 中的 Type 列表。仓库 example/function/src/test/resources/model.yaml 就是典型的 Map Schema它声明了MAZE与SOLVE两个函数分别指向org.apache.calcite.example.maze.MazeTable类的generate与solve方法。Custom Schema把外部数据源接入 Calcite 的桥Custom Schema 是接入 CSV、MongoDB、Cassandra 等外部数据源的标准方式。它通过一个工厂类把外部资源转换成一个 Calcite Schema{ name: mongo, type: custom, factory: org.apache.calcite.adapter.mongodb.MongoSchemaFactory, operand: { host: localhost, database: test } }字段必填说明factory是工厂类全限定名必须实现org.apache.calcite.schema.SchemaFactory接口且具有公共无参构造器operand否传给工厂的任意属性键值对Map源码 ModelHandler.java 中visit(JsonCustomSchema)会先通过ClassNameFilter校验工厂类名再用AvaticaUtils.instantiatePlugin反射实例化SchemaFactory最后调用schemaFactory.create(parentSchema, name, operandMap)创建 Schema。仓库 mongodb/src/test/resources/mongo-model.json 给出了完整的实战组合两个 custom Schemamongo_raw、_foodmart读取 MongoDB 集合再叠加一个 Map Schema 用视图把文档字段cast成关系型列。自动注入的额外 operand值得注意Calcite 会向 custom Schema 的 operand 自动注入三个额外键定义于 ModelHandler.java 的ExtraOperand枚举仅当用户在 operand 中没有显式指定时才注入modelUri模型本身的 URI文件路径或inline:内容baseDirectory模型文件所在目录inline:模型则为空目录适配器可据此解析相对路径tables在该 Schema 内显式声明的表列表。CSV 适配器的 CsvSchemaFactory.java 正是利用baseDirectory把相对路径directory: sales解析为模型文件目录下的sales/并用flavoroperand 控制生成的表类型SCANNABLE、FILTERABLE或TRANSLATABLE见 example/csv/src/test/resources/smart.yaml。JDBC Schema直接映射关系型数据库JDBC Schema 把 Calcite 连接到任何 JDBC 数据源自动暴露其 catalog/schema/表结构name: foodmart type: jdbc jdbcDriver: TODO jdbcUrl: TODO jdbcUser: TODO jdbcPassword: TODO jdbcCatalog: TODO jdbcSchema: TODO字段必填说明jdbcDriver否JDBC 驱动类名不指定时由java.sql.DriverManager自动选择jdbcUrl是JDBC 连接串如jdbc:mysql://localhost/foodmart。注意原文档将 jdbcUrl 标为可选但源码 JsonJdbcSchema.java 中该属性实际标记为required true因此实践中它是必需的jdbcUser否用户名jdbcPassword否密码jdbcCatalog否数据源中的初始 catalog 名称jdbcSchema否数据源中的初始 schema 名称ModelHandler.java 的实现会通过JdbcSchema.dataSource(...)创建DataSource再调用JdbcSchema.create(...)生成 Schema。另外该类还支持一个文档未展开的sqlDialectFactory字段指定SqlDialectFactory实现类全名时Calcite 会用它来决定方言的生成策略否则采用默认方言。Table 与 ColumnSchema 中最基础的实体Table 出现在root.schemas.tablesColumn 出现在root.schemas.tables.columns{ name: sales_fact, columns: [ Column... ] }Table 字段必填类型 / 默认值说明name是string表名在 Schema 内必须唯一type否string默认custom子类型customCustom Table、viewView。源码 JsonTable.java 中未指定时默认JsonCustomTablecolumns否listColumn 列表对某些表如 View可选Column 只有name必填一个字段{ name: empno }View用 SQL 定义虚拟表View 是用 SQL 查询定义的虚拟表name: female_emps type: view sql: select * from emps where gender F modifiable: true字段必填说明sql是视图的 SQL 定义。可以是单个字符串也可以是字符串列表会被拼接成多行 SQL行间以换行符连接见 JsonView.javapath否解析查询所用的 SQL 路径不指定时默认当前 SchemaModelHandler.java 用Util.first(jsonView.path, currentSchemaPath())兜底modifiable否视图是否可修改不指定时 Calcite 自动推导可修改视图modifiable view的判定规则一个视图是可修改的当且仅当它只包含SELECT、FROM、WHERE不允许 JOIN、聚合或子查询并且每一列满足以下任一条件在 SELECT 子句中恰好出现一次或在 WHERE 子句中带column literal谓词或该列可空nullable。第二条规则的典型用途是多租户场景tenantId列被隐藏、强制非空NOT NULL但对某个视图而言其值是常量。此时 Calcite 可以自动为隐藏列提供正确值。与可修改视图相关的三类报错源码注释也复述于 JsonView.java若视图标记modifiable: true但实际不可修改Calcite 在读取 Schema 时抛错若对不可修改的视图提交 INSERT、UPDATE 或 UPSERTCalcite 在校验语句时抛错若 DML 语句产生一条不会出现在视图中的行例如向female_emps插入gender M的行Calcite 在执行语句时抛错。仓库 example/csv/src/test/resources/model-with-view.yaml 是一个带视图的完整模型SALEScustom Schema 之上叠加了FEMALE_EMPS视图。而 mongodb/src/test/resources/mongo-model.json 中的视图则展示了把 MongoDB 文档字段_MAP[city]cast 成varchar等关系型列的标准写法。Custom Table由工厂类创建的表与 Custom Schema 类似Custom Table 通过工厂类把外部资源包装成表name: EMPS type: custom factory: org.apache.calcite.adapter.csv.CsvTableFactory operand: file: sales/EMPS.csv.gz flavor: scannable字段必填说明factory是工厂类全限定名必须实现org.apache.calcite.schema.TableFactory且具有公共无参构造器operand否传给工厂的任意属性 MapModelHandler.java 中visit(JsonCustomTable)反射实例化TableFactory并调用tableFactory.create(schema, name, operand, null)。仓库 example/csv/src/test/resources/model-with-custom-table.yaml 给出了可直接运行的示例EMPS表由CsvTableFactory创建读取sales/EMPS.csv.gz并以scannable风格暴露。Stream声明流式表能力Stream 出现在root.schemas.tables.stream描述表是否支持流式读取{ stream: true, history: false }字段必填默认值说明stream否true表是否允许流式读取history否false流的完整历史是否可用仓库 example/csv/src/test/resources/model-stream-table.yaml 演示了流式表的声明方式DEPTS表使用CsvStreamTableFactory并设置stream: { stream: true }。Function声明标量函数、表宏与聚合函数Function 出现在root.schemas.functions用于把 Java 类注册为可被 SQL 调用的函数{ name: MY_PLUS, className: com.example.functions.MyPlusFunction, methodName: apply, path: [] }字段必填说明name是函数名className是实现函数的类全限定名methodName否实现函数的大小写敏感的方法名path否解析此函数的 SQL 路径methodName的行为分三种情况源码 JsonFunction.java 与 ModelHandler.java 的addFunctions实现相互印证指定具体方法名Calcite 创建标量函数。方法可为 static 或非 static非 static 时类必须有公共无参构造器。methodName: *Calcite 为类中的每个方法创建一个函数对应ScalarFunctionImpl.functions(clazz)遍历。不指定 methodNameCalcite 查找名为eval的方法找到则创建表宏Table Macro或标量函数同时查找init、add、merge、result方法找到则创建聚合函数。若最终都不匹配会抛出Not a valid function class: ...的运行时异常。addFunctions内部还揭示了方法探测顺序先尝试TableFunctionImpl再尝试TableMacroImpl因为表宏与标量函数都可能有eval方法必须先判定表宏最后才是ScalarFunctionImpl与AggregateFunctionImpl。Type定义用户自定义类型Type 可以出现在root.types全局所有 Schema 共享或root.schemas.typesSchema 内{ name: mytype1, type: BIGINT, attributes: [ { name: f1, type: BIGINT } ] }字段必填说明name是类型名type否SQL 类型名attributes否类型属性列表规则若attributes与type在同一层级同时存在type优先。源码 ModelHandler.java 中visit(JsonType)在type非空时直接通过typeFactory.createSqlType(SqlTypeName.get(...))创建基础类型否则遍历attributes构建结构化struct类型。值得注意的是属性类型会先按SqlTypeName查找找不到时还会尝试从当前 Schema 中解析自定义类型——即类型可以嵌套引用。Materialization物化查询结果Materialization 出现在root.schemas.materializations把一个查询的物化结果暴露为 Schema 中的表{ view: V, table: T, sql: select deptno, count(*) as c, sum(sal) as s from emp group by deptno }字段必填说明view否视图名。为 null 表示表已存在且已被正确数据填充table是承载查询结果的表名。若view非 null 且表不存在Calcite 会创建并填充一张内存表sql否物化的 SQL 定义可以是字符串或字符串列表拼接为多行字符串从实现看ModelHandler.java若未提供viewCalcite 会生成一个形如$N的合成视图名并将existing置为 true表示数据已预先填充最终通过MaterializedViewTable.create(...)注册到 Schema。此外定义 materialization 的父 Schema 必须是SemiMutableSchema否则会抛出Cannot define materialization; parent schema ... is not a SemiMutableSchema——ModelTest.java 用不可变 custom Schema 验证了这一约束。Lattice、Tile 与 Measure星型模型的自动物化框架Lattice 是 Calcite 对星型模型star schema的抽象它定义一个事实表、若干维表及其连接路径并以此为基础识别、推荐和物化不同聚合粒度的物化视图。出现在root.schemas.lattices。一个完整示例官方文档原样注意 SQL 字符串列表会被拼接为多行{ name: star, sql: [ select 1 from foodmart.sales_fact_1997 as s, join foodmart.product as p using (product_id), join foodmart.time_by_day as t using (time_id), join foodmart.product_class as pc on p.product_class_id pc.product_class_id ], auto: false, algorithm: true, algorithmMaxMillis: 10000, rowCountEstimate: 86837, defaultMeasures: [ { agg: count } ], tiles: [ { dimensions: [ the_year, [t, quarter] ], measures: [ { agg: sum, args: unit_sales }, { agg: sum, args: store_sales }, { agg: count } ] } ] }Lattice 字段详解字段必填默认值说明name是—Lattice 名称sql是—定义事实表、维表与连接路径的 SQL。SQL 语句的结构特别是 FROM 子句中各项的顺序决定了谁是事实表、谁是维表auto否true是否在执行查询时按需物化 tilealgorithm否false是否用优化算法建议并填充一组初始 tilealgorithmMaxMillis否-1不限时算法最大运行毫秒数超时后采用算法目前得到的最佳结果rowCountEstimate否文档标注默认1000.0Lattice 的行数估计。从源码 JsonLattice.java 看该字段实际为可空nullable未指定时 ModelHandler.java 不会设置行数估计统计信息将交由 statistic provider 计算defaultMeasures否[ { agg: count } ]即count(*)tile 默认应含有的度量tiles中的每个 tile 仍可定义自己的度量包括不在该列表中的tiles否—预先创建的物化聚合 Tile 列表statisticProvider否默认由 Calcite 生成并执行 SQL 查询求真实值并缓存提供各列去重值distinct values估计的类必须实现org.apache.calcite.materialize.LatticeStatisticProvider。可以写类名也可以写类名#静态字段statisticProvider: org.apache.calcite.materialize.Lattices#CACHING_SQL_STATISTIC_PROVIDER从源码实现看visit(JsonLattice)ModelHandler.java会创建Lattice.Builder并依次应用auto、algorithm、rowCountEstimate、statisticProvider随后通过populateLattice处理默认度量与 tile最终schema.add(name, latticeBuilder.build())把 Lattice 注册为 Schema 元素。Lattice 的完整概念与用法可进一步参考文档 site/_docs/lattice.md。Tile预定义的物化聚合Tile 出现在root.schemas.lattices.tiles{ dimensions: [ the_year, [t, quarter] ], measures: [ { agg: sum, args: unit_sales } ] }字段必填说明dimensions是可为空列表tile 的维度语义类似GROUP BY子句。每个元素可以是字符串Lattice 内该列的唯一标签也可以是字符串列表表别名 列名构成的二元组measures否作用于参数的聚合函数列表不指定时使用 Lattice 的默认度量列表Measure聚合度量Measure 出现在root.schemas.lattices.defaultMeasures与root.schemas.lattices.tiles.measuresagg: sum args: unit_sales字段说明agg聚合函数名通常为count、sum、min、maxargs可选。列标签字符串或零个/多个列标签的列表args的合法取值不指定无参数、null无参数、空列表无参数、字符串单个参数为 Lattice 中的某列标签、列表多个参数每项为列标签。与 Lattice 维度不同Measure 不能用[table, column]的限定格式。因此在定义 Lattice 时应确保每个拟用作度量的列在 Lattice 内都有唯一标签必要时用AS label显式命名并在作为度量参数时使用该标签。实战从零写一个可运行的模型1. CSV 数据源Custom Schema最简单的模型只需一个 custom Schema。仓库 example/csv/src/test/resources/model.yaml 展示了标准写法version: 1.0 defaultSchema: SALES schemas: - name: SALES type: custom factory: org.apache.calcite.adapter.csv.CsvSchemaFactory operand: directory: salesdirectory: sales是相对路径CsvSchemaFactory会基于baseDirectory模型文件所在目录解析。若想获得过滤下推能力可在 operand 中加flavor: TRANSLATABLE见 example/csv/src/test/resources/smart.yaml。2. 叠加视图在 custom Schema 的tables下声明视图即可在原始表之上提供逻辑层example/csv/src/test/resources/model-with-view.yamlversion: 1.0 defaultSchema: SALES schemas: - name: SALES type: custom factory: org.apache.calcite.adapter.csv.CsvSchemaFactory operand: directory: sales tables: - name: FEMALE_EMPS type: view sql: SELECT * FROM emps WHERE gender F3. 连接模型模型文件就绪后可通过 JDBC URL 连接参见 site/_docs/howto.mdsqlline !connect jdbc:calcite:modelmongodb/src/test/resources/mongo-model.json admin admin也可以把模型内联进连接字符串inline:前缀这在测试与快速原型中尤其方便——ModelTest.java 中大量测试正是以CalciteAssert.model(inline:...)形式运行的。小结Calcite 的 JSON/YAML 模型是一套精炼而完整的声明式 Schema 描述语言从version与defaultSchema的根级配置到 map/custom/jdbc 三种 Schema 的接入方式再到表、列、视图、函数、类型、物化与 Lattice 的逐层细化每一个元素在 org.apache.calcite.model 包中都有对应的 POJO 与加载逻辑并且都被 ModelTest.java 等测试用例覆盖验证。无论是接入 CSV、MongoDB 这类外部数据源还是构建带视图、物化视图与 Lattice 的分析型 Schema模型文件都是你与 Calcite 交互的第一道也是最重要的一道接口。赞分享后端数据库【免费下载链接】calciteApache Calcite项目地址https://gitcode.com/gh_mirrors/ca/calcite点击查看免费下载相关推荐Pydantic JSON Schema 生成与自定义完全指南从模型到规范化的 JSON SchemaPydantic JSON Schema 生成与自定义完全指南从模型到规范化的 JSON Schema Pydantic 能从模型自动生成并深度定制 JSON后端序列化Apache Calcite 完全指南从入门到实战Apache Calcite 完全指南从入门到实战 Apache Calcite 是一个开源的数据管理框架它提供了强大的 SQL 解析、查询优化和多数据源适后端数据库Lovefield Schema 定义完全指南从动态构建器到静态 YAML 的数据库建模Lovefield Schema 定义完全指南从动态构建器到静态 YAML 的数据库建模 Lovefield 是一个面向 Web 应用的关系型数据库rela数据库关系型数据库嵌入式数据库上一篇如何在《鸣潮》中自定义游戏体验AES密钥与模组制作完全解析下一篇Windows安装错误2502/2503快速修复AtlasOS系统优化方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考