From 2f5f47224ce5ed0d26d6d6d14b0612a111031a4e Mon Sep 17 00:00:00 2001 From: Zhiyu Yang <69311263+zyyang-taosdata@users.noreply.github.com> Date: Fri, 14 Jan 2022 08:47:23 +0800 Subject: [PATCH] [TS-1063](connector): one batch bind multi tables' data (#9785) * [TS-1063](connector): one batch bind multi tables' data * [TS-1063](connector): jdbc change * [TS-1063](connector): fix null pointer exception * [TS-1063](connector): init and prepared stmt until setTableName --- .../jni/com_taosdata_jdbc_TSDBJNIConnector.h | 30 ++- src/client/src/TSDBJNIConnector.c | 186 +++++++++++------- .../com/taosdata/jdbc/TSDBJNIConnector.java | 35 +++- .../taosdata/jdbc/TSDBPreparedStatement.java | 75 ++++--- 4 files changed, 202 insertions(+), 124 deletions(-) diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index 79d481498e..4c999b710a 100644 --- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -47,7 +47,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions * Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException; */ JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp - (JNIEnv *, jclass, jstring); + (JNIEnv *, jclass, jstring); /* * Class: com_taosdata_jdbc_TSDBJNIConnector @@ -209,6 +209,15 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp (JNIEnv *, jobject, jlong, jstring, jlong); + +/** + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: setTableNameTagsImp + * Signature: (JLjava/lang/String;I[B[B[B[BJ)I + */ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp + (JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: bindColDataImp @@ -217,6 +226,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp (JNIEnv *, jobject, jlong, jbyteArray, jbyteArray, jbyteArray, jint, jint, jint, jint, jlong); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: stmt_add_batch + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con); + + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: executeBatchImp @@ -231,13 +248,12 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(J */ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, jlong con); -/** +/* * Class: com_taosdata_jdbc_TSDBJNIConnector - * Method: setTableNameTagsImp - * Signature: (JLjava/lang/String;I[B[B[B[BJ)I + * Method: stmt_errstr + * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp - (JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong); +JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con); /* * Class: com_taosdata_jdbc_TSDBJNIConnector @@ -245,7 +261,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI * Signature: ([Ljava/lang/String;JII)I */ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp - (JNIEnv *, jobject, jobjectArray, jlong, jint, jint); + (JNIEnv *, jobject, jobjectArray, jlong, jint, jint); #ifdef __cplusplus } diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 5fd5371fb3..468aac437d 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -370,7 +370,7 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(J JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS * tscon = (TAOS *)con; + TAOS *tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, tres); if (code != JNI_SUCCESS) { return code; @@ -413,7 +413,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp( JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { - TAOS * tscon = (TAOS *)con; + TAOS *tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { return code; @@ -429,13 +429,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsIm JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp(JNIEnv *env, jobject jobj, jlong con, jlong res, jobject arrayListObj) { - TAOS * tscon = (TAOS *)con; + TAOS *tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { return code; } - TAOS_RES * tres = (TAOS_RES *)res; + TAOS_RES *tres = (TAOS_RES *)res; TAOS_FIELD *fields = taos_fetch_fields(tres); int32_t num_fields = taos_num_fields(tres); @@ -572,13 +572,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con, jlong res, jobject rowobj) { - TAOS * tscon = (TAOS *)con; + TAOS *tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { return code; } - TAOS_RES * tres = (TAOS_RES *)res; + TAOS_RES *tres = (TAOS_RES *)res; TAOS_FIELD *fields = taos_fetch_fields(tres); int32_t numOfFields = taos_num_fields(tres); @@ -810,6 +810,78 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI return JNI_SUCCESS; } +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp( + JNIEnv *env, jobject jobj, jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList, + jbyteArray lengthList, jbyteArray nullList, jlong conn) { + TAOS *tsconn = (TAOS *)conn; + if (tsconn == NULL) { + jniError("jobj:%p, connection already closed", jobj); + return JNI_CONNECTION_NULL; + } + + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; + if (pStmt == NULL) { + jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn); + return JNI_SQL_NULL; + } + + jsize len = (*env)->GetArrayLength(env, tags); + char *tagsData = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, tags, 0, len, (jbyte *)tagsData); + if ((*env)->ExceptionCheck(env)) { + // todo handle error + } + + len = (*env)->GetArrayLength(env, lengthList); + int64_t *lengthArray = (int64_t *)calloc(1, len); + (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray); + if ((*env)->ExceptionCheck(env)) { + } + + len = (*env)->GetArrayLength(env, typeList); + char *typeArray = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte *)typeArray); + if ((*env)->ExceptionCheck(env)) { + } + + len = (*env)->GetArrayLength(env, nullList); + int32_t *nullArray = (int32_t *)calloc(1, len); + (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray); + if ((*env)->ExceptionCheck(env)) { + } + + const char *name = (*env)->GetStringUTFChars(env, tableName, NULL); + char *curTags = tagsData; + + TAOS_BIND *tagsBind = calloc(numOfTags, sizeof(TAOS_BIND)); + for (int32_t i = 0; i < numOfTags; ++i) { + tagsBind[i].buffer_type = typeArray[i]; + tagsBind[i].buffer = curTags; + tagsBind[i].is_null = &nullArray[i]; + tagsBind[i].length = (uintptr_t *)&lengthArray[i]; + + curTags += lengthArray[i]; + } + + int32_t code = taos_stmt_set_tbname_tags((void *)stmt, name, tagsBind); + + int32_t nTags = (int32_t)numOfTags; + jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, nTags); + + tfree(tagsData); + tfree(lengthArray); + tfree(typeArray); + tfree(nullArray); + tfree(tagsBind); + (*env)->ReleaseStringUTFChars(env, tableName, name); + + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code)); + return JNI_TDENGINE_ERROR; + } + return JNI_SUCCESS; +} + JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp( JNIEnv *env, jobject jobj, jlong stmt, jbyteArray colDataList, jbyteArray lengthList, jbyteArray nullList, jint dataType, jint dataBytes, jint numOfRows, jint colIndex, jlong con) { @@ -877,8 +949,8 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp( return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt, - jlong con) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); @@ -891,19 +963,18 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(J return JNI_SQL_NULL; } - taos_stmt_add_batch(pStmt); - int32_t code = taos_stmt_execute(pStmt); + int32_t code = taos_stmt_add_batch(pStmt); if (code != TSDB_CODE_SUCCESS) { jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); return JNI_TDENGINE_ERROR; } - jniDebug("jobj:%p, conn:%p, batch execute", jobj, tscon); + jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, - jlong con) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); @@ -916,90 +987,61 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv return JNI_SQL_NULL; } - int32_t code = taos_stmt_close(pStmt); + int32_t code = taos_stmt_execute(pStmt); if (code != TSDB_CODE_SUCCESS) { jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); return JNI_TDENGINE_ERROR; } - jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); + jniDebug("jobj:%p, conn:%p, batch execute", jobj, tscon); return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp( - JNIEnv *env, jobject jobj, jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList, - jbyteArray lengthList, jbyteArray nullList, jlong conn) { - TAOS *tsconn = (TAOS *)conn; - if (tsconn == NULL) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { + TAOS *tscon = (TAOS *)con; + if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { - jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn); + jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon); return JNI_SQL_NULL; } - jsize len = (*env)->GetArrayLength(env, tags); - char *tagsData = (char *)calloc(1, len); - (*env)->GetByteArrayRegion(env, tags, 0, len, (jbyte *)tagsData); - if ((*env)->ExceptionCheck(env)) { - // todo handle error - } - - len = (*env)->GetArrayLength(env, lengthList); - int64_t *lengthArray = (int64_t *)calloc(1, len); - (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray); - if ((*env)->ExceptionCheck(env)) { + int32_t code = taos_stmt_close(pStmt); + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); + return JNI_TDENGINE_ERROR; } - len = (*env)->GetArrayLength(env, typeList); - char *typeArray = (char *)calloc(1, len); - (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte *)typeArray); - if ((*env)->ExceptionCheck(env)) { - } + jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); + return JNI_SUCCESS; +} - len = (*env)->GetArrayLength(env, nullList); - int32_t *nullArray = (int32_t *)calloc(1, len); - (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray); - if ((*env)->ExceptionCheck(env)) { +JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { + char errMsg[128]; + TAOS *tscon = (TAOS *)con; + if (tscon == NULL) { + jniError("jobj:%p, connection already closed", jobj); + sprintf(errMsg, "jobj:%p, connection already closed", jobj); + return (*env)->NewStringUTF(env, errMsg); } - const char *name = (*env)->GetStringUTFChars(env, tableName, NULL); - char * curTags = tagsData; - - TAOS_BIND *tagsBind = calloc(numOfTags, sizeof(TAOS_BIND)); - for (int32_t i = 0; i < numOfTags; ++i) { - tagsBind[i].buffer_type = typeArray[i]; - tagsBind[i].buffer = curTags; - tagsBind[i].is_null = &nullArray[i]; - tagsBind[i].length = (uintptr_t *)&lengthArray[i]; - - curTags += lengthArray[i]; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; + if (pStmt == NULL) { + jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon); + sprintf(errMsg, "jobj:%p, conn:%p, invalid stmt", jobj, tscon); + return (*env)->NewStringUTF(env, errMsg); } - int32_t code = taos_stmt_set_tbname_tags((void *)stmt, name, tagsBind); - - int32_t nTags = (int32_t)numOfTags; - jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, nTags); - - tfree(tagsData); - tfree(lengthArray); - tfree(typeArray); - tfree(nullArray); - tfree(tagsBind); - (*env)->ReleaseStringUTFChars(env, tableName, name); - - if (code != TSDB_CODE_SUCCESS) { - jniError("jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code)); - return JNI_TDENGINE_ERROR; - } - return JNI_SUCCESS; + return (*env)->NewStringUTF(env, taos_stmt_errstr((TAOS_STMT *)stmt)); } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp - (JNIEnv *env, jobject jobj, jobjectArray lines, jlong conn, jint protocol, jint precision){ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp (JNIEnv *env, jobject jobj, jobjectArray lines, jlong conn, jint protocol, jint precision){ TAOS *taos = (TAOS *)conn; if (taos == NULL) { jniError("jobj:%p, connection already closed", jobj); @@ -1031,4 +1073,4 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp return JNI_TDENGINE_ERROR; } return code; -} \ No newline at end of file +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index b1e0d5e062..d9a61f5af8 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -29,6 +29,8 @@ public class TSDBJNIConnector { System.loadLibrary("taos"); } + /***********************************************************************/ + //NOTE: JDBC public static void init(Properties props) throws SQLWarning { synchronized (LOCK) { if (!isInitialized) { @@ -243,6 +245,9 @@ public class TSDBJNIConnector { private native int closeConnectionImp(long connection); + /*****************************************************************************************/ + // NOTE: subscribe + /** * Create a subscription */ @@ -270,6 +275,8 @@ public class TSDBJNIConnector { private native void unsubscribeImp(long subscription, boolean isKeep); + /******************************************************************************************************/ + // NOTE: parameter binding public long prepareStmt(String sql) throws SQLException { long stmt = prepareStmtImp(sql.getBytes(), this.taos); @@ -294,16 +301,19 @@ public class TSDBJNIConnector { public void setBindTableName(long stmt, String tableName) throws SQLException { int code = setBindTableNameImp(stmt, tableName, this.taos); if (code != TSDBConstants.JNI_SUCCESS) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "table name: " + tableName + ", failed to set table name"); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, + "failed to set table name, reason: " + stmtErrorMsgImp(stmt, this.taos)); } } private native int setBindTableNameImp(long stmt, String name, long conn); - public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException { + public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, + ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException { int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), nullList.array(), this.taos); if (code != TSDBConstants.JNI_SUCCESS) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind table name and corresponding tags"); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, + "failed to bind table name and corresponding tags, reason: " + stmtErrorMsgImp(stmt, this.taos)); } } @@ -312,7 +322,8 @@ public class TSDBJNIConnector { public void bindColumnDataArray(long stmt, ByteBuffer colDataList, ByteBuffer lengthList, ByteBuffer isNullList, int type, int bytes, int numOfRows, int columnIndex) throws SQLException { int code = bindColDataImp(stmt, colDataList.array(), lengthList.array(), isNullList.array(), type, bytes, numOfRows, columnIndex, this.taos); if (code != TSDBConstants.JNI_SUCCESS) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind column data"); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, + "failed to bind column data, reason: " + stmtErrorMsgImp(stmt, this.taos)); } } @@ -321,10 +332,20 @@ public class TSDBJNIConnector { public void executeBatch(long stmt) throws SQLException { int code = executeBatchImp(stmt, this.taos); if (code != TSDBConstants.JNI_SUCCESS) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to execute batch bind"); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, + "failed to execute batch bind, reason: " + stmtErrorMsgImp(stmt, this.taos)); + } + } + + public void addBatch(long stmt) throws SQLException { + int code = addBatchImp(stmt, this.taos); + if (code != TSDBConstants.JNI_SUCCESS){ + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, stmtErrorMsgImp(stmt, this.taos)); } } + private native int addBatchImp(long stmt, long con); + private native int executeBatchImp(long stmt, long con); public void closeBatch(long stmt) throws SQLException { @@ -336,6 +357,10 @@ public class TSDBJNIConnector { private native int closeStmt(long stmt, long con); + private native String stmtErrorMsgImp(long stmt, long con); + + /*************************************************************************************************/ + // NOTE: schemaless-lines public void insertLines(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException { int code = insertLinesImp(lines, this.taos, protocolType.ordinal(), timestampType.ordinal()); if (code != TSDBConstants.JNI_SUCCESS) { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java index 5fd8f18138..20fc2e53c5 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java @@ -40,25 +40,27 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat private String rawSql; private Object[] parameters; // for parameter binding - private long nativeStmtHandle = 0; + private long nativeStmtHandle; private String tableName; private ArrayList tableTags; private int tagValueLength; private ArrayList colData; - TSDBPreparedStatement(TSDBConnection connection, String sql) { + TSDBPreparedStatement(TSDBConnection connection, String sql) throws SQLException { super(connection); init(sql); - int parameterCnt = 0; - if (sql.contains("?")) { - for (int i = 0; i < sql.length(); i++) { - if ('?' == sql.charAt(i)) { - parameterCnt++; - } + if (!sql.contains("?")) + return; + for (int i = 0; i < sql.length(); i++) { + if ('?' == sql.charAt(i)) { + parameterCnt++; } } parameters = new Object[parameterCnt]; + // for parameter-binding +// TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); +// this.nativeStmtHandle = connector.prepareStmt(rawSql); if (parameterCnt > 1) { // the table name is also a parameter, so ignore it. @@ -530,8 +532,14 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } public void setTableName(String name) throws SQLException { + + if (this.nativeStmtHandle == 0) { + TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); + this.nativeStmtHandle = connector.prepareStmt(rawSql); + } + if (this.tableName != null) { - this.columnDataExecuteBatch(); + this.columnDataAddBatch(); this.columnDataClearBatchInternal(); } this.tableName = name; @@ -681,7 +689,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat if (rawSql == null) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "sql statement not set yet"); } - // table name is not set yet, abort if (this.tableName == null) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "table name not set yet"); @@ -691,24 +698,25 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat if (numOfCols == 0) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind"); } + if (nativeStmtHandle == 0) { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "stmt is null"); + } TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); - this.nativeStmtHandle = connector.prepareStmt(rawSql); - if (this.tableTags == null) { connector.setBindTableName(this.nativeStmtHandle, this.tableName); } else { - int num = this.tableTags.size(); + int tagSize = this.tableTags.size(); ByteBuffer tagDataList = ByteBuffer.allocate(this.tagValueLength); tagDataList.order(ByteOrder.LITTLE_ENDIAN); - ByteBuffer typeList = ByteBuffer.allocate(num); + ByteBuffer typeList = ByteBuffer.allocate(tagSize); typeList.order(ByteOrder.LITTLE_ENDIAN); - ByteBuffer lengthList = ByteBuffer.allocate(num * Long.BYTES); + ByteBuffer lengthList = ByteBuffer.allocate(tagSize * Long.BYTES); lengthList.order(ByteOrder.LITTLE_ENDIAN); - ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES); + ByteBuffer isNullList = ByteBuffer.allocate(tagSize * Integer.BYTES); isNullList.order(ByteOrder.LITTLE_ENDIAN); for (TableTagInfo tag : this.tableTags) { @@ -732,53 +740,42 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat lengthList.putLong(Byte.BYTES); break; } - case TSDBConstants.TSDB_DATA_TYPE_BOOL: { Boolean val = (Boolean) tag.value; tagDataList.put((byte) (val ? 1 : 0)); lengthList.putLong(Byte.BYTES); break; } - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { Short val = (Short) tag.value; tagDataList.putShort(val); lengthList.putLong(Short.BYTES); - break; } - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { Long val = (Long) tag.value; tagDataList.putLong(val == null ? 0 : val); lengthList.putLong(Long.BYTES); - break; } - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { Float val = (Float) tag.value; tagDataList.putFloat(val == null ? 0 : val); lengthList.putLong(Float.BYTES); - break; } - case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { Double val = (Double) tag.value; tagDataList.putDouble(val == null ? 0 : val); lengthList.putLong(Double.BYTES); - break; } - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_BINARY: { String charset = TaosGlobalConfig.getCharset(); String val = (String) tag.value; - - byte[] b = null; + byte[] b; try { if (tag.type == TSDBConstants.TSDB_DATA_TYPE_BINARY) { b = val.getBytes(); @@ -788,12 +785,10 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } catch (UnsupportedEncodingException e) { throw new RuntimeException(e.getMessage()); } - tagDataList.put(b); lengthList.putLong(b.length); break; } - case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: case TSDBConstants.TSDB_DATA_TYPE_UINT: @@ -801,13 +796,12 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types"); } } - typeList.put((byte) tag.type); isNullList.putInt(tag.isNull ? 1 : 0); } - connector.setBindTableNameAndTags(this.nativeStmtHandle, this.tableName, this.tableTags.size(), tagDataList, - typeList, lengthList, isNullList); + connector.setBindTableNameAndTags(this.nativeStmtHandle, this.tableName, this.tableTags.size(), + tagDataList, typeList, lengthList, isNullList); } ColumnInfo colInfo = this.colData.get(0); @@ -821,7 +815,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat if (col1 == null || !col1.isTypeSet()) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "column data not bind"); } - if (rows != col1.data.size()) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "the rows in column data not identical"); } @@ -938,7 +931,6 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } break; } - case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: case TSDBConstants.TSDB_DATA_TYPE_UINT: @@ -949,6 +941,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat connector.bindColumnDataArray(this.nativeStmtHandle, colDataList, lengthList, isNullList, col1.type, col1.bytes, rows, i); } + connector.addBatch(this.nativeStmtHandle); + this.columnDataClearBatchInternal(); } public void columnDataExecuteBatch() throws SQLException { @@ -963,13 +957,14 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } private void columnDataClearBatchInternal() { - int size = this.colData.size(); - this.colData.clear(); - this.colData.addAll(Collections.nCopies(size, null)); - this.tableName = null; // clear the table name + this.tableName = null; + if (this.tableTags != null) + this.tableTags.clear(); + tagValueLength = 0; + if (this.colData != null) + this.colData.clear(); } - public void columnDataCloseBatch() throws SQLException { TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); connector.closeBatch(this.nativeStmtHandle); -- GitLab