提交 56d1c42f 编写于 作者: 陶建辉(Jeff)'s avatar 陶建辉(Jeff)

add destIp support for NAT

上级 aea2e74e
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class CatalogResultSet extends TSDBResultSetWrapper {
public CatalogResultSet(ResultSet resultSet) {
super.setOriginalResultSet(resultSet);
}
@Override
public String getString(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getString(columnIndex);
} else {
return null;
}
}
@Override
public boolean getBoolean(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getBoolean(columnIndex);
} else {
return false;
}
}
@Override
public byte[] getBytes(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getBytes(columnIndex);
} else {
return null;
}
}
@Override
public Object getObject(int columnIndex) throws SQLException {
if (columnIndex <= 1) {
return super.getObject(columnIndex);
} else {
return null;
}
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
public class ColumnMetaData {
int colType = 0;
String colName = null;
int colSize = -1;
int colIndex = 0;
public int getColSize() {
return colSize;
}
public void setColSize(int colSize) {
this.colSize = colSize;
}
public int getColType() {
return colType;
}
public void setColType(int colType) {
this.colType = colType;
}
public String getColName() {
return colName;
}
public void setColName(String colName) {
this.colName = colName;
}
public int getColIndex() {
return colIndex;
}
public void setColIndex(int colIndex) {
this.colIndex = colIndex;
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class GetColumnsResultSet extends TSDBResultSetWrapper {
private String catalog;
private String schemaPattern;
private String tableNamePattern;
private String columnNamePattern;
public GetColumnsResultSet(ResultSet resultSet, String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) {
super.setOriginalResultSet(resultSet);
this.catalog = catalog;
this.schemaPattern = schemaPattern;
this.tableNamePattern = tableNamePattern;
this.columnNamePattern = columnNamePattern;
}
@Override
public String getString(int columnIndex) {
switch (columnIndex) {
case 1:
return catalog;
case 2:
return null;
case 3:
return tableNamePattern;
default:
return null;
}
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
* TDengine only supports a subset of the standard SQL, thus this implemetation of the
* standard JDBC API contains more or less some adjustments customized for certain
* compatibility needs.
*/
public class GetTablesResultSet extends TSDBResultSetWrapper {
private String catalog;
private String schemaPattern;
private String tableNamePattern;
private String[] types;
public GetTablesResultSet(ResultSet resultSet, String catalog, String schemaPattern, String tableNamePattern, String[] types) {
super.setOriginalResultSet(resultSet);
this.catalog = catalog;
this.schemaPattern = schemaPattern;
this.tableNamePattern = tableNamePattern;
this.types = types;
}
@Override
public String getString(int columnIndex) throws SQLException {
String ret = null;
switch (columnIndex) {
case 3:
return super.getString(1);
case 4:
return "table";
default:
return null;
}
}
}
package com.taosdata.jdbc;
import com.taosdata.jdbc.bean.TSDBPreparedParam;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* this class is used to precompile the sql of tdengine insert or import ops
*/
public class SavedPreparedStatement {
private TSDBPreparedStatement tsdbPreparedStatement;
/**
* sql param List
*/
private List<TSDBPreparedParam> sqlParamList;
/**
* init param according the sql
*/
private TSDBPreparedParam initPreparedParam;
/**
* is table name dynamic in the prepared sql
*/
private boolean isTableNameDynamic;
/**
* insert or import sql template pattern, the template are the following:
* <p>
* insert/import into tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ] values(?, ?, ...) (?, ?, ...)
* <p>
* we split it to three part:
* 1. prefix, insert/import
* 2. middle, tableName [(field1, field2, ...)] [using stables tags(?, ?, ...) ]
* 3. valueList, the content after values, for example (?, ?, ...) (?, ?, ...)
*/
private Pattern sqlPattern = Pattern.compile("(?s)(?i)^\\s*(INSERT|IMPORT)\\s+INTO\\s+((?<tablename>\\S+)\\s*(\\(.*\\))?\\s+(USING\\s+(?<stableName>\\S+)\\s+TAGS\\s*\\((?<tagValue>.+)\\))?)\\s*VALUES\\s*(?<valueList>\\(.*\\)).*");
/**
* the raw sql template
*/
private String sql;
/**
* the prefix part of sql
*/
private String prefix;
/**
* the middle part of sql
*/
private String middle;
private int middleParamSize;
/**
* the valueList part of sql
*/
private String valueList;
private int valueListSize;
/**
* default param value
*/
private static final String DEFAULT_VALUE = "NULL";
private static final String PLACEHOLDER = "?";
private String tableName;
/**
* is the parameter add to batch list
*/
private boolean isAddBatch;
public SavedPreparedStatement(String sql, TSDBPreparedStatement tsdbPreparedStatement) throws SQLException {
this.sql = sql;
this.tsdbPreparedStatement = tsdbPreparedStatement;
this.sqlParamList = new ArrayList<>();
parsePreparedParam(this.sql);
}
/**
* parse the init param according the sql param
*
* @param sql
*/
private void parsePreparedParam(String sql) throws SQLException {
Matcher matcher = sqlPattern.matcher(sql);
if (matcher.find()) {
tableName = matcher.group("tablename");
if (tableName != null && PLACEHOLDER.equals(tableName)) {
// the table name is dynamic
this.isTableNameDynamic = true;
}
prefix = matcher.group(1);
middle = matcher.group(2);
valueList = matcher.group("valueList");
if (middle != null && !"".equals(middle)) {
middleParamSize = parsePlaceholder(middle);
}
if (valueList != null && !"".equals(valueList)) {
valueListSize = parsePlaceholder(valueList);
}
initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
} else {
// not match
throw new SQLException(TSDBConstants.WrapErrMsg("the sql is not complete!"));
}
}
private TSDBPreparedParam initDefaultParam(String tableName, int middleParamSize, int valueListSize) {
TSDBPreparedParam tsdbPreparedParam = new TSDBPreparedParam(tableName);
tsdbPreparedParam.setMiddleParamList(getDefaultParamList(middleParamSize));
tsdbPreparedParam.setValueList(getDefaultParamList(valueListSize));
return tsdbPreparedParam;
}
/**
* generate the default param value list
*
* @param paramSize
* @return
*/
private List<Object> getDefaultParamList(int paramSize) {
List<Object> paramList = new ArrayList<>(paramSize);
if (paramSize > 0) {
for (int i = 0; i < paramSize; i++) {
paramList.add(i, DEFAULT_VALUE);
}
}
return paramList;
}
/**
* calculate the placeholder num
*
* @param value
* @return
*/
private int parsePlaceholder(String value) {
Pattern pattern = Pattern.compile("[?]");
Matcher matcher = pattern.matcher(value);
int result = 0;
while (matcher.find()) {
result++;
}
return result;
}
/**
* set current row params
*
* @param parameterIndex the first parameter is 1, the second is 2, ...
* @param x the parameter value
*/
public void setParam(int parameterIndex, Object x) throws SQLException {
int paramSize = this.middleParamSize + this.valueListSize;
String errorMsg = String.format("the parameterIndex %s out of the range [1, %s]", parameterIndex, paramSize);
if (parameterIndex < 1 || parameterIndex > paramSize) {
throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
}
this.isAddBatch = false; //set isAddBatch to false
if (x == null) {
x = DEFAULT_VALUE; // set default null string
}
parameterIndex = parameterIndex - 1; // start from 0 in param list
if (this.middleParamSize > 0 && parameterIndex >= 0 && parameterIndex < this.middleParamSize) {
this.initPreparedParam.setMiddleParam(parameterIndex, x);
return;
}
if (this.valueListSize > 0 && parameterIndex >= this.middleParamSize && parameterIndex < paramSize) {
this.initPreparedParam.setValueParam(parameterIndex - this.middleParamSize, x);
return;
}
throw new SQLException(TSDBConstants.WrapErrMsg(errorMsg));
}
public void addBatch() {
addCurrentRowParamToList();
this.initPreparedParam = initDefaultParam(tableName, middleParamSize, valueListSize);
}
/**
* add current param to batch list
*/
private void addCurrentRowParamToList() {
if (initPreparedParam != null && (this.middleParamSize > 0 || this.valueListSize > 0)) {
this.sqlParamList.add(initPreparedParam); // add current param to batch list
}
this.isAddBatch = true;
}
/**
* execute the sql with batch sql
*
* @return
* @throws SQLException
*/
public int[] executeBatch() throws SQLException {
int result = executeBatchInternal();
return new int[]{result};
}
public int executeBatchInternal() throws SQLException {
if (!isAddBatch) {
addCurrentRowParamToList(); // add current param to batch list
}
//1. generate batch sql
String sql = generateExecuteSql();
//2. execute batch sql
int result = executeSql(sql);
//3. clear batch param list
this.sqlParamList.clear();
return result;
}
/**
* generate the batch sql
*
* @return
*/
private String generateExecuteSql() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(prefix);
stringBuilder.append(" into ");
if (!isTableNameDynamic) {
// tablename will not need to be replaced
String middleValue = replaceMiddleListParam(middle, sqlParamList);
stringBuilder.append(middleValue);
stringBuilder.append(" values");
stringBuilder.append(replaceValueListParam(valueList, sqlParamList));
} else {
// need to replace tablename
if (sqlParamList.size() > 0) {
TSDBPreparedParam firstPreparedParam = sqlParamList.get(0);
//replace middle part and value part of first row
String firstRow = replaceMiddleAndValuePart(firstPreparedParam);
stringBuilder.append(firstRow);
//the first param in the middleParamList is the tableName
String lastTableName = firstPreparedParam.getMiddleParamList().get(0).toString();
if (sqlParamList.size() > 1) {
for (int i = 1; i < sqlParamList.size(); i++) {
TSDBPreparedParam currentParam = sqlParamList.get(i);
String currentTableName = currentParam.getMiddleParamList().get(0).toString();
if (lastTableName.equalsIgnoreCase(currentTableName)) {
// tablename is same with the last row ,so only need to append the part of value
String values = replaceTemplateParam(valueList, currentParam.getValueList());
stringBuilder.append(values);
} else {
// tablename difference with the last row
//need to replace middle part and value part
String row = replaceMiddleAndValuePart(currentParam);
stringBuilder.append(row);
lastTableName = currentTableName;
}
}
}
} else {
stringBuilder.append(middle);
stringBuilder.append(" values");
stringBuilder.append(valueList);
}
}
return stringBuilder.toString();
}
/**
* replace the middle and value part
*
* @param tsdbPreparedParam
* @return
*/
private String replaceMiddleAndValuePart(TSDBPreparedParam tsdbPreparedParam) {
StringBuilder stringBuilder = new StringBuilder(" ");
String middlePart = replaceTemplateParam(middle, tsdbPreparedParam.getMiddleParamList());
stringBuilder.append(middlePart);
stringBuilder.append(" values ");
String valuePart = replaceTemplateParam(valueList, tsdbPreparedParam.getValueList());
stringBuilder.append(valuePart);
stringBuilder.append(" ");
return stringBuilder.toString();
}
/**
* replace the placeholder of the middle part of sql template with TSDBPreparedParam list
*
* @param template
* @param sqlParamList
* @return
*/
private String replaceMiddleListParam(String template, List<TSDBPreparedParam> sqlParamList) {
if (sqlParamList.size() > 0) {
//becase once the subTableName is static then will be ignore the tag which after the first setTag
return replaceTemplateParam(template, sqlParamList.get(0).getMiddleParamList());
}
return template;
}
/**
* replace the placeholder of the template with TSDBPreparedParam list
*
* @param template
* @param sqlParamList
* @return
*/
private String replaceValueListParam(String template, List<TSDBPreparedParam> sqlParamList) {
StringBuilder stringBuilder = new StringBuilder();
if (sqlParamList.size() > 0) {
for (TSDBPreparedParam tsdbPreparedParam : sqlParamList) {
String tmp = replaceTemplateParam(template, tsdbPreparedParam.getValueList());
stringBuilder.append(tmp);
}
} else {
stringBuilder.append(template);
}
return stringBuilder.toString();
}
/**
* replace the placeholder of the template with paramList
*
* @param template
* @param paramList
* @return
*/
private String replaceTemplateParam(String template, List<Object> paramList) {
if (paramList.size() > 0) {
String tmp = template;
for (int i = 0; i < paramList.size(); ++i) {
String paraStr = getParamString(paramList.get(i));
tmp = tmp.replaceFirst("[" + PLACEHOLDER + "]", paraStr);
}
return tmp;
} else {
return template;
}
}
/**
* get the string of param object
*
* @param paramObj
* @return
*/
private String getParamString(Object paramObj) {
String paraStr = paramObj.toString();
if (paramObj instanceof Timestamp || (paramObj instanceof String && !DEFAULT_VALUE.equalsIgnoreCase(paraStr))) {
paraStr = "'" + paraStr + "'";
}
return paraStr;
}
private int executeSql(String sql) throws SQLException {
return tsdbPreparedStatement.executeUpdate(sql);
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class TSDBConnection implements Connection {
private TSDBJNIConnector connector = null;
protected Properties props = null;
private String catalog = null;
private TSDBDatabaseMetaData dbMetaData = null;
private Properties clientInfoProps = new Properties();
private int timeoutMilliseconds = 0;
private String tsCharSet = "";
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
this.dbMetaData = meta;
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")),
info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), info.getProperty(TSDBDriver.PROPERTY_KEY_USER),
info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD));
}
private void connect(String host, int port, String dbName, String user, String password) throws SQLException {
this.connector = new TSDBJNIConnector();
this.connector.connect(host, port, dbName, user, password);
try {
this.setCatalog(dbName);
} catch (SQLException e) {
e.printStackTrace();
}
this.dbMetaData.setConnection(this);
}
public TSDBJNIConnector getConnection() {
return this.connector;
}
public Statement createStatement() throws SQLException {
if (!this.connector.isClosed()) {
return new TSDBStatement(this.connector);
} else {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
if (!this.connector.isClosed()) {
return new TSDBPreparedStatement(this.connector, sql);
} else {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
}
}
public CallableStatement prepareCall(String sql) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public String nativeSQL(String sql) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
public boolean getAutoCommit() throws SQLException {
return true;
}
public void commit() throws SQLException {
}
public void rollback() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void close() throws SQLException {
if (this.connector != null && !this.connector.isClosed()) {
this.connector.closeConnection();
} else {
throw new SQLException(TSDBConstants.WrapErrMsg("connection is already closed!"));
}
}
public boolean isClosed() throws SQLException {
return this.connector.isClosed();
}
/**
* A connection's database is able to provide information describing its tables,
* its supported SQL grammar, its stored procedures, the capabilities of this
* connection, etc. This information is made available through a
* DatabaseMetaData object.
*
* @return a DatabaseMetaData object for this connection
* @exception SQLException
* if a database access error occurs
*/
public DatabaseMetaData getMetaData() throws SQLException {
return this.dbMetaData;
}
/**
* This readOnly option is not supported by TDengine. However, the method is intentionally left blank here to
* support HikariCP connection.
* @param readOnly
* @throws SQLException
*/
public void setReadOnly(boolean readOnly) throws SQLException {
}
public boolean isReadOnly() throws SQLException {
return true;
}
public void setCatalog(String catalog) throws SQLException {
this.catalog = catalog;
}
public String getCatalog() throws SQLException {
return this.catalog;
}
/**
* The transaction isolation level option is not supported by TDengine.
* This method is intentionally left empty to support HikariCP connection.
* @param level
* @throws SQLException
*/
public void setTransactionIsolation(int level) throws SQLException {
}
/**
* The transaction isolation level option is not supported by TDengine.
* @return
* @throws SQLException
*/
public int getTransactionIsolation() throws SQLException {
return Connection.TRANSACTION_NONE;
}
public SQLWarning getWarnings() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void clearWarnings() throws SQLException {
// left blank to support HikariCP connection
//todo: implement getWarnings according to the warning messages returned from TDengine
}
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
// This method is implemented in the current way to support Spark
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY) {
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
}
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw new SQLException(TSDBConstants.INVALID_VARIABLES);
}
return this.prepareStatement(sql);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void setHoldability(int holdability) throws SQLException {
// intentionally left empty to support druid connection pool.
}
/**
* the transaction is not supported by TDengine, so the opened ResultSet Objects will remain open
* @return
* @throws SQLException
*/
public int getHoldability() throws SQLException {
//intentionally left empty to support HikariCP connection.
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
public Savepoint setSavepoint() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Savepoint setSavepoint(String name) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void rollback(Savepoint savepoint) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return this.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Clob createClob() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Blob createBlob() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public NClob createNClob() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public SQLXML createSQLXML() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public boolean isValid(int timeout) throws SQLException {
return !this.isClosed();
}
public void setClientInfo(String name, String value) throws SQLClientInfoException {
clientInfoProps.setProperty(name, value);
}
public void setClientInfo(Properties properties) throws SQLClientInfoException {
for (Enumeration<Object> enumer = properties.keys(); enumer.hasMoreElements();) {
String name = (String) enumer.nextElement();
clientInfoProps.put(name, properties.getProperty(name));
}
}
public String getClientInfo(String name) throws SQLException {
return clientInfoProps.getProperty(name);
}
public Properties getClientInfo() throws SQLException {
return clientInfoProps;
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void setSchema(String schema) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public String getSchema() throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void abort(Executor executor) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
this.timeoutMilliseconds = milliseconds;
}
public int getNetworkTimeout() throws SQLException {
return this.timeoutMilliseconds;
}
public <T> T unwrap(Class<T> iface) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG);
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.util.HashMap;
import java.util.Map;
public abstract class TSDBConstants {
public static final String DEFAULT_PORT = "6200";
public static final String UNSUPPORT_METHOD_EXCEPTIONZ_MSG = "this operation is NOT supported currently!";
public static final String INVALID_VARIABLES = "invalid variables";
public static Map<Integer, String> DATATYPE_MAP = null;
public static final long JNI_NULL_POINTER = 0L;
public static final int JNI_SUCCESS = 0;
public static final int JNI_TDENGINE_ERROR = -1;
public static final int JNI_CONNECTION_NULL = -2;
public static final int JNI_RESULT_SET_NULL = -3;
public static final int JNI_NUM_OF_FIELDS_0 = -4;
public static final int JNI_SQL_NULL = -5;
public static final int JNI_FETCH_END = -6;
public static final int TSDB_DATA_TYPE_NULL = 0;
public static final int TSDB_DATA_TYPE_BOOL = 1;
public static final int TSDB_DATA_TYPE_TINYINT = 2;
public static final int TSDB_DATA_TYPE_SMALLINT = 3;
public static final int TSDB_DATA_TYPE_INT = 4;
public static final int TSDB_DATA_TYPE_BIGINT = 5;
public static final int TSDB_DATA_TYPE_FLOAT = 6;
public static final int TSDB_DATA_TYPE_DOUBLE = 7;
public static final int TSDB_DATA_TYPE_BINARY = 8;
public static final int TSDB_DATA_TYPE_TIMESTAMP = 9;
public static final int TSDB_DATA_TYPE_NCHAR = 10;
public static String WrapErrMsg(String msg) {
return "TDengine Error: " + msg;
}
public static String FixErrMsg(int code) {
switch (code) {
case JNI_TDENGINE_ERROR:
return WrapErrMsg("internal error of database!");
case JNI_CONNECTION_NULL:
return WrapErrMsg("invalid tdengine connection!");
case JNI_RESULT_SET_NULL:
return WrapErrMsg("invalid resultset pointer!");
case JNI_NUM_OF_FIELDS_0:
return WrapErrMsg("invalid num of fields!");
case JNI_SQL_NULL:
return WrapErrMsg("can't execute empty sql!");
case JNI_FETCH_END:
return WrapErrMsg("fetch to the end of resultset");
default:
break;
}
return WrapErrMsg("unkown error!");
}
static {
DATATYPE_MAP = new HashMap<Integer, String>();
DATATYPE_MAP.put(1, "BOOL");
DATATYPE_MAP.put(2, "TINYINT");
DATATYPE_MAP.put(3, "SMALLINT");
DATATYPE_MAP.put(4, "INT");
DATATYPE_MAP.put(5, "BIGINT");
DATATYPE_MAP.put(6, "FLOAT");
DATATYPE_MAP.put(7, "DOUBLE");
DATATYPE_MAP.put(8, "BINARY");
DATATYPE_MAP.put(9, "TIMESTAMP");
DATATYPE_MAP.put(10, "NCHAR");
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import org.apache.commons.lang3.StringUtils;
import java.sql.*;
import java.util.Properties;
import java.util.logging.Logger;
/**
* The Java SQL framework allows for multiple database drivers. Each driver
* should supply a class that implements the Driver interface
*
* <p>
* The DriverManager will try to load as many drivers as it can find and then
* for any given connection request, it will ask each driver in turn to try to
* connect to the target URL.
*
* <p>
* It is strongly recommended that each Driver class should be small and stand
* alone so that the Driver class can be loaded and queried without bringing in
* vast quantities of supporting code.
*
* <p>
* When a Driver class is loaded, it should create an instance of itself and
* register it with the DriverManager. This means that a user can load and
* register a driver by doing Class.forName("foo.bah.Driver")
*/
public class TSDBDriver implements java.sql.Driver {
@Deprecated
private static final String URL_PREFIX1 = "jdbc:TSDB://";
private static final String URL_PREFIX = "jdbc:TAOS://";
/**
* Key used to retrieve the database value from the properties instance passed
* to the driver.
*/
public static final String PROPERTY_KEY_DBNAME = "dbname";
/**
* Key used to retrieve the host value from the properties instance passed to
* the driver.
*/
public static final String PROPERTY_KEY_HOST = "host";
/**
* Key used to retrieve the password value from the properties instance passed
* to the driver.
*/
public static final String PROPERTY_KEY_PASSWORD = "password";
/**
* Key used to retrieve the port number value from the properties instance
* passed to the driver.
*/
public static final String PROPERTY_KEY_PORT = "port";
/**
* Key used to retrieve the user value from the properties instance passed to
* the driver.
*/
public static final String PROPERTY_KEY_USER = "user";
/**
* Key for the configuration file directory of TSDB client in properties instance
*/
public static final String PROPERTY_KEY_CONFIG_DIR = "cfgdir";
/**
* Key for the timezone used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_TIME_ZONE = "timezone";
/**
* Key for the locale used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_LOCALE = "locale";
/**
* Key for the char encoding used by the TSDB client in properties instance
*/
public static final String PROPERTY_KEY_CHARSET = "charset";
public static final String PROPERTY_KEY_PROTOCOL = "protocol";
/**
* Index for port coming out of parseHostPortPair().
*/
public final static int PORT_NUMBER_INDEX = 1;
/**
* Index for host coming out of parseHostPortPair().
*/
public final static int HOST_NAME_INDEX = 0;
private TSDBDatabaseMetaData dbMetaData = null;
static {
try {
java.sql.DriverManager.registerDriver(new TSDBDriver());
} catch (SQLException E) {
throw new RuntimeException(TSDBConstants.WrapErrMsg("can't register tdengine jdbc driver!"));
}
}
public Connection connect(String url, Properties info) throws SQLException {
if (url == null) {
throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!"));
}
Properties props = null;
if ((props = parseURL(url, info)) == null) {
return null;
}
try {
TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), (String) props.get(PROPERTY_KEY_CHARSET),
(String) props.get(PROPERTY_KEY_TIME_ZONE));
Connection newConn = new TSDBConnection(props, this.dbMetaData);
return newConn;
} catch (SQLWarning sqlWarning) {
sqlWarning.printStackTrace();
Connection newConn = new TSDBConnection(props, this.dbMetaData);
return newConn;
} catch (SQLException sqlEx) {
throw sqlEx;
} catch (Exception ex) {
SQLException sqlEx = new SQLException("SQLException:" + ex.toString());
sqlEx.initCause(ex);
throw sqlEx;
}
}
/**
* Parses hostPortPair in the form of [host][:port] into an array, with the
* element of index HOST_NAME_INDEX being the host (or null if not specified),
* and the element of index PORT_NUMBER_INDEX being the port (or null if not
* specified).
*
* @param hostPortPair
* host and port in form of of [host][:port]
*
* @return array containing host and port as Strings
*
* @throws SQLException
* if a parse error occurs
*/
protected static String[] parseHostPortPair(String hostPortPair) throws SQLException {
String[] splitValues = new String[2];
int portIndex = hostPortPair.indexOf(":");
String hostname = null;
if (portIndex != -1) {
if ((portIndex + 1) < hostPortPair.length()) {
String portAsString = hostPortPair.substring(portIndex + 1);
hostname = hostPortPair.substring(0, portIndex);
splitValues[HOST_NAME_INDEX] = hostname;
splitValues[PORT_NUMBER_INDEX] = portAsString;
} else {
throw new SQLException(TSDBConstants.WrapErrMsg("port is not proper!"));
}
} else {
splitValues[HOST_NAME_INDEX] = hostPortPair;
splitValues[PORT_NUMBER_INDEX] = null;
}
return splitValues;
}
public boolean acceptsURL(String url) throws SQLException {
return true;
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
if (info == null) {
info = new Properties();
}
if ((url != null) && (url.startsWith(URL_PREFIX) || url.startsWith(URL_PREFIX1))) {
info = parseURL(url, info);
}
DriverPropertyInfo hostProp = new DriverPropertyInfo(PROPERTY_KEY_HOST, info.getProperty(PROPERTY_KEY_HOST));
hostProp.required = true;
DriverPropertyInfo portProp = new DriverPropertyInfo(PROPERTY_KEY_PORT,
info.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
portProp.required = false;
DriverPropertyInfo dbProp = new DriverPropertyInfo(PROPERTY_KEY_DBNAME, info.getProperty(PROPERTY_KEY_DBNAME));
dbProp.required = false;
dbProp.description = "Database name";
DriverPropertyInfo userProp = new DriverPropertyInfo(PROPERTY_KEY_USER, info.getProperty(PROPERTY_KEY_USER));
userProp.required = true;
DriverPropertyInfo passwordProp = new DriverPropertyInfo(PROPERTY_KEY_PASSWORD,
info.getProperty(PROPERTY_KEY_PASSWORD));
passwordProp.required = true;
DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5];
propertyInfo[0] = hostProp;
propertyInfo[1] = portProp;
propertyInfo[2] = dbProp;
propertyInfo[3] = userProp;
propertyInfo[4] = passwordProp;
return propertyInfo;
}
/**
* example: jdbc:TSDB://127.0.0.1:0/db?user=root&password=your_password
*/
public Properties parseURL(String url, Properties defaults) throws java.sql.SQLException {
Properties urlProps = (defaults != null) ? defaults : new Properties();
if (url == null) {
return null;
}
if (!StringUtils.startsWithIgnoreCase(url, URL_PREFIX) && !StringUtils.startsWithIgnoreCase(url, URL_PREFIX1)) {
return null;
}
String urlForMeta = url;
String dbProductName = url.substring(url.indexOf(":") + 1);
dbProductName = dbProductName.substring(0, dbProductName.indexOf(":"));
int beginningOfSlashes = url.indexOf("//");
url = url.substring(beginningOfSlashes + 2);
String host = url.substring(0, url.indexOf(":"));
url = url.substring(url.indexOf(":") + 1);
urlProps.setProperty(PROPERTY_KEY_HOST, host);
String port = url.substring(0, url.indexOf("/"));
urlProps.setProperty(PROPERTY_KEY_PORT, port);
url = url.substring(url.indexOf("/") + 1);
if (url.indexOf("?") != -1) {
String dbName = url.substring(0, url.indexOf("?"));
urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName);
url = url.trim().substring(1);
} else {
// without user & password so return
String dbName = url.trim();
urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName);
this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty("user"));
return urlProps;
}
String[] queryStrings = url.trim().split("&");
String user = "";
for (String queryStr : queryStrings) {
String[] kvPair = queryStr.trim().split("=");
if (kvPair.length < 2){
continue;
}
switch (kvPair[0].toLowerCase()) {
case PROPERTY_KEY_USER:
urlProps.setProperty(PROPERTY_KEY_USER, kvPair[1]);
user = kvPair[1];
break;
case PROPERTY_KEY_PASSWORD:
urlProps.setProperty(PROPERTY_KEY_PASSWORD, kvPair[1]);
break;
case PROPERTY_KEY_TIME_ZONE:
urlProps.setProperty(PROPERTY_KEY_TIME_ZONE, kvPair[1]);
break;
case PROPERTY_KEY_LOCALE:
urlProps.setProperty(PROPERTY_KEY_LOCALE, kvPair[1]);
break;
case PROPERTY_KEY_CHARSET:
urlProps.setProperty(PROPERTY_KEY_CHARSET, kvPair[1]);
break;
case PROPERTY_KEY_CONFIG_DIR:
urlProps.setProperty(PROPERTY_KEY_CONFIG_DIR, kvPair[1]);
break;
}
}
this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, user);
return urlProps;
}
public int getMajorVersion() {
return 1;
}
public int getMinorVersion() {
return 1;
}
public boolean jdbcCompliant() {
return false;
}
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
/**
* Returns the host property
*
* @param props
* the java.util.Properties instance to retrieve the hostname from.
*
* @return the host
*/
public String host(Properties props) {
return props.getProperty(PROPERTY_KEY_HOST, "localhost");
}
/**
* Returns the port number property
*
* @param props
* the properties to get the port number from
*
* @return the port number
*/
public int port(Properties props) {
return Integer.parseInt(props.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
}
/**
* Returns the database property from <code>props</code>
*
* @param props
* the Properties to look for the database property.
*
* @return the database name.
*/
public String database(Properties props) {
return props.getProperty(PROPERTY_KEY_DBNAME);
}
}
\ No newline at end of file
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.util.HashMap;
import java.util.Map;
/**
*
* TDengine error code and error message enumeration.
*
*/
public enum TSDBError {
TSDB_CODE_SUCCESS(0, "success"),
TSDB_CODE_ACTION_IN_PROGRESS(1, "in progress"),
TSDB_CODE_LAST_SESSION_NOT_FINISHED(5, "last session not finished"),
TSDB_CODE_INVALID_SESSION_ID(6, "invalid session ID"),
TSDB_CODE_INVALID_TRAN_ID(7, "invalid tran ID"),
TSDB_CODE_INVALID_MSG_TYPE(8, "invalid msg type"),
TSDB_CODE_ALREADY_PROCESSED(9, "alredy processed"),
TSDB_CODE_AUTH_FAILURE(10, "authentication failure"),
TSDB_CODE_WRONG_MSG_SIZE(11, "wrong msg size"),
TSDB_CODE_UNEXPECTED_RESPONSE(12, "unexpected response"),
TSDB_CODE_INVALID_RESPONSE_TYPE(13, "invalid response type"),
TSDB_CODE_NO_RESOURCE(14, "no resource"),
TSDB_CODE_INVALID_TIME_STAMP(15, "invalid time stamp"),
TSDB_CODE_MISMATCHED_METER_ID(16, "mismatched meter ID"),
TSDB_CODE_ACTION_TRANS_NOT_FINISHED(17, "transcation not finished"),
TSDB_CODE_ACTION_NOT_ONLINE(18, "not online"),
TSDB_CODE_ACTION_SEND_FAILD(19, "send failed"),
TSDB_CODE_NOT_ACTIVE_SESSION(20, "not active session"),
TSDB_CODE_INSERT_FAILED(21, "insert failed"),
TSDB_CODE_APP_ERROR(22, "App error"),
TSDB_CODE_INVALID_IE(23, "invalid IE"),
TSDB_CODE_INVALID_VALUE(24, "invalid value"),
TSDB_CODE_REDIRECT(25, "service not available"),
TSDB_CODE_ALREADY_THERE(26, "already there"),
TSDB_CODE_INVALID_METER_ID(27, "invalid meter ID"),
TSDB_CODE_INVALID_SQL(28, "invalid SQL"), // this message often comes with additional info which will vary based on the specific error situation
TSDB_CODE_NETWORK_UNAVAIL(29, "failed to connect to server"),
TSDB_CODE_INVALID_MSG_LEN(30, "invalid msg len"),
TSDB_CODE_INVALID_DB(31, "invalid DB"),
TSDB_CODE_INVALID_TABLE(32, "invalid table"),
TSDB_CODE_DB_ALREADY_EXIST(33, "DB already there"),
TSDB_CODE_TABLE_ALREADY_EXIST(34, "table already there"),
TSDB_CODE_INVALID_USER(35, "invalid user name"),
TSDB_CODE_INVALID_ACCT(36, "invalid acct name"),
TSDB_CODE_INVALID_PASS(37, "invalid password"),
TSDB_CODE_DB_NOT_SELECTED(38, "DB not selected"),
TSDB_CODE_MEMORY_CORRUPTED(39, "memory corrupted"),
TSDB_CODE_USER_ALREADY_EXIST(40, "user name exists"),
TSDB_CODE_NO_RIGHTS(41, "not authorized"),
TSDB_CODE_DISCONNECTED(42, "login disconnected), login again"),
TSDB_CODE_NO_MASTER(43, "mgmt master node not available"),
TSDB_CODE_NOT_CONFIGURED(44, "not configured"),
TSDB_CODE_INVALID_OPTION(45, "invalid option"),
TSDB_CODE_NODE_OFFLINE(46, "node offline"),
TSDB_CODE_SYNC_REQUIRED(47, "sync required"),
TSDB_CODE_NO_ENOUGH_DNODES(48, "more dnodes are needed"),
TSDB_CODE_UNSYNCED(49, "node in unsynced state"),
TSDB_CODE_TOO_SLOW(50, "too slow"),
TSDB_CODE_OTHERS(51, "others"),
TSDB_CODE_NO_REMOVE_MASTER(52, "can't remove dnode which is master"),
TSDB_CODE_WRONG_SCHEMA(53, "wrong schema"),
TSDB_CODE_NO_RESULT(54, "no results"),
TSDB_CODE_TOO_MANY_USERS(55, "num of users execeed maxUsers"),
TSDB_CODE_TOO_MANY_DATABSES(56, "num of databases execeed maxDbs"),
TSDB_CODE_TOO_MANY_TABLES(57, "num of tables execeed maxTables"),
TSDB_CODE_TOO_MANY_DNODES(58, "num of dnodes execeed maxDnodes"),
TSDB_CODE_TOO_MANY_ACCTS(59, "num of accounts execeed maxAccts"),
TSDB_CODE_ACCT_ALREADY_EXIST(60, "accout name exists"),
TSDB_CODE_DNODE_ALREADY_EXIST(61, "dnode ip exists"),
TSDB_CODE_SDB_ERROR(62, "sdb error"),
TSDB_CODE_METRICMETA_EXPIRED(63, "metric meta expired"), // local cached metric-meta expired causes error in metric query
TSDB_CODE_NOT_READY(64, "not ready"), // peer is not ready to process data
TSDB_CODE_MAX_SESSIONS(65, "too many sessions on server"), // too many sessions
TSDB_CODE_MAX_CONNECTIONS(66, "too many sessions from app"), // too many connections
TSDB_CODE_SESSION_ALREADY_EXIST(67, "session to dest is already there"),
TSDB_CODE_NO_QSUMMARY(68, "query list not there), please show again"),
TSDB_CODE_SERV_OUT_OF_MEMORY(69, "server out of memory"),
TSDB_CODE_INVALID_QHANDLE(70, "invalid query handle"),
TSDB_CODE_RELATED_TABLES_EXIST(71, "tables related to metric exist"),
TSDB_CODE_MONITOR_DB_FORBEIDDEN(72, "can't drop monitor database or tables"),
TSDB_CODE_VG_COMMITLOG_INIT_FAILED(73, "commit log init failed"),
TSDB_CODE_VG_INIT_FAILED(74, "vgroup init failed"),
TSDB_CODE_DATA_ALREADY_IMPORTED(75, "data is already imported"),
TSDB_CODE_OPS_NOT_SUPPORT(76, "not supported operation"),
TSDB_CODE_INVALID_QUERY_ID(77, "invalid query id string"),
TSDB_CODE_INVALID_STREAM_ID(78, "invalid stream id string"),
TSDB_CODE_INVALID_CONNECTION(79, "invalid connection string"),
TSDB_CODE_ACTION_NOT_BALANCED(80, "dnode not balanced"),
TSDB_CODE_CLI_OUT_OF_MEMORY(81, "client out of memory"),
TSDB_CODE_DATA_OVERFLOW(82, "data value overflow"),
TSDB_CODE_QUERY_CANCELLED(83, "query cancelled"),
TSDB_CODE_GRANT_POINT_LIMITED(84, "grant points limited"),
TSDB_CODE_GRANT_EXPIRED(85, "grant expired"),
TSDB_CODE_CLI_NO_DISKSPACE(86, "client no disk space"),
TSDB_CODE_FILE_CORRUPTED(87, "DB file corrupted"),
TSDB_CODE_INVALID_CLIENT_VERSION(88, "version of client and server not match");
private long errCode;
private String errMessage;
private static Map<Integer, String> errorCodeMap = new HashMap<>(86);
static {
errorCodeMap.put(0, "success");
errorCodeMap.put(1, "in progress");
errorCodeMap.put(5, "last session not finished");
errorCodeMap.put(6, "invalid session ID");
errorCodeMap.put(7, "invalid tran ID");
errorCodeMap.put(8, "invalid msg type");
errorCodeMap.put(9, "alredy processed");
errorCodeMap.put(10, "authentication failure");
errorCodeMap.put(11, "wrong msg size");
errorCodeMap.put(12, "unexpected response");
errorCodeMap.put(13, "invalid response type");
errorCodeMap.put(14, "no resource");
errorCodeMap.put(15, "invalid time stamp");
errorCodeMap.put(16, "mismatched meter ID");
errorCodeMap.put(17, "transcation not finished");
errorCodeMap.put(18, "not online");
errorCodeMap.put(19, "send failed");
errorCodeMap.put(20, "not active session");
errorCodeMap.put(21, "insert failed");
errorCodeMap.put(22, "App error");
errorCodeMap.put(23, "invalid IE");
errorCodeMap.put(24, "invalid value");
errorCodeMap.put(25, "service not available");
errorCodeMap.put(26, "already there");
errorCodeMap.put(27, "invalid meter ID");
errorCodeMap.put(28, "invalid SQL"); // this message often comes with additional info which will vary based on the specific error situation
errorCodeMap.put(29, "failed to connect to server");
errorCodeMap.put(30, "invalid msg len");
errorCodeMap.put(31, "invalid DB");
errorCodeMap.put(32, "invalid table");
errorCodeMap.put(33, "DB already there");
errorCodeMap.put(34, "table already there");
errorCodeMap.put(35, "invalid user name");
errorCodeMap.put(36, "invalid acct name");
errorCodeMap.put(37, "invalid password");
errorCodeMap.put(38, "DB not selected");
errorCodeMap.put(39, "memory corrupted");
errorCodeMap.put(40, "user name exists");
errorCodeMap.put(41, "not authorized");
errorCodeMap.put(42, "login disconnected); login again");
errorCodeMap.put(43, "mgmt master node not available");
errorCodeMap.put(44, "not configured");
errorCodeMap.put(45, "invalid option");
errorCodeMap.put(46, "node offline");
errorCodeMap.put(47, "sync required");
errorCodeMap.put(48, "more dnodes are needed");
errorCodeMap.put(49, "node in unsynced state");
errorCodeMap.put(50, "too slow");
errorCodeMap.put(51, "others");
errorCodeMap.put(52, "can't remove dnode which is master");
errorCodeMap.put(53, "wrong schema");
errorCodeMap.put(54, "no results");
errorCodeMap.put(55, "num of users execeed maxUsers");
errorCodeMap.put(56, "num of databases execeed maxDbs");
errorCodeMap.put(57, "num of tables execeed maxTables");
errorCodeMap.put(58, "num of dnodes execeed maxDnodes");
errorCodeMap.put(59, "num of accounts execeed maxAccts");
errorCodeMap.put(60, "accout name exists");
errorCodeMap.put(61, "dnode ip exists");
errorCodeMap.put(62, "sdb error");
errorCodeMap.put(63, "metric meta expired"); // local cached metric-meta expired causes error in metric query
errorCodeMap.put(64, "not ready"); // peer is not ready to process data
errorCodeMap.put(65, "too many sessions on server"); // too many sessions
errorCodeMap.put(66, "too many sessions from app"); // too many connections
errorCodeMap.put(67, "session to dest is already there");
errorCodeMap.put(68, "query list not there); please show again");
errorCodeMap.put(69, "server out of memory");
errorCodeMap.put(70, "invalid query handle");
errorCodeMap.put(71, "tables related to metric exist");
errorCodeMap.put(72, "can't drop monitor database or tables");
errorCodeMap.put(73, "commit log init failed");
errorCodeMap.put(74, "vgroup init failed");
errorCodeMap.put(75, "data is already imported");
errorCodeMap.put(76, "not supported operation");
errorCodeMap.put(77, "invalid query id string");
errorCodeMap.put(78, "invalid stream id string");
errorCodeMap.put(79, "invalid connection string");
errorCodeMap.put(80, "dnode not balanced");
errorCodeMap.put(81, "client out of memory");
errorCodeMap.put(82, "data value overflow");
errorCodeMap.put(83, "query cancelled");
errorCodeMap.put(84, "grant points limited");
errorCodeMap.put(85, "grant expired");
errorCodeMap.put(86, "client no disk space");
errorCodeMap.put(87, "DB file corrupted");
errorCodeMap.put(88, "version of client and server not match");
}
TSDBError(long code, String message) {
this.errCode = code;
this.errMessage = message;
}
public long getErrCode() {
return this.errCode;
}
public String getErrMessage() {
return this.errMessage;
}
public static String getErrMessageByCode(long errCode) {
return errorCodeMap.get(errCode);
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.List;
public class TSDBJNIConnector {
static volatile Boolean isInitialized = false;
static {
System.loadLibrary("taos");
System.out.println("java.library.path:" + System.getProperty("java.library.path"));
}
/**
* Connection pointer used in C
*/
private long taos = TSDBConstants.JNI_NULL_POINTER;
/**
* Result set pointer for the current connection
*/
private long taosResultSetPointer = TSDBConstants.JNI_NULL_POINTER;
/**
* result set status in current connection
*/
private boolean isResultsetClosed = true;
private int affectedRows = -1;
/**
* Whether the connection is closed
*/
public boolean isClosed() {
return this.taos == TSDBConstants.JNI_NULL_POINTER;
}
/**
* Returns the status of last result set in current connection
*
* @return
*/
public boolean isResultsetClosed() {
return this.isResultsetClosed;
}
/**
* Initialize static variables in JNI to optimize performance
*/
public static void init(String configDir, String locale, String charset, String timezone) throws SQLWarning {
synchronized (isInitialized) {
if (!isInitialized) {
initImp(configDir);
if (setOptions(0, locale) < 0) {
throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set locale: " + locale + ". System default will be used."));
}
if (setOptions(1, charset) < 0) {
throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set charset: " + charset + ". System default will be used."));
}
if (setOptions(2, timezone) < 0) {
throw new SQLWarning(TSDBConstants.WrapErrMsg("Failed to set timezone: " + timezone + ". System default will be used."));
}
isInitialized = true;
TaosGlobalConfig.setCharset(getTsCharset());
}
}
}
public static native void initImp(String configDir);
public static native int setOptions(int optionIndex, String optionValue);
public static native String getTsCharset();
/**
* Get connection pointer
*
* @throws SQLException
*/
public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException {
if (this.taos != TSDBConstants.JNI_NULL_POINTER) {
this.closeConnectionImp(this.taos);
this.taos = TSDBConstants.JNI_NULL_POINTER;
}
this.taos = this.connectImp(host, port, dbName, user, password);
if (this.taos == TSDBConstants.JNI_NULL_POINTER) {
throw new SQLException(TSDBConstants.WrapErrMsg(this.getErrMsg()), "", this.getErrCode());
}
return true;
}
private native long connectImp(String host, int port, String dbName, String user, String password);
/**
* Execute DML/DDL operation
*
* @throws SQLException
*/
public int executeQuery(String sql) throws SQLException {
if (!this.isResultsetClosed) {
freeResultSet(taosResultSetPointer);
}
int code;
try {
code = this.executeQueryImp(sql.getBytes(TaosGlobalConfig.getCharset()), this.taos);
} catch (Exception e) {
e.printStackTrace();
throw new SQLException(TSDBConstants.WrapErrMsg("Unsupported encoding"));
}
affectedRows = code;
if (code < 0) {
affectedRows = -1;
if (code == TSDBConstants.JNI_TDENGINE_ERROR) {
throw new SQLException(TSDBConstants.WrapErrMsg(this.getErrMsg()), "", this.getErrCode());
} else {
throw new SQLException(TSDBConstants.FixErrMsg(code), "", this.getErrCode());
}
}
// Try retrieving result set for the executed SQL using the current connection pointer. If the executed
// SQL is a DML/DDL which doesn't return a result set, then taosResultSetPointer should be 0L. Otherwise,
// taosResultSetPointer should be a non-zero value.
taosResultSetPointer = this.getResultSetImp(this.taos);
if (taosResultSetPointer != TSDBConstants.JNI_NULL_POINTER) {
isResultsetClosed = false;
}
return code;
}
private native int executeQueryImp(byte[] sqlBytes, long connection);
/**
* Get recent error code by connection
*/
public int getErrCode() {
return Math.abs(this.getErrCodeImp(this.taos));
}
private native int getErrCodeImp(long connection);
/**
* Get recent error message by connection
*/
public String getErrMsg() {
return this.getErrMsgImp(this.taos);
}
private native String getErrMsgImp(long connection);
/**
* Get resultset pointer
* Each connection should have a single open result set at a time
*/
public long getResultSet() {
return taosResultSetPointer;
}
private native long getResultSetImp(long connection);
/**
* Free resultset operation from C to release resultset pointer by JNI
*/
public int freeResultSet(long result) {
int res = TSDBConstants.JNI_SUCCESS;
if (result != taosResultSetPointer && taosResultSetPointer != TSDBConstants.JNI_NULL_POINTER) {
throw new RuntimeException("Invalid result set pointer");
} else if (taosResultSetPointer != TSDBConstants.JNI_NULL_POINTER) {
res = this.freeResultSetImp(this.taos, result);
isResultsetClosed = true; // reset resultSetPointer to 0 after freeResultSetImp() return
taosResultSetPointer = TSDBConstants.JNI_NULL_POINTER;
} else {
isResultsetClosed = true;
}
return res;
}
/**
* Close the open result set which is associated to the current connection. If the result set is already
* closed, return 0 for success.
*
* @return
*/
public int freeResultSet() {
int resCode = TSDBConstants.JNI_SUCCESS;
if (!isResultsetClosed) {
resCode = this.freeResultSetImp(this.taos, this.taosResultSetPointer);
taosResultSetPointer = TSDBConstants.JNI_NULL_POINTER;
isResultsetClosed = true;
}
return resCode;
}
private native int freeResultSetImp(long connection, long result);
/**
* Get affected rows count
*/
public int getAffectedRows() {
int affectedRows = this.affectedRows;
if (affectedRows < 0) {
affectedRows = this.getAffectedRowsImp(this.taos);
}
return affectedRows;
}
private native int getAffectedRowsImp(long connection);
/**
* Get schema metadata
*/
public int getSchemaMetaData(long resultSet, List<ColumnMetaData> columnMetaData) {
return this.getSchemaMetaDataImp(this.taos, resultSet, columnMetaData);
}
private native int getSchemaMetaDataImp(long connection, long resultSet, List<ColumnMetaData> columnMetaData);
/**
* Get one row data
*/
public int fetchRow(long resultSet, TSDBResultSetRowData rowData) {
return this.fetchRowImp(this.taos, resultSet, rowData);
}
private native int fetchRowImp(long connection, long resultSet, TSDBResultSetRowData rowData);
/**
* Execute close operation from C to release connection pointer by JNI
*
* @throws SQLException
*/
public void closeConnection() throws SQLException {
int code = this.closeConnectionImp(this.taos);
if (code < 0) {
throw new SQLException(TSDBConstants.FixErrMsg(code), "", this.getErrCode());
} else if (code == 0) {
this.taos = TSDBConstants.JNI_NULL_POINTER;
} else {
throw new SQLException("Undefined error code returned by TDengine when closing a connection");
}
}
private native int closeConnectionImp(long connection);
/**
* Subscribe to a table in TSDB
*/
public long subscribe(String host, String user, String password, String database, String table, long time, int period) {
return subscribeImp(host, user, password, database, table, time, period);
}
private native long subscribeImp(String host, String user, String password, String database, String table, long time, int period);
/**
* Consume a subscribed table
*/
public TSDBResultSetRowData consume(long subscription) {
return this.consumeImp(subscription);
}
private native TSDBResultSetRowData consumeImp(long subscription);
/**
* Unsubscribe a table
*
* @param subscription
*/
public void unsubscribe(long subscription) {
unsubscribeImp(subscription);
}
private native void unsubscribeImp(long subscription);
/**
* Validate if a <I>create table</I> sql statement is correct without actually creating that table
*/
public boolean validateCreateTableSql(String sql) {
long connection = taos;
int res = validateCreateTableSqlImp(connection, sql.getBytes());
return res != 0 ? false : true;
}
private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes);
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
import java.sql.ParameterMetaData;
import java.sql.SQLException;
public class TSDBParameterMetaData implements ParameterMetaData {
@Override
public int getParameterCount() throws SQLException {
return 0;
}
@Override
public int isNullable(int param) throws SQLException {
return 0;
}
@Override
public boolean isSigned(int param) throws SQLException {
return false;
}
@Override
public int getPrecision(int param) throws SQLException {
return 0;
}
@Override
public int getScale(int param) throws SQLException {
return 0;
}
@Override
public int getParameterType(int param) throws SQLException {
return 0;
}
@Override
public String getParameterTypeName(int param) throws SQLException {
return null;
}
@Override
public String getParameterClassName(int param) throws SQLException {
return null;
}
@Override
public int getParameterMode(int param) throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc;
public class TaosGlobalConfig {
static String charset = "";
public static String getCharset() {
if (charset == null || charset.isEmpty()) {
charset = System.getProperty("file.encoding");
}
return charset;
}
public static void setCharset(String tsCharset) {
TaosGlobalConfig.charset = tsCharset;
}
}
/***************************************************************************
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
package com.taosdata.jdbc.utils;
import com.taosdata.jdbc.TSDBConnection;
import com.taosdata.jdbc.TSDBJNIConnector;
import java.sql.Connection;
import java.sql.SQLException;
public class SqlSyntaxValidator {
private TSDBConnection tsdbConnection;
public SqlSyntaxValidator(Connection connection) {
this.tsdbConnection = (TSDBConnection) connection;
}
public boolean validateSqlSyntax(String sql) throws SQLException {
boolean res = false;
if (tsdbConnection == null || tsdbConnection.isClosed()) {
throw new SQLException("invalid connection");
} else {
TSDBJNIConnector jniConnector = tsdbConnection.getConnection();
if (jniConnector == null) {
throw new SQLException("jniConnector is null");
} else {
res = jniConnector.validateCreateTableSql(sql);
}
}
return res;
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册