Calcite使用SQL实现查询csv/json文件内容

 更新时间:2025年01月22日 09:28:40   作者:张铁牛  
calcite可以支持文件系统的数据源适配, 其实官方已经提供了相应的能力, 其支持csv和json的查询适配,下面我们就来看看Calcite如何使用SQL实现查询csv/json文件内容吧

1. 简介

我们在前面的文章提到了calcite可以支持文件系统的数据源适配, 其实官方已经提供了相应的能力, 其支持csv和json的查询适配, 废话不多说, 直接展示.

2. Maven

<!-- calcite文件系统支持 -->
<dependency>
    <groupId>org.apache.calcite</groupId>
    <artifactId>calcite-file</artifactId>
    <version>1.37.0</version>
</dependency>
<dependency>
    <groupId>org.apache.calcite</groupId>
    <artifactId>calcite-core</artifactId>
    <version>1.37.0</version>
</dependency>

3. 数据文件准备

3.1 csv

user_info.csv

首行将来被解析成表的字段, 冒号后面是字段类型, 如果未指定类型 默认使用varchar

ID:long,姓名:string,GENDER:string,BIRTHDAY:date
100,"张三",,"2001-01-01"
110,"李四","M","2001-01-01"
120,"王五","M","2002-05-03"
130,"赵六","F","2005-09-07"
140,"张铁牛","M","2007-01-01"

3.2 json

role_info.json

[
  {
    "id": 123,
    "name": "管理员",
    "key": "manager"
  },
  {
    "id": 234,
    "name": "老师",
    "key": "teacher"
  },
  {
    "id": 345,
    "name": "学生",
    "key": "student"
  }
]

然后将文件放到resources/file目录下

4. 核心代码

package com.ldx.calcite;

import com.google.common.collect.ImmutableMap;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.adapter.file.FileSchemaFactory;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.util.Sources;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testng.collections.Maps;

import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Properties;

@Slf4j
public class CalciteFileTest {
    private static Connection connection;

    private static SchemaPlus rootSchema;

    private static Statement statement;

    @BeforeAll
    @SneakyThrows
    public static void beforeAll() {
        Properties info = new Properties();
        // 不区分sql大小写
        info.setProperty("caseSensitive", "false");
        // 创建Calcite连接
        connection = DriverManager.getConnection("jdbc:calcite:", info);
        CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);
        // 构建RootSchema,在Calcite中,RootSchema是所有数据源schema的parent,多个不同数据源schema可以挂在同一个RootSchema下
        rootSchema = calciteConnection.getRootSchema();
        final Schema schema = FileSchemaFactory.INSTANCE.create(rootSchema, "x",
                ImmutableMap.of("directory", resourcePath("file"), "flavor", "scannable"));
        rootSchema.add("test", schema);
        // 创建SQL语句执行查询
        statement = calciteConnection.createStatement();
    }

    @Test
    @SneakyThrows
    public void execute_simple_query() {
        ResultSet resultSet = statement.executeQuery("SELECT * FROM test.user_info");
        printResultSet(resultSet);
    }
  
    @Test
    @SneakyThrows
    public void test_execute_join_query() {
        ResultSet resultSet = statement.executeQuery("SELECT * FROM test.user_info ui inner join test.role_info ri on ui.role_id = ri.id");
        printResultSet(resultSet);
    }

    @AfterAll
    @SneakyThrows
    public static void closeResource() {
        statement.close();
        connection.close();
    }

    private static String resourcePath(String path) {
        final URL url = CalciteFileTest.class.getResource("/" + path);
        return Sources.of(url).file().getAbsolutePath();
    }

    public static void printResultSet(ResultSet resultSet) throws SQLException {
        // 获取 ResultSet 元数据
        ResultSetMetaData metaData = resultSet.getMetaData();

        // 获取列数
        int columnCount = metaData.getColumnCount();
        log.info("Number of columns: {}",columnCount);

        // 遍历 ResultSet 并打印结果
        while (resultSet.next()) {
            final Map<String, String> item = Maps.newHashMap();
            // 遍历每一列并打印
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                String columnValue = resultSet.getString(i);
                item.put(columnName, columnValue);
            }

            log.info(item.toString());
        }
    }
}

其实核心代码就几行, 如下:

通过FileSchemaFactory指定文件目录和文件内容的读取方式, 默认将指定目录下的csv和json文件读取成Table, 表名就是file的名称

flavor:

  • SCANNABLE: 数据扫描。会更侧重于快速地读取和遍历数据。这种方式适用于需要对大量数据进行全表扫描或者范围扫描的情况,例如统计汇总操作
  • FILTERABLE: 数据过滤。会更侧重于数据的条件筛选,比如在 SQL 查询中的WHERE子句。
  • TRANSLATABLE: 数据转换。会更侧重于数据转换,以满足特定的查询需求或者数据处理要求。这种转换可能包括数据类型的转换(如将字符串类型的数字转换为实际的数值类型)、格式转换(如日期格式的调整)等。
// 这里的第二个参数“x”没什么意义, 源码中没用到, 可以随便填
final Schema schema = FileSchemaFactory.INSTANCE.create(rootSchema, "x",
               ImmutableMap.of("directory", resourcePath("file"), "flavor", "scannable"));
// 使用目录名称为schema名称, 这里的test就是schema名称
rootSchema.add("test", schema);

calcite也可以做对应表的关联查询, 测试中csv关联json文件信息

"SELECT * FROM test.user_info ui inner join test.role_info ri on ui.role_id = ri.id"

5. 测试查询

execute_simple_query方法执行如下

test_execute_join_query方法执行如下:

以上就是Calcite使用SQL实现查询csv/json文件内容的详细内容,更多关于Calcite SQL查询csv/json的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Security中successHandler无效问题及解决

    Spring Security中successHandler无效问题及解决

    这篇文章主要介绍了Spring Security中successHandler无效问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 关于BufferedReader读取文件指定字符集问题

    关于BufferedReader读取文件指定字符集问题

    这篇文章主要介绍了关于BufferedReader读取文件指定字符集问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • dom4j读取XML文件详解

    dom4j读取XML文件详解

    这篇文章主要为大家详细介绍了dom4j读取XML文件的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Milvus快速入门及用Java操作Milvus的全过程

    Milvus快速入门及用Java操作Milvus的全过程

    Milvus是面向向量的数据库,通过相似性搜索处理非结构化数据特征,本文给大家介绍Milvus快速入门以及用Java操作Milvus的方法,感兴趣的朋友一起看看吧
    2025-09-09
  • JDBC 使用说明(流程、架构、编程)

    JDBC 使用说明(流程、架构、编程)

    这篇文章主要介绍了JDBC 使用说明,需要的朋友可以参考下
    2015-08-08
  • 利用Java实现图片马赛克效果

    利用Java实现图片马赛克效果

    马赛克效果是一种常见的图像处理技术,通过将图像划分为多个小块并对每个小块进行平均色处理,模拟马赛克的效果,在本项目中,我们将使用Java的Swing库和图像处理技术来实现图片的马赛克特效,需要的朋友可以参考下
    2025-02-02
  • J2EE项目代码编写规范分享

    J2EE项目代码编写规范分享

    这篇文章主要介绍了J2EE项目代码编写规范分享,需要的朋友可以参考下
    2014-10-10
  • Java数据结构顺序表用法详解

    Java数据结构顺序表用法详解

    顺序表是计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系
    2021-10-10
  • Java中的自旋锁与阻塞锁详解

    Java中的自旋锁与阻塞锁详解

    这篇文章主要介绍了Java中的自旋锁与阻塞锁详解,阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒,阻塞或者唤醒一个Java线程需要操作系统切换CPU 状态来完成,这种状态转换 需要耗费处理器时间,需要的朋友可以参考下
    2023-10-10
  • Nacos配置中心与本地代码工程配置文件之间的优先级关系详解

    Nacos配置中心与本地代码工程配置文件之间的优先级关系详解

    本文介绍了Spring Cloud生态中配置加载原理,强调Nacos远程配置优先级高于本地`application.yml`但低于命令行和环境变量,覆盖了多环境配置、动态刷新配置及安全配置外置等应用场景,对比了Nacos配置中心与本地配置文件的优缺点,并给出最佳实践建议
    2026-04-04

最新评论