Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.dolphindb.jdbc.JDBCStatement Maven / Gradle / Ivy
package com.dolphindb.jdbc;
import com.xxdb.data.*;
import com.xxdb.data.Void;
import java.io.IOException;
import java.sql.*;
import java.text.MessageFormat;
import java.util.*;
public class JDBCStatement implements Statement {
protected JDBCConnection connection;
protected ResultSet resultSet;
protected StringBuilder batch;
protected Queue objectQueue;
protected Object result;
protected Deque resultSets;
protected HashMap tableTypes;
protected static final String IN_MEMORY_TABLE = "IN-MEMORY TABLE";
protected boolean isClosed;
private int timeout = 100;
private int fetchSize = 0;
private int maxRows = -1;
public JDBCStatement(JDBCConnection cnn){
this.connection = cnn;
this.objectQueue = new LinkedList<>();
this.resultSets = new LinkedList<>();
this.batch = new StringBuilder();
}
@Override
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
return 0;
}
@Override
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
return 0;
}
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return 0;
}
@Override
public long executeLargeUpdate(String sql) throws SQLException {
return 0;
}
@Override
public long[] executeLargeBatch() throws SQLException {
return new long[0];
}
@Override
public long getLargeMaxRows() throws SQLException {
return 0;
}
@Override
public void setLargeMaxRows(long max) throws SQLException {
if (max < 0)
throw new SQLException("The param max cannot less than 0.");
if (max == 0)
max = -1;
this.maxRows = (int) max;
}
@Override
public long getLargeUpdateCount() throws SQLException {
return 0;
}
private String getTableType(String tableName) throws SQLException{
if (tableTypes == null) {
tableTypes = new LinkedHashMap<>();
}
String tableType = tableTypes.get(tableName);
if (tableType == null) {
try {
tableType = connection.run("typestr " + tableName).getString();
} catch (IOException e) {
throw new SQLException(e);
}
tableTypes.put(tableName, tableType);
return tableType;
}else{
return tableType;
}
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
sql = Utils.changeCase(sql, connection);
sql = sql.trim();
while (sql.endsWith(";"))
sql = sql.substring(0, sql.length() - 1);
sql = sql.trim();
if (sql!=null&&sql.equals("select 1"))
sql = "select 1 as val";
sql = Utils.outerJoinToFullJoin(sql);
sql = Utils.oracleToDolphin(sql);
String[] strings = sql.split(";");
String lastStatement = strings[strings.length - 1].trim();
int dml = Utils.getDml(lastStatement);
Entity entity;
switch (dml){
case Utils.DML_INSERT:
case Utils.DML_UPDATE:
case Utils.DML_DELETE:
throw new SQLException("The given SQL statement produces anything other than a single ResultSet object.");
case Utils.DML_SELECT:
case Utils.DML_EXEC:
case Utils.DML_OTHER:
try {
if(this.fetchSize != 0) {
if (fetchSize < 8192) {
throw new SQLException("The fetchSize param must be greater than 8192.");
}
entity = connection.run(sql, fetchSize);
} else {
entity = connection.run(sql);
}
if (entity instanceof BasicTable || entity.getDataForm() == Entity.DATA_FORM.DF_SCALAR
|| entity.getDataForm() == Entity.DATA_FORM.DF_VECTOR || entity.getDataForm() == Entity.DATA_FORM.DF_MATRIX) {
resultSet = new JDBCResultSet(connection, this, entity, sql, this.maxRows);
return resultSet;
} else if(entity instanceof EntityBlockReader) {
resultSet = new JDBCResultSet(connection, this, (EntityBlockReader) entity, sql, this.maxRows);
return resultSet;
} else {
throw new SQLException("The given SQL statement produces anything other than a single ResultSet object.");
}
} catch (IOException e){
throw new SQLException(e);
}
default:
throw new SQLException("The given SQL statement produces anything other than a single ResultSet object.");
}
}
@Override
public int executeUpdate(String sql) throws SQLException {
sql = Utils.changeCase(sql, connection);
sql = sql.trim();
while (sql.endsWith(";"))
sql = sql.substring(0, sql.length() - 1);
String[] strings = sql.split(";");
String lastStatement = strings[strings.length - 1].trim();
String tableName = Utils.getTableName(lastStatement, false);
int dml = Utils.getDml(lastStatement);
String tableType;
switch (dml) {
case Utils.DML_INSERT:
if (tableName != null) {
tableType = getTableType(tableName);
if (tableType.equals(IN_MEMORY_TABLE)) {
try {
connection.run(sql);
return SUCCESS_NO_INFO;
} catch (IOException e) {
throw new SQLException(e);
}
} else {
String INSERT_SQL_COMMA_SPLIT_REGEX = ",(?=(?:[^()]*\\([^()]*\\))*[^()]*$)";
String[] values = lastStatement.substring(lastStatement.indexOf("values") + "values".length()).replaceAll("^\\(|\\)$", "").split(INSERT_SQL_COMMA_SPLIT_REGEX, -1);
String runSql = processValueInSql(tableName, values);
try {
connection.run(runSql);
return SUCCESS_NO_INFO;
} catch (IOException e) {
throw new SQLException(e);
}
}
} else {
throw new SQLException("check the SQL " + sql);
}
case Utils.DML_UPDATE:
case Utils.DML_DELETE:
if (tableName != null) {
try {
connection.run(sql);
return SUCCESS_NO_INFO;
} catch (IOException e) {
throw new SQLException(e);
}
} else {
throw new SQLException("check the Query " + sql);
}
case Utils.DML_SELECT:
case Utils.DML_EXEC:
throw new SQLException("Can not issue SELECT or EXEC via executeUpdate()");
default:
Entity entity;
try {
entity = connection.run(sql);
}catch (IOException e){
throw new SQLException(e);
}
if(entity instanceof BasicTable){
throw new SQLException("Can not produces ResultSet");
}
return 0;
}
}
protected String processValueInSql(String tableName, String[] values) {
StringBuilder sqlSb = new StringBuilder("append!(").append(tableName).append(",").append("table(");
String colName = "col";
int colIndex = 1;
AbstractVector typeStringVec;
try {
typeStringVec = getNULLValueType(tableName);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < values.length; i++) {
if (values[i].trim().equals("NULL")) {
String nullValueType = typeStringVec.get(i).getString().toLowerCase();
sqlSb.append(nullValueType).append("(").append(values[i]).append(")").append(" as ").append(colName+colIndex).append(",");
colIndex++;
} else if (values[i].trim().equals("")) {
String nullValueType = typeStringVec.get(i).getString().toLowerCase();
if (nullValueType.equals("complex") || nullValueType.equals("point")) {
sqlSb.append(nullValueType).append("(00i,00i)").append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.contains("decimal")) {
String DECIMAL_REGEX = "decimal(32|64|128)\\((\\d+)\\)";
String NULL_replacement = "decimal$1(NULL, $2)";
String replacedDecimal = nullValueType.replaceAll(DECIMAL_REGEX, NULL_replacement);
sqlSb.append(replacedDecimal).append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.equals("symbol")) {
sqlSb.append("array(SYMBOL, 0, 1)").append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.equals("uuid")) {
sqlSb.append("uuid(\"\")").append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.equals("ipaddr")) {
sqlSb.append("ipaddr(\"\")").append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.equals("int128")) {
sqlSb.append("int128(\"\")").append(" as ").append(colName+colIndex).append(",");
} else if (nullValueType.equals("blob")) {
sqlSb.append("blob(string(NULL))").append(" as ").append(colName+colIndex).append(",");
} else {
sqlSb.append(nullValueType).append("(NULL)").append(" as ").append(colName+colIndex).append(",");
}
colIndex++;
} else {
sqlSb.append(values[i]).append(" as ").append(colName+colIndex).append(",");
colIndex++;
}
}
sqlSb.delete(sqlSb.length() - ",".length(), sqlSb.length());
sqlSb.append("))");
return sqlSb.toString();
}
protected AbstractVector getNULLValueType(String tableName) throws IOException {
BasicDictionary schema = (BasicDictionary) connection.run(String.format("schema(%s)", tableName));
BasicTable colDefs = (BasicTable) schema.get(new BasicString("colDefs"));
AbstractVector typeStringVec = (AbstractVector) colDefs.getColumn("typeString");
return typeStringVec;
}
@Override
public void close() throws SQLException {
isClosed = true;
batch = null;
result = null;
if(objectQueue != null){
objectQueue.clear();
objectQueue = null;
}
if(resultSet != null) {
resultSet.close();
objectQueue = null;
}
if(tableTypes != null){
tableTypes.clear();
tableTypes = null;
}
}
@Override
public int getMaxFieldSize() throws SQLException {
return 0;
}
@Override
public void setMaxFieldSize(int maxFieldSize) throws SQLException {
}
@Override
public int getMaxRows() throws SQLException {
if (this.maxRows <= 0)
return 0;
return this.maxRows;
}
@Override
public void setMaxRows(int maxRows) throws SQLException {
setLargeMaxRows(maxRows);
}
@Override
public void setEscapeProcessing(boolean b) throws SQLException {
Driver.unused();
}
@Override
public int getQueryTimeout() throws SQLException {
return timeout;
}
@Override
public void setQueryTimeout(int queryTimeout) throws SQLException {
timeout = queryTimeout * 1000;
}
@Override
public void cancel() throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public SQLWarning getWarnings() throws SQLException {
// TODO: implement warnings
return null;
}
@Override
public void clearWarnings() throws SQLException {
// TODO: implement warnings
}
@Override
public void setCursorName(String cursorName) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
public String trimFirstAndLastChar(String str, String element){
boolean beginIndexFlag = true;
boolean endIndexFlag = true;
do{
int beginIndex = str.indexOf(element) == 0 ? 1 : 0;
int endIndex = str.lastIndexOf(element) + 1 == str.length() ? str.lastIndexOf(element) : str.length();
str = str.substring(beginIndex, endIndex);
beginIndexFlag = (str.indexOf(element) == 0);
endIndexFlag = (str.lastIndexOf(element) + 1 == str.length());
} while (beginIndexFlag || endIndexFlag);
return str;
}
@Override
public boolean execute(String sql) throws SQLException {
sql = Utils.changeCase(sql);
sql = sql.trim();
while (sql.endsWith(";"))
sql = sql.substring(0, sql.length() - 1);
sql = sql.trim();
if (sql!=null&&sql.equals("select 1"))
sql = "select 1 as val";
String[] strings;
if(sql.startsWith("[")&&sql.endsWith("]")){
String temp = trimFirstAndLastChar(sql,"[");
sql = trimFirstAndLastChar(temp,"]");
strings = sql.split(",");
String[] statementbatch = strings;
for(int i =0; i< statementbatch.length;i++){
ResultSet resultSet_batch = executeQuery(statementbatch[i]);
resultSets.offerLast(resultSet_batch);
objectQueue.offer(resultSet_batch);
}
if (objectQueue.isEmpty()) {
return false;
} else {
result = objectQueue.poll();
return result instanceof ResultSet;
}
} else
strings = sql.split(";");
String lastStatement = strings[strings.length - 1].trim();
int dml = Utils.getDml(lastStatement);
switch (dml) {
case Utils.DML_SELECT:
case Utils.DML_EXEC: {
ResultSet resultSet_ = executeQuery(sql);
resultSets.offerLast(resultSet_);
objectQueue.offer(resultSet_);
}
break;
case Utils.DML_INSERT:
case Utils.DML_UPDATE:
case Utils.DML_DELETE:
objectQueue.offer(executeUpdate(sql));
break;
default: {
Entity entity;
try {
entity = connection.run(sql);
} catch (IOException e) {
throw new SQLException(e);
}
if (entity instanceof BasicTable || (entity.getDataForm() == Entity.DATA_FORM.DF_SCALAR && !(entity instanceof Void))
|| entity.getDataForm() == Entity.DATA_FORM.DF_VECTOR || entity.getDataForm() == Entity.DATA_FORM.DF_MATRIX) {
ResultSet resultSet = new JDBCResultSet(connection, this, entity, sql, this.maxRows);
resultSets.offerLast(resultSet);
objectQueue.offer(resultSet);
}
}
}
if (objectQueue.isEmpty()) {
return false;
} else {
result = objectQueue.poll();
return result instanceof ResultSet;
}
}
@Override
public ResultSet getResultSet() throws SQLException {
if(result == null) {
resultSet = null;
}else if(result instanceof ResultSet){
resultSet = (JDBCResultSet) result;
}else{
resultSet = null;
}
result = null;
return resultSet;
}
@Override
public int getUpdateCount() throws SQLException {
int updateCount;
if(result == null) {
updateCount = -1;
}else if(result instanceof Integer){
updateCount = (int)result;
}else{
updateCount = -1;
}
result = null;
return updateCount;
}
@Override
public boolean getMoreResults() throws SQLException {
while (!resultSets.isEmpty()){
ResultSet resultSet_ = resultSets.pollFirst();
if(resultSet_ == null){
resultSet_.close();
}
}
if(!objectQueue.isEmpty()){
result = objectQueue.poll();
return result instanceof ResultSet;
}else{
return false;
}
}
@Override
public void setFetchDirection(int direction) throws SQLException {
switch (direction) {
case java.sql.ResultSet.FETCH_FORWARD:
break;
default:
throw new SQLException("DolpinDB JDBC Statement direction only suppport FETCH_FORWARD.");
}
}
@Override
public int getFetchDirection() throws SQLException {
return java.sql.ResultSet.FETCH_FORWARD;
}
@Override
public void setFetchSize(int fetchSize) throws SQLException {
this.fetchSize = fetchSize;
}
@Override
public int getFetchSize() throws SQLException {
return fetchSize;
}
@Override
public int getResultSetConcurrency() throws SQLException {
Driver.unused();
return 0;
}
@Override
public int getResultSetType() throws SQLException {
Driver.unused();
return 0;
}
@Override
public void addBatch(String sql) throws SQLException {
batch.append(sql).append(";\n");
}
@Override
public void clearBatch() throws SQLException {
batch.delete(0,batch.length());
}
@Override
public int[] executeBatch() throws SQLException {
String[] strings = batch.toString().split(";");
int[] arr_int = new int[strings.length];
int index = 0;
try {
for(String item : strings){
arr_int[index] = executeUpdate(item);
++index;
}
batch.delete(0,batch.length());
return arr_int;
}catch (SQLException e){
batch.delete(0,batch.length());
throw new BatchUpdateException(e.getMessage(),Arrays.copyOf(arr_int,index));
}
}
@Override
public Connection getConnection() throws SQLException {
return connection;
}
@Override
public boolean getMoreResults(int current) throws SQLException{
switch (current){
case Statement.CLOSE_ALL_RESULTS:
while (!resultSets.isEmpty()){
ResultSet resultSet_ = resultSets.pollLast();
if(resultSet_ != null){
resultSet_.close();
}
}
break;
case Statement.CLOSE_CURRENT_RESULT:
if(resultSet != null){
resultSet.close();
}
break;
case Statement.KEEP_CURRENT_RESULT:
break;
default:
throw new SQLException("The argument supplied is not one of the following:\n" +
"Statement.CLOSE_CURRENT_RESULT,\n" +
"Statement.KEEP_CURRENT_RESULT or\n" +
" Statement.CLOSE_ALL_RESULTS");
}
return false;
}
@Override
public ResultSet getGeneratedKeys() throws SQLException {
Driver.unused();
return null;
}
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException{
return executeUpdate(sql);
}
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException{
return executeUpdate(sql);
}
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException{
return executeUpdate(sql);
}
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException{
return execute(sql);
}
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException{
return execute(sql);
}
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException{
return execute(sql);
}
@Override
public int getResultSetHoldability() throws SQLException {
Driver.unused();
return 0;
}
@Override
public boolean isClosed() throws SQLException {
return isClosed;
}
@Override
public void setPoolable(boolean b) throws SQLException {
Driver.unused();
}
@Override
public boolean isPoolable() throws SQLException {
Driver.unused();
return false;
}
@Override
public void closeOnCompletion() throws SQLException {
Driver.unused();
}
@Override
public boolean isCloseOnCompletion() throws SQLException {
Driver.unused();
return false;
}
@Override
public T unwrap(Class aClass) throws SQLException {
return aClass.cast(this);
}
@Override
public boolean isWrapperFor(Class> aClass) throws SQLException {
return aClass.isInstance(this);
}
protected BasicInt tableInsert(String tableName, String sql) throws IOException{
if (sql.startsWith("tableInsert")){
return (BasicInt)connection.run(sql);
}
else {
String values;
int index = sql.indexOf(";");
if (index == -1) {
values = sql.substring(sql.indexOf("values") + "values".length());
} else {
values = sql.substring(sql.indexOf("values") + "values".length(), index);
}
String new_sql = MessageFormat.format("tableInsert({0},{1})", tableName, values);
BasicInt n = (BasicInt) connection.run(new_sql);
return n;
}
}
}