blob: c9376b2556cc45d15a5154942b8f2878ceb81aa2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.gora.ignite.utils;
import avro.shaded.com.google.common.collect.Lists;
import com.healthmarketscience.sqlbuilder.BinaryCondition;
import com.healthmarketscience.sqlbuilder.CreateTableQuery;
import com.healthmarketscience.sqlbuilder.CustomSql;
import com.healthmarketscience.sqlbuilder.DeleteQuery;
import com.healthmarketscience.sqlbuilder.DropQuery;
import com.healthmarketscience.sqlbuilder.FunctionCall;
import com.healthmarketscience.sqlbuilder.InsertQuery;
import com.healthmarketscience.sqlbuilder.SelectQuery;
import com.healthmarketscience.sqlbuilder.SqlObject;
import com.healthmarketscience.sqlbuilder.UpdateQuery;
import com.healthmarketscience.sqlbuilder.custom.mysql.MysLimitClause;
import com.healthmarketscience.sqlbuilder.dbspec.Constraint;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbConstraint;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec;
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.gora.ignite.store.Column;
import org.apache.gora.ignite.store.IgniteMapping;
/**
*
* SQL Builder utility for Ignite.
*/
public class IgniteSQLBuilder {
/**
* Returns a SQL query for determine whether a table exists or not.
*
* @param tableName The name of the table to be check.
* @return SQL query
*/
public static String tableExists(String tableName) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(tableName);
return new SelectQuery().addAllColumns().addFromTable(aTable)
.addCustomization(new MysLimitClause(0)).validate().toString();
}
/**
* Returns a SQL create table statement for initializing a datastore based
* upon a Ignite Mapping definition.
*
* @param mapping The ignite mapping definition of the data store
* @return SQL create query (DDL).
*/
public static String createTable(IgniteMapping mapping) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
ArrayList<Column> fieldsList = Lists.newArrayList(mapping.getPrimaryKey());
fieldsList.addAll(Lists.newArrayList(mapping.getFields().values()));
for (Column aColumn : fieldsList) {
String name = aColumn.getName();
Column.FieldType dataType = aColumn.getDataType();
aTable.addColumn(name, dataType.toString(), null);
}
String[] keys = new String[mapping.getPrimaryKey().size()];
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
keys[i] = mapping.getPrimaryKey().get(i).getName();
}
aTable.addConstraint(new DbConstraint(aTable,
mapping.getTableName() + "_PRIMARY_KEY",
Constraint.Type.PRIMARY_KEY, keys));
return new CreateTableQuery(aTable, true).validate().toString();
}
/**
* Returns a SQL drop table statement for deleting a datastore instance within
* ignite.
*
* @param tableName The name of the table to be dropped.
* @return SQL drop query (DDL).
*/
public static String dropTable(String tableName) {
String statement = DropQuery.dropTable(tableName).validate().toString();
return statement.substring(0, 11) + "IF EXISTS " + statement.substring(11);
}
/**
* Returns a bare SQL insert statement for adding a new record on a Ignite
* data store.
*
* @param mapping The ignite mapping definition of the data store
* @param data A map containing the Column-Value pairs of the new record.
* @return SQL insert statement
*/
public static String createInsertQuery(IgniteMapping mapping, Map<Column, Object> data) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
InsertQuery insertQuery = new InsertQuery(aTable);
List<Entry<Column, Object>> list = new ArrayList<>(data.entrySet());
String[] columns = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
columns[i] = list.get(i).getKey().getName();
}
return insertQuery.addCustomPreparedColumns(columns).validate().toString()
.replaceFirst("INSERT", "MERGE");
}
/**
* Fills a SQL PreparedStatement of a insert operation with the actual data to
* be inserted.
*
* @param statement The insertion PreparedStatement to be filled.
* @param insertData A map containing the Column-Value pairs of the new
* record.
* @throws SQLException When invalid values are provided as parameters for the
* insert statement.
*/
public static void fillInsertQuery(PreparedStatement statement, Map<Column, Object> insertData) throws SQLException {
List<Entry<Column, Object>> list = new ArrayList<>(insertData.entrySet());
for (int i = 0; i < list.size(); i++) {
int j = i + 1;
statement.setObject(j, list.get(i).getValue());
}
}
/**
* Returns a bare SQL statement for deleting a record from the Ignite data
* store.
*
* @param mapping The ignite mapping definition of the data store
* @return SQL delete statement
*/
public static String createDeleteQuery(IgniteMapping mapping) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
DeleteQuery statement = new DeleteQuery(aTable);
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
statement.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, mapping.getPrimaryKey().get(i).getName(), null),
SqlObject.QUESTION_MARK));
}
return statement.validate().toString();
}
/**
* Fills a SQL PreparedStatement of a delete operation with the actual key of
* the record to be deleted
*
* @param statement The deletion PreparedStatement to be filled.
* @param mapping The ignite mapping definition of the data store
* @param deleteData An Object array containing the primary key values of the
* record to be deleted
* @throws SQLException When invalid keys' values are provided as parameters
*/
public static void fillDeleteQuery(PreparedStatement statement, IgniteMapping mapping, Object... deleteData) throws SQLException {
assert mapping.getPrimaryKey().size() == deleteData.length;
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
int j = i + 1;
statement.setObject(j, deleteData[i]);
}
}
/**
* Returns a bare SQL statement for checking if a key exists
*
* @param mapping The ignite mapping definition of the data store
* @return SQL select statement
*/
public static String createSelectQueryExists(IgniteMapping mapping) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
SelectQuery selectQuery = new SelectQuery();
selectQuery.addCustomColumns(FunctionCall.countAll());
selectQuery.addFromTable(aTable);
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, mapping.getPrimaryKey().get(i).getName(), null),
SqlObject.QUESTION_MARK));
}
return selectQuery.validate().toString();
}
/**
* Returns a bare SQL statement for retrieving a record from the ignite data
* store
*
* @param mapping The ignite mapping definition of the data store
* @param columns A list of columns to be retrieved within the select query
* @return SQL select statement
*/
public static String createSelectQueryGet(IgniteMapping mapping, List<String> columns) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
SelectQuery selectQuery = new SelectQuery();
selectQuery.addFromTable(aTable);
DbColumn[] lsColumns = new DbColumn[columns.size()];
for (int i = 0; i < columns.size(); i++) {
lsColumns[i] = aTable.addColumn(columns.get(i));
}
selectQuery.addColumns(lsColumns);
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, mapping.getPrimaryKey().get(i).getName(), null),
SqlObject.QUESTION_MARK));
}
return selectQuery.validate().toString();
}
/**
* Fills a SQL PreparedStatement of a select operation with the actual keys of
* the record to be retrieved
*
* @param statement The select PreparedStatement to be filled.
* @param mapping The ignite mapping definition of the data store
* @param selectData An Object array containing the primary key values of the
* record to be retrieved
* @throws SQLException When invalid keys' values are provided as parameters
*/
public static void fillSelectQuery(PreparedStatement statement, IgniteMapping mapping, Object... selectData) throws SQLException {
assert mapping.getPrimaryKey().size() == selectData.length;
for (int i = 0; i < mapping.getPrimaryKey().size(); i++) {
int j = i + 1;
statement.setObject(j, selectData[i]);
}
}
/**
* Returns a base SQL statement for retrieving multiple records from the
* ignite data store
*
* @param mapping The ignite mapping definition of the data store
* @param selectFields A list of columns to be retrieved within the select
* query
* @return SQL select statement
*/
public static String createSelectQuery(IgniteMapping mapping, List<String> selectFields) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
SelectQuery selectQuery = new SelectQuery();
selectQuery.addFromTable(aTable);
List<String> fields = new ArrayList<>();
for (Column c : mapping.getPrimaryKey()) {
fields.add(c.getName());
}
fields.addAll(selectFields);
DbColumn[] lsColumns = new DbColumn[fields.size()];
for (int i = 0; i < fields.size(); i++) {
lsColumns[i] = aTable.addColumn(fields.get(i));
}
selectQuery.addColumns(lsColumns);
return selectQuery.validate().toString();
}
/**
* Returns a base SQL statement for deleting multiple records from the ignite
* data store
*
* @param mapping The ignite mapping definition of the data store
* @return SQL delete statement
*/
public static String createDeleteQueryMultipleRecords(IgniteMapping mapping) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
DeleteQuery deleteQuery = new DeleteQuery(aTable);
return deleteQuery.validate().toString();
}
/**
* Returns a base SQL statement for deleting fields from records of the ignite
* data store
*
* @param mapping The ignite mapping definition of the data store
* @param deleteFields A list of columns to be deleted (set to null)
* @return SQL update statement
*/
public static String createDeleteQueryWithFields(IgniteMapping mapping, List<String> deleteFields) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
UpdateQuery updateQuery = new UpdateQuery(aTable);
for (int i = 0; i < deleteFields.size(); i++) {
updateQuery.addSetClause(new DbColumn(aTable, deleteFields.get(i), null), SqlObject.NULL_VALUE);
}
return updateQuery.validate().toString();
}
/**
* Returns a SQL's WHERE segment with proper conditions set for
* Querying/Deleting/Updating multiple records of a ignite data store
*
* @param mapping The ignite mapping definition of the data store
* @param startKey Start key of the WHERE condition
* @param endKey End key of the WHERE condition
* @param limit The maximum number of records to be consider
* @return SQL WHERE segment
*/
public static String createWhereClause(IgniteMapping mapping, Object startKey, Object endKey, long limit) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable(mapping.getTableName());
SelectQuery selectQuery = new SelectQuery();
selectQuery.addFromTable(aTable);
String fisrtPart = selectQuery.validate().toString();
String keycolumn = mapping.getPrimaryKey().get(0).getName();
if (startKey != null || endKey != null) {
if (startKey != null && endKey != null && startKey.equals(endKey)) {
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new CustomSql(keycolumn), SqlObject.QUESTION_MARK));
} else {
if (startKey != null) {
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.GREATER_THAN_OR_EQUAL_TO,
new CustomSql(keycolumn), SqlObject.QUESTION_MARK));
}
if (endKey != null) {
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.LESS_THAN_OR_EQUAL_TO,
new CustomSql(keycolumn), SqlObject.QUESTION_MARK));
}
}
}
if (limit > 0) {
selectQuery.addCustomization(new MysLimitClause(limit));
}
String completeQuery = selectQuery.validate().toString();
return completeQuery.substring(fisrtPart.length());
}
/**
* Fills a SQL PreparedStatement's WHERE segment of a select/delete/update
* operation with proper key values
*
* @param statement The select PreparedStatement to be filled.
* @param startKey Start key of the WHERE condition
* @param endKey End key of the WHERE condition
* @throws SQLException When invalid keys' values are provided as parameters
*/
public static void fillWhereClause(PreparedStatement statement, Object startKey, Object endKey) throws SQLException {
if (startKey != null || endKey != null) {
if (startKey != null && endKey != null && startKey.equals(endKey)) {
statement.setObject(1, startKey);
} else {
if (startKey != null && endKey != null) {
statement.setObject(1, startKey);
statement.setObject(2, endKey);
} else {
if (startKey != null) {
statement.setObject(1, startKey);
} else {
statement.setObject(1, endKey);
}
}
}
}
}
/**
* Returns a SQL statement for returning a list of tables
*/
public static String createSelectAllTablesNames(String schemaIgnite) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable("SYS.TABLES");
SelectQuery selectQuery = new SelectQuery();
DbColumn[] lsColumns = new DbColumn[]{aTable.addColumn("TABLE_NAME")};
selectQuery.addColumns(lsColumns);
selectQuery.addFromTable(aTable);
return selectQuery.validate().toString();
}
/**
* Returns a SQL statement for metadata of a table
*/
public static String createSelectAllColumnsOfTable(String schemaIgnite, String table) {
DbSpec spec = new DbSpec();
DbSchema schema = spec.addDefaultSchema();
DbTable aTable = schema.addTable("INFORMATION_SCHEMA.COLUMNS");
DbTable aTable2 = schema.addTable("SYS.TABLE_COLUMNS");
SelectQuery selectQuery = new SelectQuery();
DbColumn[] lsColumns = new DbColumn[]{aTable.addColumn("COLUMN_NAME"),
aTable.addColumn("TYPE_NAME"), aTable2.addColumn("PK")};
selectQuery.addColumns(lsColumns);
selectQuery.addFromTable(aTable);
selectQuery.addFromTable(aTable2);
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, "TABLE_SCHEMA", null),
schemaIgnite));
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, "TABLE_NAME", null),
table));
selectQuery.addCondition(new BinaryCondition(BinaryCondition.Op.EQUAL_TO,
new DbColumn(aTable, "COLUMN_NAME", null),
new DbColumn(aTable2, "COLUMN_NAME", null)));
return selectQuery.validate().toString();
}
}