All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.voltdb.volttableutil.VoltTableUtil Maven / Gradle / Ivy

There is a newer version: 10.1.1
Show newest version
/* This file is part of VoltDB.
 * Copyright (C) 2008-2020 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see .
 */

package org.voltdb.volttableutil;

import com.google_voltpatches.common.base.Preconditions;
import org.apache.calcite.jdbc.Driver;
import com.google.common.collect.ImmutableList;
import org.apache.calcite.sql.type.SqlTypeName;
import org.voltdb.VoltTable;
import org.voltdb.plannerv2.ColumnTypes;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.UUID;

/**
 * The utility class that allow user to run SQL query on {@link VoltTable}.
 * @author Chao Zhou
 */
public final class VoltTableUtil {
    private VoltTableUtil() {
    }

    /**
     * Run a SQL query on {@link VoltTable}.
     * Exp:
     * VoltTable vt = VoltTableUtil.executeSql(
     * "select stations.station_id, count(activity.card_id)
     * from stations, activity where stations.station_id = activity.station_id
     * group by stations.station_id",
     * "stations", stations, "activity", activity);
     *
     * @param sql  The SQL string.
     * @param tableNames a list of {@link String} table names.
     * @param tables a list of {@link VoltTable} volt tables. Then sizes of tables and tableNames must equal.
     * @return A result set represented in {@link VoltTable}.
     */
    public static VoltTable executeSql(String sql, List tableNames, List tables) throws Exception {
        return run(sql, new VoltTableData.Database(asTable(tableNames, tables)));
    }

    public static VoltTable executeSql(String sql, String tableName, VoltTable table) throws Exception {
        return run(sql, new VoltTableData.Database(
                Collections.singletonList(new VoltTableData.Table(tableName, table))));
    }

    private static VoltTable run(String sql, VoltTableData.Database db) throws Exception {
        final String uuid = UUID.randomUUID().toString();
        VoltTableData.SCHEMA.put(uuid, db);
        final Properties info = new Properties();

        info.setProperty("schemaFactory", "org.voltdb.volttableutil.VoltTableSchemaFactory");
        info.setProperty("schema.id", uuid);
        try {       // mimic what a transaction block does: clean schema afterwards
            return asVoltTable(new Driver().connect("jdbc:calcite:", info).createStatement().executeQuery(sql));
        } finally {
            VoltTableData.SCHEMA.remove(uuid);
        }
    }

    private static List asTable(List tableNames, List tables) {
        Preconditions.checkArgument(tables.size() == tableNames.size(),
                "Length of table names must equal to length of tables");
        ImmutableList.Builder builder = ImmutableList.builder();
        for (int i = 0; i < tableNames.size(); ++i) {
            builder.add(new VoltTableData.Table(tableNames.get(i), tables.get(i)));
        }
        return builder.build();
    }

    private static VoltTable asVoltTable(ResultSet resultSet) throws SQLException {
        if (resultSet == null) {
            return null;
        } else {
            try {
                final ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                VoltTable.ColumnInfo[] columnInfoArray = new VoltTable.ColumnInfo[resultSetMetaData.getColumnCount()];
                for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
                    // TODO: verify the type convert
                    columnInfoArray[i] = new VoltTable.ColumnInfo(resultSetMetaData.getColumnName(i + 1),
                            ColumnTypes.getVoltType(SqlTypeName.getNameForJdbcType(resultSetMetaData.getColumnType(i + 1))));
                }
                final VoltTable vt = new VoltTable(columnInfoArray);
                while (resultSet.next()) {
                    Object[] row = new Object[resultSetMetaData.getColumnCount()];
                    for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
                        Object value = resultSet.getObject(i + 1);
                        if (resultSet.wasNull()) {
                            value = ColumnTypes.getVoltType(SqlTypeName.getNameForJdbcType(
                                    resultSetMetaData.getColumnType(i + 1)))
                                    .getNullValue();
                        }
                        row[i] = value;
                    }
                    vt.addRow(row);
                }
                return vt;
            } finally {
                resultSet.close();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy