diff --git a/src/connector/C#/src/test/Cases/Utils.cs b/src/connector/C#/src/test/Cases/Utils.cs index 1c2ab137930384c0a85ae2103ff6be0893d7733b..5a2962564fb9063e8994e549f0135cedb36b6ec5 100644 --- a/src/connector/C#/src/test/Cases/Utils.cs +++ b/src/connector/C#/src/test/Cases/Utils.cs @@ -3,7 +3,6 @@ using TDengineDriver; using System.Runtime.InteropServices; using System.Text; using System.Collections.Generic; - namespace Test.UtilsTools { public class UtilsTools diff --git a/src/connector/nodejs/nodetaos/cinterface.js b/src/connector/nodejs/nodetaos/cinterface.js index fa0eb20055df38c2a8092637e30ae807e473fa30..2403ffa4c68ca9571f2ec583fa263765208bfb2b 100644 --- a/src/connector/nodejs/nodetaos/cinterface.js +++ b/src/connector/nodejs/nodetaos/cinterface.js @@ -14,7 +14,12 @@ const _ = require('lodash') const TaosObjects = require('./taosobjects'); module.exports = CTaosInterface; - +const TAOSFIELD = { + NAME_LENGTH: 65, + TYPE_OFFSET: 65, + BYTES_OFFSET: 66, + STRUCT_SIZE: 68, +} function convertTimestamp(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); let res = []; @@ -195,6 +200,24 @@ function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) return res; } +function convertJsonTag(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { + data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); + let res = []; + + let currOffset = 0; + while (currOffset < data.length) { + let len = data.readIntLE(currOffset, 2); + let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column; + if (dataEntry[0] == 255 && dataEntry[1] == 255) { + res.push(null) + } else { + res.push(dataEntry.toString("utf-8")); + } + currOffset += nbytes; + } + return res; +} + // Object with all the relevant converters from pblock data to javascript readable data let convertFunctions = { [FieldTypes.C_BOOL]: convertBool, @@ -210,7 +233,8 @@ let convertFunctions = { [FieldTypes.C_TINYINT_UNSIGNED]: convertTinyintUnsigned, [FieldTypes.C_SMALLINT_UNSIGNED]: convertSmallintUnsigned, [FieldTypes.C_INT_UNSIGNED]: convertIntUnsigned, - [FieldTypes.C_BIGINT_UNSIGNED]: convertBigintUnsigned + [FieldTypes.C_BIGINT_UNSIGNED]: convertBigintUnsigned, + [FieldTypes.C_JSON_TAG]: convertJsonTag, } // Define TaosField structure @@ -219,8 +243,8 @@ var TaosField = Struct({ 'name': char_arr, }); TaosField.fields.name.type.size = 65; -TaosField.defineProperty('type', ref.types.char); -TaosField.defineProperty('bytes', ref.types.short); +TaosField.defineProperty('type', ref.types.uint8); +TaosField.defineProperty('bytes', ref.types.int16); //define schemaless line array var smlLine = ArrayType(ref.coerceType('char *')) @@ -390,14 +414,14 @@ CTaosInterface.prototype.useResult = function useResult(result) { let fields = []; let pfields = this.fetchFields(result); + if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, this.fieldsCount(result) * 68, 0); - for (let i = 0; i < pfields.length; i += 68) { - //0 - 63 = name //64 - 65 = bytes, 66 - 67 = type + pfields = ref.reinterpret(pfields, this.fieldsCount(result) * TAOSFIELD.STRUCT_SIZE, 0); + for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { fields.push({ - name: ref.readCString(ref.reinterpret(pfields, 65, i)), - type: pfields[i + 65], - bytes: pfields[i + 66] + name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), + type: pfields[i + TAOSFIELD.TYPE_OFFSET], + bytes: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 }) } } @@ -532,13 +556,12 @@ CTaosInterface.prototype.fetchFields_a = function fetchFields_a(result) { let pfieldscount = this.numFields(result); let fields = []; if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, 68 * pfieldscount, 0); - for (let i = 0; i < pfields.length; i += 68) { - //0 - 64 = name //65 = type, 66 - 67 = bytes + pfields = ref.reinterpret(pfields, pfieldscount * TAOSFIELD.STRUCT_SIZE, 0); + for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { fields.push({ - name: ref.readCString(ref.reinterpret(pfields, 65, i)), - type: pfields[i + 65], - bytes: pfields[i + 66] + name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), + type: pfields[i + TAOSFIELD.TYPE_OFFSET], + bytes: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 }) } } @@ -594,13 +617,12 @@ CTaosInterface.prototype.consume = function consume(subscription) { let fields = []; let pfields = this.fetchFields(result); if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, this.numFields(result) * 68, 0); - for (let i = 0; i < pfields.length; i += 68) { - //0 - 63 = name //64 - 65 = bytes, 66 - 67 = type + pfields = ref.reinterpret(pfields, this.numFields(result) * TAOSFIELD.STRUCT_SIZE, 0); + for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { fields.push({ - name: ref.readCString(ref.reinterpret(pfields, 64, i)), - bytes: pfields[i + 64], - type: pfields[i + 66] + name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), + bytes: pfields[TAOSFIELD.TYPE_OFFSET], + type: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 }) } } @@ -684,23 +706,23 @@ CTaosInterface.prototype.closeStream = function closeStream(stream) { * @returns TAOS_RES * */ -CTaosInterface.prototype.schemalessInsert = function schemalessInsert(connection,lines, protocal, precision) { +CTaosInterface.prototype.schemalessInsert = function schemalessInsert(connection, lines, protocal, precision) { let _numLines = null; let _lines = null; - - if(_.isString(lines)){ + + if (_.isString(lines)) { _numLines = 1; _lines = Buffer.alloc(_numLines * ref.sizeof.pointer); - ref.set(_lines,0,ref.allocCString(lines),ref.types.char_ptr); + ref.set(_lines, 0, ref.allocCString(lines), ref.types.char_ptr); } - else if(_.isArray(lines)){ + else if (_.isArray(lines)) { _numLines = lines.length; _lines = Buffer.alloc(_numLines * ref.sizeof.pointer); - for(let i = 0; i < _numLines ; i++){ - ref.set(_lines,i*ref.sizeof.pointer,ref.allocCString(lines[i]),ref.types.char_ptr) + for (let i = 0; i < _numLines; i++) { + ref.set(_lines, i * ref.sizeof.pointer, ref.allocCString(lines[i]), ref.types.char_ptr) } } - else{ + else { throw new errors.InterfaceError("Unsupport lines input") } return this.libtaos.taos_schemaless_insert(connection, _lines, _numLines, protocal, precision); diff --git a/src/connector/nodejs/nodetaos/constants.js b/src/connector/nodejs/nodetaos/constants.js index 551cfce71677fbd6635a76884474e1b1aeac7ab9..b055e0ed01522348556475fa72e8bf34a9d3fe70 100644 --- a/src/connector/nodejs/nodetaos/constants.js +++ b/src/connector/nodejs/nodetaos/constants.js @@ -6,13 +6,13 @@ const SCHEMALESS_PROTOCOL = { TSDB_SML_JSON_PROTOCOL: 3 } const SCHEMALESS_PRECISION = { - TSDB_SML_TIMESTAMP_NOT_CONFIGURED : 0, - TSDB_SML_TIMESTAMP_HOURS : 1, - TSDB_SML_TIMESTAMP_MINUTES : 2, - TSDB_SML_TIMESTAMP_SECONDS : 3, - TSDB_SML_TIMESTAMP_MILLI_SECONDS : 4, - TSDB_SML_TIMESTAMP_MICRO_SECONDS : 5, - TSDB_SML_TIMESTAMP_NANO_SECONDS : 6 + TSDB_SML_TIMESTAMP_NOT_CONFIGURED: 0, + TSDB_SML_TIMESTAMP_HOURS: 1, + TSDB_SML_TIMESTAMP_MINUTES: 2, + TSDB_SML_TIMESTAMP_SECONDS: 3, + TSDB_SML_TIMESTAMP_MILLI_SECONDS: 4, + TSDB_SML_TIMESTAMP_MICRO_SECONDS: 5, + TSDB_SML_TIMESTAMP_NANO_SECONDS: 6 } const typeCodesToName = { 0: 'Null', @@ -30,6 +30,7 @@ const typeCodesToName = { 12: 'Smallint Unsigned', 13: 'Int Unsigned', 14: 'Bigint Unsigned', + 15: 'Json', } /** @@ -80,6 +81,7 @@ module.exports = { C_SMALLINT_UNSIGNED: 12, C_INT_UNSIGNED: 13, C_BIGINT_UNSIGNED: 14, + C_JSON_TAG: 15, // NULL value definition // NOTE: These values should change according to C definition in tsdb.h C_BOOL_NULL: 2, diff --git a/src/connector/nodejs/nodetaos/taosresult.js b/src/connector/nodejs/nodetaos/taosresult.js index 4138ebbec6e1b792691d17a25b7c18d35b6a922a..1ea5abee9f6c3c2754081ad82ecdb51c3b5bd4d3 100644 --- a/src/connector/nodejs/nodetaos/taosresult.js +++ b/src/connector/nodejs/nodetaos/taosresult.js @@ -29,19 +29,19 @@ function TaosResult(data, fields) { TaosResult.prototype.pretty = function pretty() { let fieldsStr = ""; let sizing = []; - this.fields.forEach((field,i) => { - if (field._field.type == 8 || field._field.type == 10){ + this.fields.forEach((field, i) => { + if (field._field.type == 8 || field._field.type == 10 ) { sizing.push(Math.max(field.name.length, field._field.bytes)); } else { sizing.push(Math.max(field.name.length, suggestedMinWidths[field._field.type])); } - fieldsStr += fillEmpty(Math.floor(sizing[i]/2 - field.name.length / 2)) + field.name + fillEmpty(Math.ceil(sizing[i]/2 - field.name.length / 2)) + " | "; + fieldsStr += fillEmpty(Math.floor(sizing[i] / 2 - field.name.length / 2)) + field.name + fillEmpty(Math.ceil(sizing[i] / 2 - field.name.length / 2)) + " | "; }); - var sumLengths = sizing.reduce((a,b)=> a+=b,(0)) + sizing.length * 3; + var sumLengths = sizing.reduce((a, b) => a += b, (0)) + sizing.length * 3; console.log("\n" + fieldsStr); - console.log(printN("=",sumLengths)); + console.log(printN("=", sumLengths)); this.data.forEach(row => { let rowStr = ""; row.data.forEach((entry, i) => { @@ -62,16 +62,21 @@ const suggestedMinWidths = { 2: 4, 3: 6, 4: 11, - 5: 12, + 5: 20, 6: 24, 7: 24, 8: 10, 9: 25, 10: 10, + 11: 4, + 12: 6, + 13: 11, + 14: 20, + 15: 20, } function printN(s, n) { let f = ""; - for (let i = 0; i < n; i ++) { + for (let i = 0; i < n; i++) { f += s; } return f; diff --git a/src/connector/nodejs/package.json b/src/connector/nodejs/package.json index d7eba48a463643dd293960251f6eebcb253d93c4..3d8dfc7e0135d8d5e8ba0eacf110d527f9e3f7bf 100644 --- a/src/connector/nodejs/package.json +++ b/src/connector/nodejs/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": "node test/test.js && node test/testMicroseconds.js && node test/testNanoseconds.js && node test/testUnsignedType.js && node test/testSchemalessInsert.js " + "test": "node test/test.js && node test/testMicroseconds.js && node test/testNanoseconds.js && node test/testUnsignedType.js && node test/testSchemalessInsert.js && node test/testJsonTag.js" }, "repository": { "type": "git", diff --git a/src/connector/nodejs/test/testJsonTag.js b/src/connector/nodejs/test/testJsonTag.js new file mode 100644 index 0000000000000000000000000000000000000000..a922afb8e6b6614b208a6ba7cd82a8d00f983282 --- /dev/null +++ b/src/connector/nodejs/test/testJsonTag.js @@ -0,0 +1,280 @@ +const taos = require('../tdengine'); +var conn = taos.connect({ host: "127.0.0.1", user: "root", password: "taosdata", config: "/etc/taos", port: 10 }); +var c1 = conn.cursor(); + +function executeUpdate(sql) { + console.log(sql); + c1.execute(sql); +} +function executeQuery(sql, flag = "all") { + console.log(sql); + c1.execute(sql) + var data = c1.fetchall(); + if (flag == "metadata" || flag == "all") { + // Latest query's Field metadata is stored in cursor.fields + console.log(c1.fields); + } 2 + if (flag == "data" || flag == "all") { + // Latest query's result data is stored in cursor.data, also returned by fetchall. + console.log(c1.data); + } + console.log(""); +} + +function prettyQuery(sql) { + try { + c1.query(sql).execute().then(function (result) { + result.pretty(); + }); + } + catch (err) { + conn.close(); + throw err; + } +} + +function executeError(sql) { + console.log(sql); + try { + c1.execute(sql) + } catch (e) { + console.log(e.message); + console.log(""); + } +} + +executeUpdate("create database if not exists nodedb keep 36500;"); +executeUpdate("use nodedb;"); +console.log("# STEP 1 prepare data & validate json string"); +executeUpdate("create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json);"); +executeUpdate("insert into jsons1_1 using jsons1 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 1, false, 'json1', '涛思数据') (1591060608000, 23, true, '涛思数据', 'json')"); +executeUpdate("insert into jsons1_2 using jsons1 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060628000, 2, true, 'json2', 'sss')"); +executeUpdate("insert into jsons1_3 using jsons1 tags('{\"tag1\":false,\"tag2\":\"beijing\"}') values (1591060668000, 3, false, 'json3', 'efwe')"); +executeUpdate("insert into jsons1_4 using jsons1 tags('{\"tag1\":null,\"tag2\":\"shanghai\",\"tag3\":\"hello\"}') values (1591060728000, 4, true, 'json4', '323sd')"); +executeUpdate("insert into jsons1_5 using jsons1 tags('{\"tag1\":1.232, \"tag2\":null}') values(1591060928000, 1, false, '涛思数据', 'ewe')"); +executeUpdate("insert into jsons1_6 using jsons1 tags('{\"tag1\":11,\"tag2\":\"\",\"tag2\":null}') values(1591061628000, 11, false, '涛思数据','')"); +executeUpdate("insert into jsons1_7 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')"); + +console.log("## test duplicate key using the first one. elimate empty key"); +executeUpdate("CREATE TABLE if not exists jsons1_8 using jsons1 tags('{\"tag1\":null, \"tag1\":true, \"tag1\":45, \"1tag$\":2, \" \":90}')"); + +console.log("## test empty json string, save as jtag is NULL"); +executeUpdate("insert into jsons1_9 using jsons1 tags('\t') values (1591062328000, 24, NULL, '涛思数据', '2sdw')"); +executeUpdate("CREATE TABLE if not exists jsons1_10 using jsons1 tags('')"); +executeUpdate("CREATE TABLE if not exists jsons1_11 using jsons1 tags(' ')"); +executeUpdate("CREATE TABLE if not exists jsons1_12 using jsons1 tags('{}')"); +executeUpdate("CREATE TABLE if not exists jsons1_13 using jsons1 tags('null')"); + +console.log("## test invalidate json"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('\"efwewf\"')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('3333')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('33.33')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('false')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('[1,true]')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{222}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"fe\"}')"); +executeQuery("select * from jsons1;", "data"); + +console.log("## test invalidate json key, key must can be printed assic char="); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":[1,true]}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":{}}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"。loc\":\"fff\"}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\":\"fff\"}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\t\":\"fff\"}')"); +executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"涛思数据\":\"fff\"}')"); + +console.log("# STEP 2 alter table json tag"); +executeError("ALTER STABLE jsons1 add tag tag2 nchar(20)"); +executeError("ALTER STABLE jsons1 drop tag jtag"); +executeError("ALTER TABLE jsons1_1 SET TAG jtag=4"); +executeUpdate("ALTER TABLE jsons1_1 SET TAG jtag='{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}'") + +console.log("# STEP 3 query table"); +console.log("## test error syntax"); +executeError("select * from jsons1 where jtag->tag1='beijing'"); +executeError("select * from jsons1 where jtag->'location'"); +executeError("select * from jsons1 where jtag->''"); +executeError("select * from jsons1 where jtag->''=9"); +executeError("select -> from jsons1"); +executeError("select * from jsons1 where contains"); +executeError("select * from jsons1 where jtag->"); +executeError("select jtag->location from jsons1"); +executeError("select jtag contains location from jsons1"); +executeError("select * from jsons1 where jtag contains location"); +executeError("select * from jsons1 where jtag contains''"); +executeError("select * from jsons1 where jtag contains 'location'='beijing'"); + +console.log("## test select normal column"); +executeQuery("select dataint from jsons1"); + +console.log("## test select json tag"); +executeQuery("select * from jsons1", "data") +executeQuery("select jtag from jsons1", "data"); +executeQuery("select jtag from jsons1 where jtag is null", "data"); +executeQuery("select jtag from jsons1 where jtag is not null", "data"); +executeQuery("select jtag from jsons1_8", "data"); +executeQuery("select jtag from jsons1_1", "data"); + +console.log("## test jtag is NULL"); +executeQuery("select jtag from jsons1_9", "data"); + +console.log("## test select json tag->'key', value is string"); +executeQuery("select jtag->'tag1' from jsons1_1", "data"); +executeQuery("select jtag->'tag2' from jsons1_6", "data"); + +console.log("### test select json tag->'key', value is int"); +executeQuery("select jtag->'tag2' from jsons1_1", "data"); + +console.log("### test select json tag->'key', value is bool"); +executeQuery("select jtag->'tag3' from jsons1_1", "data"); + +console.log("### test select json tag->'key', value is null"); +executeQuery("select jtag->'tag1' from jsons1_4", "data"); + +console.log("### test select json tag->'key', value is double"); +executeQuery("select jtag->'tag1' from jsons1_5", "data"); + +console.log("### test select json tag->'key', key is not exist"); +executeQuery("select jtag->'tag10' from jsons1_4", "data"); +executeQuery("select jtag->'tag1' from jsons1", "data"); + +console.log("### test header name"); +executeQuery("select jtag->'tag1' from jsons1", "metadata"); + +console.log("## test where with json tag"); +executeError("select * from jsons1_1 where jtag is not null"); +executeError("select * from jsons1 where jtag='{\"tag1\":11,\"tag2\":\"\"}'"); +executeError("select * from jsons1 where jtag->'tag1'={}"); + +console.log("### where json value is string"); +executeQuery("select * from jsons1 where jtag->'tag2'='beijing'", "data"); +executeQuery("select dataint,tbname,jtag->'tag1',jtag from jsons1 where jtag->'tag2'='beijing'"); +executeQuery("select * from jsons1 where jtag->'tag1'='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'='涛思数据'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'>'beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'>='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'<'beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'<='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'!='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2'=''", "data"); + +console.log("### where json value is int"); +executeQuery("select * from jsons1 where jtag->'tag1'=5", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=10", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'<54", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'<=11", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'>4", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'>=5", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'!=5", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'!=55", "data"); + +console.log("### where json value is double"); +executeQuery("select * from jsons1 where jtag->'tag1'=1.232", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'<1.232", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'<=1.232", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'>1.23", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'>=1.232", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'!=1.232", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'!=3.232", "data"); +executeError("select * from jsons1 where jtag->'tag1'/0=3", "data"); +executeError("select * from jsons1 where jtag->'tag1'/5=1", "data"); + +console.log("### where json value is bool"); +executeQuery("select * from jsons1 where jtag->'tag1'=true", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=false", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'!=false", "data"); +executeError("select * from jsons1 where jtag->'tag1'>false"); + +console.log("### where json value is null"); +executeQuery("select * from jsons1 where jtag->'tag1'=null"); //only json suport =null. This synatx will change later. + +console.log("### where json is null"); +executeQuery("select * from jsons1 where jtag is null", "data"); +executeQuery("select * from jsons1 where jtag is not null", "data"); + +console.log("### where json key is null"); +executeQuery("select * from jsons1 where jtag->'tag_no_exist'=3", "data") + +console.log("### where json value is not exist"); +executeQuery("select * from jsons1 where jtag->'tag1' is null", "data"); +executeQuery("select * from jsons1 where jtag->'tag4' is null", "data"); +executeQuery("select * from jsons1 where jtag->'tag3' is not null", "data") + +console.log("### test contains"); +executeQuery("select * from jsons1 where jtag contains 'tag1'", "data") +executeQuery("select * from jsons1 where jtag contains 'tag3'", "data") +executeQuery("select * from jsons1 where jtag contains 'tag_no_exist'", "data") + +console.log("### test json tag in where condition with and/or"); +executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=false or jtag->'tag2'='beijing'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35", "data"); +executeQuery("select * from jsons1 where jtag->'tag1' is not null and jtag contains 'tag3'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1'='femail' and jtag contains 'tag3'", "data"); + +console.log("### test with tbname/normal column"); +executeQuery("select * from jsons1 where tbname = 'jsons1_1'", "data") +executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3'", "data") +executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=3", "data") +executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=23", "data") + +console.log("### test where condition like"); +executeQuery("select *,tbname from jsons1 where jtag->'tag2' like 'bei%'", "data"); +executeQuery("select *,tbname from jsons1 where jtag->'tag1' like 'fe%' and jtag->'tag2' is not null", "data"); + +console.log("### test where condition in no support in"); +executeError("select * from jsons1 where jtag->'tag1' in ('beijing')"); + +console.log("### test where condition match"); +executeQuery("select * from jsons1 where jtag->'tag1' match 'ma'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1' match 'ma$'", "data"); +executeQuery("select * from jsons1 where jtag->'tag2' match 'jing$'", "data"); +executeQuery("select * from jsons1 where jtag->'tag1' match '收到'", "data"); + +console.log("### test distinct"); +executeUpdate("insert into jsons1_14 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')", "data"); +executeQuery("select distinct jtag->'tag1' from jsons1", "data"); +executeQuery("select distinct jtag from jsons1", "data"); + +console.log("### test dumplicate key with normal colomn"); +executeUpdate("INSERT INTO jsons1_15 using jsons1 tags('{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"涛思数据\"}') values(1591060828000, 4, false, 'jjsf', \"涛思数据\")"); +executeQuery("select *,tbname,jtag from jsons1 where jtag->'datastr' match '涛思' and datastr match 'js'", "data"); +executeQuery("select tbname,jtag->'tbname' from jsons1 where jtag->'tbname'='tt' and tbname='jsons1_14'", "data"); + +console.log("## test join"); +executeUpdate("create table if not exists jsons2(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)") +executeUpdate("insert into jsons2_1 using jsons2 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 2, false, 'json2', '你是2')") +executeUpdate("insert into jsons2_2 using jsons2 tags('{\"tag1\":5,\"tag2\":null}') values (1591060628000, 2, true, 'json2', 'sss')") +executeUpdate("create table if not exists jsons3(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)") +executeUpdate("insert into jsons3_1 using jsons3 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 3, false, 'json3', '你是3')") +executeUpdate("insert into jsons3_2 using jsons3 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060638000, 2, true, 'json3', 'sss')") + +executeQuery("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'", "data"); +executeQuery("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'", "metadata"); + +console.log("## test group by & order by json tag"); + +executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' desc", "data"); +executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' asc", "data"); + +console.log("## test stddev with group by json tag"); +executeQuery("select stddev(dataint) from jsons1 group by jtag->'tag1'", "data"); +executeQuery("select stddev(dataint) from jsons1 group by jsons1.jtag->'tag1'", "metadata"); + +console.log("## test top/bottom with group by json tag"); +executeQuery("select top(dataint,100) from jsons1 group by jtag->'tag1'", "metadata"); + +console.log("## subquery with json tag"); +executeQuery("select * from (select jtag, dataint from jsons1)", "metadata"); +executeQuery("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)", "metadata"); +executeQuery("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)", "metada"); +executeQuery("select ts,tbname,jtag->'tag1' from (select jtag->'tag1',tbname,ts from jsons1 order by ts)", "data") + + +executeUpdate("drop database nodedb;"); + + +setTimeout(() => conn.close(), 2000); diff --git a/src/connector/nodejs/test/testUnsignedType.js b/src/connector/nodejs/test/testUnsignedType.js index 14b102972a898c582e0011698bfd7b3cd771bc42..3f0b0c20459959fe7ea863757220ea77fe377694 100644 --- a/src/connector/nodejs/test/testUnsignedType.js +++ b/src/connector/nodejs/test/testUnsignedType.js @@ -1,14 +1,6 @@ const taos = require('../tdengine'); var conn = taos.connect({ host: "127.0.0.1", user: "root", password: "taosdata", config: "/etc/taos", port: 10 }); var c1 = conn.cursor(); -executeUpdate("create database if not exists nodedb;"); -executeUpdate("use nodedb;"); -executeUpdate("create table if not exists unsigntest(ts timestamp,ut tinyint unsigned,us smallint unsigned,ui int unsigned,ub bigint unsigned,bi bigint);"); -executeUpdate("insert into unsigntest values (now, 254,65534,4294967294,18446744073709551614,9223372036854775807);"); -executeUpdate("insert into unsigntest values (now, 0,0,0,0,-9223372036854775807);"); -executeQuery("select * from unsigntest;"); -executeUpdate("drop database if exists nodedb;"); - function executeUpdate(sql) { console.log(sql); c1.execute(sql); @@ -21,5 +13,28 @@ function executeQuery(sql) { // Latest query's result data is stored in cursor.data, also returned by fetchall. console.log(c1.data); } + +function prettyQuery(sql){ + try { + c1.query(sql).execute().then(function(result){ + result.pretty(); + }); + } + catch (err) { + conn.close(); + throw err; + } +} + +executeUpdate("create database nodedb;"); +executeUpdate("use nodedb;"); +executeUpdate("create table unsigntest(ts timestamp,ut tinyint unsigned,us smallint unsigned,ui int unsigned,ub bigint unsigned,bi bigint);"); +executeUpdate("insert into unsigntest values (now, 254,65534,4294967294,18446744073709551614,9223372036854775807);"); +executeUpdate("insert into unsigntest values (now, 0,0,0,0,-9223372036854775807);"); +executeQuery("select * from unsigntest;"); +prettyQuery("select * from unsigntest;"); +executeUpdate("drop database nodedb;"); + + setTimeout(()=>conn.close(),2000);