Merge pull request #6520 from taosdata/feature/td-3776
[TD-3776]fix:set time precision after parsing and JNI time precision chg
This commit is contained in:
commit
d43197b9fd
|
@ -51,10 +51,10 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_taosdata_jdbc_TSDBJNIConnector
|
* Class: com_taosdata_jdbc_TSDBJNIConnector
|
||||||
* Method: getResultTimePrecision
|
* Method: getResultTimePrecisionImp
|
||||||
* Signature: (J)J
|
* Signature: (JJ)I
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecision
|
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecisionImp
|
||||||
(JNIEnv *, jobject, jlong, jlong);
|
(JNIEnv *, jobject, jlong, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -113,7 +113,7 @@ static void jniGetGlobalMethod(JNIEnv *env) {
|
||||||
g_rowdataSetFloatFp = (*env)->GetMethodID(env, g_rowdataClass, "setFloat", "(IF)V");
|
g_rowdataSetFloatFp = (*env)->GetMethodID(env, g_rowdataClass, "setFloat", "(IF)V");
|
||||||
g_rowdataSetDoubleFp = (*env)->GetMethodID(env, g_rowdataClass, "setDouble", "(ID)V");
|
g_rowdataSetDoubleFp = (*env)->GetMethodID(env, g_rowdataClass, "setDouble", "(ID)V");
|
||||||
g_rowdataSetStringFp = (*env)->GetMethodID(env, g_rowdataClass, "setString", "(ILjava/lang/String;)V");
|
g_rowdataSetStringFp = (*env)->GetMethodID(env, g_rowdataClass, "setString", "(ILjava/lang/String;)V");
|
||||||
g_rowdataSetTimestampFp = (*env)->GetMethodID(env, g_rowdataClass, "setTimestamp", "(IJ)V");
|
g_rowdataSetTimestampFp = (*env)->GetMethodID(env, g_rowdataClass, "setTimestamp", "(IJI)V");
|
||||||
g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V");
|
g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V");
|
||||||
(*env)->DeleteLocalRef(env, rowdataClass);
|
(*env)->DeleteLocalRef(env, rowdataClass);
|
||||||
|
|
||||||
|
@ -519,9 +519,11 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
||||||
jniFromNCharToByteArray(env, (char *)row[i], length[i]));
|
jniFromNCharToByteArray(env, (char *)row[i], length[i]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetTimestampFp, i, (jlong) * ((int64_t *)row[i]));
|
int precision = taos_result_precision(result);
|
||||||
|
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetTimestampFp, i, (jlong) * ((int64_t *)row[i]), precision);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -672,7 +674,15 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(J
|
||||||
return (*env)->NewStringUTF(env, (const char *)tsCharset);
|
return (*env)->NewStringUTF(env, (const char *)tsCharset);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecision(JNIEnv *env, jobject jobj, jlong con,
|
/**
|
||||||
|
* Get Result Time Precision
|
||||||
|
* @param env vm
|
||||||
|
* @param jobj the TSDBJNIConnector java object
|
||||||
|
* @param con the c connection pointer
|
||||||
|
* @param res the TAOS_RES object, i.e. the SSqlObject
|
||||||
|
* @return precision 0:ms 1:us 2:ns
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultTimePrecisionImp(JNIEnv *env, jobject jobj, jlong con,
|
||||||
jlong res) {
|
jlong res) {
|
||||||
TAOS *tscon = (TAOS *)con;
|
TAOS *tscon = (TAOS *)con;
|
||||||
if (tscon == NULL) {
|
if (tscon == NULL) {
|
||||||
|
|
|
@ -772,6 +772,10 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||||
pCmd->active = pCmd->pQueryInfo;
|
pCmd->active = pCmd->pQueryInfo;
|
||||||
pCmd->command = pCmd->pQueryInfo->command;
|
pCmd->command = pCmd->pQueryInfo->command;
|
||||||
|
|
||||||
|
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||||
|
pSql->res.precision = tscGetTableInfo(pTableMetaInfo->pTableMeta).precision;
|
||||||
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS; // do not build query message here
|
return TSDB_CODE_SUCCESS; // do not build query message here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,16 @@ public class TSDBJNIConnector {
|
||||||
|
|
||||||
private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData);
|
private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Result Time Precision.
|
||||||
|
* @return 0: ms, 1: us, 2: ns
|
||||||
|
*/
|
||||||
|
public int getResultTimePrecision(long sqlObj) {
|
||||||
|
return this.getResultTimePrecisionImp(this.taos, sqlObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private native int getResultTimePrecisionImp(long connection, long result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute close operation from C to release connection pointer by JNI
|
* Execute close operation from C to release connection pointer by JNI
|
||||||
*
|
*
|
||||||
|
|
|
@ -414,26 +414,40 @@ public class TSDBResultSetRowData {
|
||||||
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api
|
* $$$ this method is invoked by databaseMetaDataResultSet and so on which use a index start from 1 in JDBC api
|
||||||
*/
|
*/
|
||||||
public void setTimestampValue(int colIndex, long value) {
|
public void setTimestampValue(int colIndex, long value) {
|
||||||
setTimestamp(colIndex - 1, value);
|
setTimestamp(colIndex - 1, value, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* !!! this method is invoked by JNI method and the index start from 0 in C implementations
|
* !!! this method is invoked by JNI method and the index start from 0 in C implementations
|
||||||
|
* @param precision 0 : ms, 1 : us, 2 : ns
|
||||||
*/
|
*/
|
||||||
public void setTimestamp(int col, long ts) {
|
public void setTimestamp(int col, long ts, int precision) {
|
||||||
//TODO: this implementation contains logical error
|
long milliseconds = 0;
|
||||||
// when precision is us the (long ts) is 16 digital number
|
int fracNanoseconds = 0;
|
||||||
// when precision is ms, the (long ts) is 13 digital number
|
switch (precision) {
|
||||||
// we need a JNI function like this:
|
case 0: {
|
||||||
// public void setTimestamp(int col, long epochSecond, long nanoAdjustment)
|
milliseconds = ts;
|
||||||
if (ts < 1_0000_0000_0000_0L) {
|
fracNanoseconds = (int)(ts*1_000_000%1_000_000_000);
|
||||||
data.set(col, new Timestamp(ts));
|
break;
|
||||||
} else {
|
}
|
||||||
long epochSec = ts / 1000_000l;
|
case 1: {
|
||||||
long nanoAdjustment = ts % 1000_000l * 1000l;
|
milliseconds = ts/1_000;
|
||||||
Timestamp timestamp = Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
fracNanoseconds = (int)(ts*1_000%1_000_000_000);
|
||||||
data.set(col, timestamp);
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
milliseconds = ts/1_000_000;
|
||||||
|
fracNanoseconds = (int)(ts%1_000_000_000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new IllegalArgumentException("precision is not valid. precision: " + precision);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timestamp tsObj = new Timestamp(milliseconds);
|
||||||
|
tsObj.setNanos(fracNanoseconds);
|
||||||
|
data.set(col, tsObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Timestamp getTimestamp(int col, int nativeType) {
|
public Timestamp getTimestamp(int col, int nativeType) {
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package com.taosdata.jdbc;
|
package com.taosdata.jdbc;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.SQLWarning;
|
import java.sql.SQLWarning;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.RuntimeMXBean;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
|
|
||||||
public class TSDBJNIConnectorTest {
|
public class TSDBJNIConnectorTest {
|
||||||
|
|
||||||
private static TSDBResultSetRowData rowData;
|
private static TSDBResultSetRowData rowData;
|
||||||
|
@ -14,17 +19,68 @@ public class TSDBJNIConnectorTest {
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
try {
|
||||||
|
//change sleepSeconds when debugging with attach to process to find PID
|
||||||
|
int sleepSeconds = -1;
|
||||||
|
if (sleepSeconds>0) {
|
||||||
|
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||||
|
String jvmName = runtimeBean.getName();
|
||||||
|
long pid = Long.valueOf(jvmName.split("@")[0]);
|
||||||
|
System.out.println("JVM PID = " + pid);
|
||||||
|
|
||||||
|
Thread.sleep(sleepSeconds*1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
TSDBJNIConnector.init("/etc/taos/taos.cfg", null, null, null);
|
TSDBJNIConnector.init("/etc/taos", null, null, null);
|
||||||
|
|
||||||
// connect
|
// connect
|
||||||
TSDBJNIConnector connector = new TSDBJNIConnector();
|
TSDBJNIConnector connector = new TSDBJNIConnector();
|
||||||
connector.connect("127.0.0.1", 6030, "unsign_jni", "root", "taosdata");
|
connector.connect("127.0.0.1", 6030, null, "root", "taosdata");
|
||||||
|
|
||||||
|
// setup
|
||||||
|
String setupSqlStrs[] = {"create database if not exists d precision \"us\"",
|
||||||
|
"create table if not exists d.t(ts timestamp, f int)",
|
||||||
|
"create database if not exists d2",
|
||||||
|
"create table if not exists d2.t2(ts timestamp, f int)",
|
||||||
|
"insert into d.t values(now+100s, 100)",
|
||||||
|
"insert into d2.t2 values(now+200s, 200)"
|
||||||
|
};
|
||||||
|
for (String setupSqlStr : setupSqlStrs) {
|
||||||
|
long setupSql = connector.executeQuery(setupSqlStr);
|
||||||
|
|
||||||
|
assertEquals(0, connector.getResultTimePrecision(setupSql));
|
||||||
|
if (connector.isUpdateQuery(setupSql)) {
|
||||||
|
connector.freeResultSet(setupSql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
long sqlObj1 = connector.executeQuery("select * from d2.t2");
|
||||||
|
assertEquals(0, connector.getResultTimePrecision(sqlObj1));
|
||||||
|
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
|
||||||
|
int code = connector.getSchemaMetaData(sqlObj1, columnMetaDataList);
|
||||||
|
rowData = new TSDBResultSetRowData(columnMetaDataList.size());
|
||||||
|
assertTrue(next(connector, sqlObj1));
|
||||||
|
assertEquals(0, connector.getResultTimePrecision(sqlObj1));
|
||||||
|
connector.freeResultSet(sqlObj1);
|
||||||
|
}
|
||||||
|
|
||||||
// executeQuery
|
// executeQuery
|
||||||
long pSql = connector.executeQuery("select * from unsign_jni.us_table");
|
long pSql = connector.executeQuery("select * from d.t");
|
||||||
|
|
||||||
if (connector.isUpdateQuery(pSql)) {
|
if (connector.isUpdateQuery(pSql)) {
|
||||||
connector.freeResultSet(pSql);
|
connector.freeResultSet(pSql);
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_WITH_EXECUTEQUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertEquals(1, connector.getResultTimePrecision(pSql));
|
||||||
|
|
||||||
// get schema
|
// get schema
|
||||||
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
|
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
|
||||||
int code = connector.getSchemaMetaData(pSql, columnMetaDataList);
|
int code = connector.getSchemaMetaData(pSql, columnMetaDataList);
|
||||||
|
@ -37,6 +93,8 @@ public class TSDBJNIConnectorTest {
|
||||||
if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
|
if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) {
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertEquals(1, connector.getResultTimePrecision(pSql));
|
||||||
int columnSize = columnMetaDataList.size();
|
int columnSize = columnMetaDataList.size();
|
||||||
// print metadata
|
// print metadata
|
||||||
for (int i = 0; i < columnSize; i++) {
|
for (int i = 0; i < columnSize; i++) {
|
||||||
|
@ -45,9 +103,8 @@ public class TSDBJNIConnectorTest {
|
||||||
rowData = new TSDBResultSetRowData(columnSize);
|
rowData = new TSDBResultSetRowData(columnSize);
|
||||||
// iterate resultSet
|
// iterate resultSet
|
||||||
for (int i = 0; next(connector, pSql); i++) {
|
for (int i = 0; next(connector, pSql); i++) {
|
||||||
// System.out.println("col[" + i + "] size: " + rowData.getColSize());
|
assertEquals(1, connector.getResultTimePrecision(pSql));
|
||||||
// rowData.getData().stream().forEach(col -> System.out.print(col + "\t"));
|
System.out.println();
|
||||||
// System.out.println();
|
|
||||||
}
|
}
|
||||||
// close resultSet
|
// close resultSet
|
||||||
code = connector.freeResultSet(pSql);
|
code = connector.freeResultSet(pSql);
|
||||||
|
@ -86,4 +143,4 @@ public class TSDBJNIConnectorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue