diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 64b5f8d7eed59c9bde77c0466b25da60799e384a..87cc2b854a41c917d0ab5960b002861336e90311 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -191,6 +191,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo); void tscFieldInfoCopy(SFieldInfo* pFieldInfo, const SFieldInfo* pSrc, const SArray* pExprList); static FORCE_INLINE int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQueryInfo->fieldsInfo.numOfOutput; } +int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo); int32_t tscFieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2, int32_t *diffSize); void tscInsertPrimaryTsSourceColumn(SQueryInfo* pQueryInfo, uint64_t uid); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index b129ee56785503119c56498d61f32d171e859505..d1de53ddc0eb898afabde34c3776e75976365396 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -7231,9 +7231,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo s = &pSchema[colIndex]; } } - - size_t size = tscNumOfExprs(pQueryInfo); - + if (TSDB_COL_IS_TAG(pColIndex->flag)) { int32_t f = TSDB_FUNC_TAG; @@ -7241,8 +7239,10 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo f = TSDB_FUNC_TAGPRJ; } + int32_t pos = tscGetFirstInvisibleFieldPos(pQueryInfo); + SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex}; - SExprInfo* pExpr = tscExprAppend(pQueryInfo, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true); + SExprInfo* pExpr = tscExprInsert(pQueryInfo, pos, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true); memset(pExpr->base.aliasName, 0, sizeof(pExpr->base.aliasName)); tstrncpy(pExpr->base.aliasName, s->name, sizeof(pExpr->base.aliasName)); @@ -7252,13 +7252,15 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo // NOTE: tag column does not add to source column list SColumnList ids = createColumnList(1, 0, pColIndex->colIndex); - insertResultField(pQueryInfo, (int32_t)size, &ids, s->bytes, (int8_t)s->type, s->name, pExpr); + insertResultField(pQueryInfo, pos, &ids, s->bytes, (int8_t)s->type, s->name, pExpr); } else { // if this query is "group by" normal column, time window query is not allowed if (isTimeWindowQuery(pQueryInfo)) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } + size_t size = tscNumOfExprs(pQueryInfo); + bool hasGroupColumn = false; for (int32_t j = 0; j < size; ++j) { SExprInfo* pExpr = tscExprGet(pQueryInfo, j); diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 98122cabde343665140d4035ec3d5d9e97ba6207..b8f0c345c9315a51a6b563402e42912c25e7cd70 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -2120,6 +2120,22 @@ TAOS_FIELD tscCreateField(int8_t type, const char* name, int16_t bytes) { return f; } +int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo) { + if (pQueryInfo->fieldsInfo.numOfOutput <= 0 || pQueryInfo->fieldsInfo.internalField == NULL) { + return 0; + } + + for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { + SInternalField* pField = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i); + if (!pField->visible) { + return i; + } + } + + return pQueryInfo->fieldsInfo.numOfOutput; +} + + SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { assert(pFieldInfo != NULL); pFieldInfo->numOfOutput++; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java index 12a0ab57e2c35c7f1f550dd213db19a0effd4ebc..e818736096355c4937e5af0470b77c95486c86db 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -18,7 +18,7 @@ public class RestfulConnection extends AbstractConnection { private final String url; private final String database; private final String token; - /******************************************************/ + private boolean isClosed; private final DatabaseMetaData metadata; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java index a88dc411f333fea82fa5310ee87f263b117f7e70..21c76f73b287e55ef14f5d70cf6a911a9cb543db 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java @@ -88,17 +88,24 @@ public class RestfulStatement extends AbstractStatement { } private String getUrl() throws SQLException { + String dbname = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_DBNAME); + if (dbname == null || dbname.trim().isEmpty()) { + dbname = ""; + } else { + dbname = "/" + dbname.toLowerCase(); + } TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase()); String url; + switch (timestampFormat) { case TIMESTAMP: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt" + dbname; break; case UTC: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc" + dbname; break; default: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql" + dbname; } return url; } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java new file mode 100644 index 0000000000000000000000000000000000000000..18a2c32aca0535567dd42e886bc87ae618596a40 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java @@ -0,0 +1,101 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MultiConnectionWithDifferentDbTest { + + private static String host = "127.0.0.1"; + private static String db1 = "db1"; + private static String db2 = "db2"; + + private long ts; + + @Test + public void test() { + List threads = IntStream.range(1, 3).mapToObj(i -> new Thread(new Runnable() { + @Override + public void run() { + for (int j = 0; j < 10; j++) { + queryDb(); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void queryDb() { + String url = "jdbc:TAOS-RS://" + host + ":6041/db" + i + "?user=root&password=taosdata"; + try (Connection connection = DriverManager.getConnection(url)) { + Statement stmt = connection.createStatement(); + + ResultSet rs = stmt.executeQuery("select * from weather"); + assertNotNull(rs); + rs.next(); + long actual = rs.getTimestamp("ts").getTime(); + assertEquals(ts, actual); + + int f1 = rs.getInt("f1"); + assertEquals(i, f1); + + String loc = i == 1 ? "beijing" : "shanghai"; + String loc_actual = rs.getString("loc"); + assertEquals(loc, loc_actual); + + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }, "thread-" + i)).collect(Collectors.toList()); + + threads.forEach(Thread::start); + + for (Thread t : threads) { + try { + t.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + + @Before + public void before() { + ts = System.currentTimeMillis(); + + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + db1); + stmt.execute("create database if not exists " + db1); + stmt.execute("use " + db1); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('beijing') values(" + ts + ", 1)"); + + stmt.execute("drop database if exists " + db2); + stmt.execute("create database if not exists " + db2); + stmt.execute("use " + db2); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('shanghai') values(" + ts + ", 2)"); + + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9fe51e7203fac7133783e47fd5b0cc07f33b2494 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java @@ -0,0 +1,69 @@ +package com.taosdata.jdbc.rs; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; + +import static org.junit.Assert.*; + +public class DatabaseSpecifiedTest { + + private static String host = "127.0.0.1"; + private static String dbname = "test_db_spec"; + + private Connection connection; + private long ts; + + @Test + public void test() throws SQLException { + // when + connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/" + dbname + "?user=root&password=taosdata"); + try (Statement stmt = connection.createStatement();) { + ResultSet rs = stmt.executeQuery("select * from weather"); + + //then + assertNotNull(rs); + rs.next(); + long now = rs.getTimestamp("ts").getTime(); + assertEquals(ts, now); + int f1 = rs.getInt(2); + assertEquals(1, f1); + String loc = rs.getString("loc"); + assertEquals("beijing", loc); + } + connection.close(); + } + + @Before + public void before() { + ts = System.currentTimeMillis(); + try { + Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + Statement stmt = connection.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('beijing') values( " + ts + ", 1)"); + + stmt.close(); + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @After + public void after() { + try { + if (connection != null) + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 29fa2de3ea0fe1ef910c75bd7358fc6a053af30b..f13a4c39edc8a5e7cd02ce1a8e4ecfd34fd987c7 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -7957,12 +7957,12 @@ static int insertTestProcess() { end = taosGetTimestampMs(); fprintf(stderr, - "Spent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", + "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl, g_actualChildTables); if (g_fpOfInsertResult) { fprintf(g_fpOfInsertResult, - "Spent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", + "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl, g_actualChildTables); }