diff --git a/examples/C#/.gitignore b/examples/C#/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..59588c8c5a6f25cbef8ec070b706e783b5404807 --- /dev/null +++ b/examples/C#/.gitignore @@ -0,0 +1,13 @@ +C#checker/bin/ +C#checker/obj/ +TDengineTest/bin/ +TDengineTest/obj/ +schemaless/bin/ +schemaless/obj/ +stmt/TDengineDriver.cs +stmt/TaosBind.cs +stmt/TaosMultiBind.cs +stmt/bin/ +stmt/obj/ +taosdemo/bin/ +taosdemo/obj/ diff --git a/examples/C#/C#checker/C#checker.cs b/examples/C#/C#checker/C#checker.cs new file mode 100644 index 0000000000000000000000000000000000000000..29ad290343bb4fbacade48a0b59e0350bd35f213 --- /dev/null +++ b/examples/C#/C#checker/C#checker.cs @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +using System; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Collections; + +namespace TDengineDriver +{ + class TDengineTest + { + //connect parameters + private string host; + private string configDir; + private string user; + private string password; + private short port = 0; + + //sql parameters + private string dbName; + private string tbName; + private string precision; + + private bool isInsertData; + private bool isQueryData; + + private long tableCount; + private long totalRows; + private long batchRows; + private long beginTimestamp = 1551369600000L; + + private IntPtr conn = IntPtr.Zero; + private long rowsInserted = 0; + + static void Main(string[] args) + { + TDengineTest tester = new TDengineTest(); + tester.ReadArgument(args); + + + tester.InitTDengine(); + tester.ConnectTDengine(); + tester.createDatabase(); + tester.useDatabase(); + tester.checkDropTable(); + tester.createTable(); + tester.checkInsert(); + tester.checkSelect(); + tester.checkDropTable(); + tester.dropDatabase(); + tester.CloseConnection(); + tester.cleanup(); + + + } + + public long GetArgumentAsLong(String[] argv, String argName, int minVal, int maxVal, int defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", tmp); + ExitProgram(); + } + + long tmpVal = Convert.ToInt64(tmp); + if (tmpVal < minVal || tmpVal > maxVal) + { + Console.WriteLine("option {0:G} should in range [{1:G}, {2:G}]", argName, minVal, maxVal); + ExitProgram(); + } + + return tmpVal; + } + } + + return defaultValue; + } + + public String GetArgumentAsString(String[] argv, String argName, String defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", tmp); + ExitProgram(); + } + return tmp; + } + } + + return defaultValue; + } + + public void PrintHelp(String[] argv) + { + for (int i = 0; i < argv.Length; ++i) + { + if ("--help" == argv[i]) + { + String indent = " "; + Console.WriteLine("taosTest is simple example to operate TDengine use C# Language.\n"); + Console.WriteLine("{0:G}{1:G}", indent, "-h"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "TDEngine server IP address to connect"); + Console.WriteLine("{0:G}{1:G}", indent, "-u"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is root"); + Console.WriteLine("{0:G}{1:G}", indent, "-p"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is taosdata"); + Console.WriteLine("{0:G}{1:G}", indent, "-d"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Database used to create table or import data, default is db"); + Console.WriteLine("{0:G}{1:G}", indent, "-s"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Super Tables used to create table, default is mt"); + Console.WriteLine("{0:G}{1:G}", indent, "-t"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Table prefixs, default is t"); + Console.WriteLine("{0:G}{1:G}", indent, "-w"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to insert data"); + Console.WriteLine("{0:G}{1:G}", indent, "-r"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to query data"); + Console.WriteLine("{0:G}{1:G}", indent, "-n"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many Tables to create, default is 10"); + Console.WriteLine("{0:G}{1:G}", indent, "-b"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows per insert batch, default is 10"); + Console.WriteLine("{0:G}{1:G}", indent, "-i"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows to insert, default is 100"); + Console.WriteLine("{0:G}{1:G}", indent, "-c"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configuration directory"); + // + Console.WriteLine("{0:G}{1:G}", indent, "-ps"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configurate db precision,default millisecond"); + ExitProgram(); + } + } + } + + public void ReadArgument(String[] argv) + { + PrintHelp(argv); + host = this.GetArgumentAsString(argv, "-h", "127.0.0.1"); + user = this.GetArgumentAsString(argv, "-u", "root"); + password = this.GetArgumentAsString(argv, "-p", "taosdata"); + dbName = this.GetArgumentAsString(argv, "-d", "test"); + tbName = this.GetArgumentAsString(argv, "-s", "weather"); + precision = this.GetArgumentAsString(argv, "-ps", "ms"); + isInsertData = this.GetArgumentAsLong(argv, "-w", 0, 1, 1) != 0; + isQueryData = this.GetArgumentAsLong(argv, "-r", 0, 1, 1) != 0; + tableCount = this.GetArgumentAsLong(argv, "-n", 1, 10000, 10); + batchRows = this.GetArgumentAsLong(argv, "-b", 1, 1000, 500); + totalRows = this.GetArgumentAsLong(argv, "-i", 1, 10000000, 10000); + configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg"); + } + + public void InitTDengine() + { + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir); + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60"); + Console.WriteLine("init..."); + TDengine.Init(); + Console.WriteLine("get connection starting..."); + } + + public void ConnectTDengine() + { + string db = ""; + this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port); + if (this.conn == IntPtr.Zero) + { + Console.WriteLine("connection failed: " + this.host); + ExitProgram(); + } + else + { + Console.WriteLine("[ OK ] Connection established."); + } + } + public void createDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("create database if not exists ").Append(this.dbName).Append(" precision '").Append(this.precision).Append("'"); + execute(sql.ToString()); + } + public void useDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("use ").Append(this.dbName); + execute(sql.ToString()); + } + public void checkSelect() + { + StringBuilder sql = new StringBuilder(); + sql.Append("select * from ").Append(this.dbName).Append(".").Append(this.tbName); + ExecuteQuery(sql.ToString()); + } + public void createTable() + { + StringBuilder sql = new StringBuilder(); + sql.Append("create table if not exists ").Append(this.dbName).Append(".").Append(this.tbName).Append("(ts timestamp, temperature float, humidity int)"); + execute(sql.ToString()); + } + public void checkInsert() + { + StringBuilder sql = new StringBuilder(); + sql.Append("insert into ").Append(this.dbName).Append(".").Append(this.tbName).Append("(ts, temperature, humidity) values(now, 20.5, 34)"); + execute(sql.ToString()); + } + public void checkDropTable() + { + StringBuilder sql = new StringBuilder(); + sql.Append("drop table if exists ").Append(this.dbName).Append(".").Append(this.tbName).Append(""); + execute(sql.ToString()); + } + public void dropDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("drop database if exists ").Append(this.dbName); + execute(sql.ToString()); + } + public void execute(string sql) + { + DateTime dt1 = DateTime.Now; + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + DateTime dt2 = DateTime.Now; + TimeSpan span = dt2 - dt1; + + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + } + + public void ExecuteQuery(string sql) + { + + DateTime dt1 = DateTime.Now; + long queryRows = 0; + IntPtr res = TDengine.Query(conn, sql); + getPrecision(res); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + DateTime dt2 = DateTime.Now; + TimeSpan span = dt2 - dt1; + Console.WriteLine("[OK] time cost: " + span.ToString() + "ms, execute statement ====> " + sql.ToString()); + int fieldCount = TDengine.FieldCount(res); + + List metas = TDengine.FetchFields(res); + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + } + + IntPtr rowdata; + StringBuilder builder = new StringBuilder(); + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + builder.Append("---"); + + if (data == IntPtr.Zero) + { + builder.Append("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + builder.Append(v1); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + byte v2 = Marshal.ReadByte(data); + builder.Append(v2); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + builder.Append(v3); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + builder.Append(v4); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + builder.Append(v5); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + builder.Append(v6); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + builder.Append(v7); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data); + builder.Append(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + builder.Append(v9); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data); + builder.Append(v10); + break; + } + } + builder.Append("---"); + + if (queryRows <= 10) + { + Console.WriteLine(builder.ToString()); + } + builder.Clear(); + } + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res)); + } + Console.WriteLine(""); + + TDengine.FreeResult(res); + + } + + public void CloseConnection() + { + if (this.conn != IntPtr.Zero) + { + TDengine.Close(this.conn); + Console.WriteLine("connection closed."); + } + } + + static void ExitProgram() + { + System.Environment.Exit(0); + } + + public void cleanup() + { + Console.WriteLine("clean up..."); + System.Environment.Exit(0); + } + // method to get db precision + public void getPrecision(IntPtr res) + { + int psc=TDengine.ResultPrecision(res); + switch(psc) + { + case 0: + Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"millisecond"); + break; + case 1: + Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"microsecond"); + break; + case 2: + Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"nanosecond"); + break; + } + + } + } +} diff --git a/examples/C#/C#checker/C#checker.csproj b/examples/C#/C#checker/C#checker.csproj new file mode 100644 index 0000000000000000000000000000000000000000..afeeaf3f01301210c0e945c8e02b40790ebec743 --- /dev/null +++ b/examples/C#/C#checker/C#checker.csproj @@ -0,0 +1,13 @@ + + + + Exe + net5.0 + C_checker + + + + + + + diff --git a/examples/C#/TDengineTest/TDengineTest.cs b/examples/C#/TDengineTest/TDengineTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f84634ffb400e5d891a9fdeaeee0c013829f969 --- /dev/null +++ b/examples/C#/TDengineTest/TDengineTest.cs @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +using System; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Collections; + +namespace TDengineDriver +{ + class TDengineTest + { + //connect parameters + private string host; + private string configDir; + private string user; + private string password; + private short port = 0; + + //sql parameters + private string dbName; + private string stableName; + private string tablePrefix; + + private bool isInsertData; + private bool isQueryData; + + private long tableCount; + private long totalRows; + private long batchRows; + private long beginTimestamp = 1551369600000L; + + private IntPtr conn = IntPtr.Zero; + private long rowsInserted = 0; + + static void Main(string[] args) + { + TDengineTest tester = new TDengineTest(); + tester.ReadArgument(args); + + Console.WriteLine("---------------------------------------------------------------"); + Console.WriteLine("Starting Testing..."); + Console.WriteLine("---------------------------------------------------------------"); + + tester.InitTDengine(); + tester.ConnectTDengine(); + tester.CreateDbAndTable(); + tester.ExecuteInsert(); + tester.ExecuteQuery(); + tester.CloseConnection(); + + Console.WriteLine("---------------------------------------------------------------"); + Console.WriteLine("Stop Testing..."); + Console.WriteLine("---------------------------------------------------------------"); + + } + + public long GetArgumentAsLong(String[] argv, String argName, int minVal, int maxVal, int defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", tmp); + ExitProgram(); + } + + long tmpVal = Convert.ToInt64(tmp); + if (tmpVal < minVal || tmpVal > maxVal) + { + Console.WriteLine("option {0:G} should in range [{1:G}, {2:G}]", argName, minVal, maxVal); + ExitProgram(); + } + + return tmpVal; + } + } + + return defaultValue; + } + + public String GetArgumentAsString(String[] argv, String argName, String defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", tmp); + ExitProgram(); + } + return tmp; + } + } + + return defaultValue; + } + + public void PrintHelp(String[] argv) + { + for (int i = 0; i < argv.Length; ++i) + { + if ("--help" == argv[i]) + { + String indent = " "; + Console.WriteLine("taosTest is simple example to operate TDengine use C# Language.\n"); + Console.WriteLine("{0:G}{1:G}", indent, "-h"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "TDEngine server IP address to connect"); + Console.WriteLine("{0:G}{1:G}", indent, "-u"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is root"); + Console.WriteLine("{0:G}{1:G}", indent, "-p"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is taosdata"); + Console.WriteLine("{0:G}{1:G}", indent, "-d"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Database used to create table or import data, default is db"); + Console.WriteLine("{0:G}{1:G}", indent, "-s"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Super Tables used to create table, default is mt"); + Console.WriteLine("{0:G}{1:G}", indent, "-t"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Table prefixs, default is t"); + Console.WriteLine("{0:G}{1:G}", indent, "-w"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to insert data"); + Console.WriteLine("{0:G}{1:G}", indent, "-r"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to query data"); + Console.WriteLine("{0:G}{1:G}", indent, "-n"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many Tables to create, default is 10"); + Console.WriteLine("{0:G}{1:G}", indent, "-b"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows per insert batch, default is 10"); + Console.WriteLine("{0:G}{1:G}", indent, "-i"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows to insert, default is 100"); + Console.WriteLine("{0:G}{1:G}", indent, "-c"); + Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configuration directory"); + + ExitProgram(); + } + } + } + + public void ReadArgument(String[] argv) + { + PrintHelp(argv); + host = this.GetArgumentAsString(argv, "-h", "127.0.0.1"); + user = this.GetArgumentAsString(argv, "-u", "root"); + password = this.GetArgumentAsString(argv, "-p", "taosdata"); + dbName = this.GetArgumentAsString(argv, "-d", "tdengint_test_cs"); + stableName = this.GetArgumentAsString(argv, "-s", "st"); + tablePrefix = this.GetArgumentAsString(argv, "-t", "t"); + isInsertData = this.GetArgumentAsLong(argv, "-w", 0, 1, 1) != 0; + isQueryData = this.GetArgumentAsLong(argv, "-r", 0, 1, 1) != 0; + tableCount = this.GetArgumentAsLong(argv, "-n", 1, 10000, 10); + batchRows = this.GetArgumentAsLong(argv, "-b", 1, 1000,500 ); + totalRows = this.GetArgumentAsLong(argv, "-i", 1, 10000000, 10000); + configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg"); + } + + public void InitTDengine() + { + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir); + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60"); + TDengine.Init(); + Console.WriteLine("TDengine Initialization finished"); + } + + public void ConnectTDengine() + { + string db = ""; + Console.WriteLine("Host:{0}", this.host); + this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port); + if (this.conn == IntPtr.Zero) + { + Console.WriteLine("Connect to TDengine failed"); + ExitProgram(); + } + else + { + Console.WriteLine("Connect to TDengine success"); + } + } + + public void CreateDbAndTable() + { + if (!this.isInsertData) + { + return; + } + + StringBuilder sql = new StringBuilder(); + sql.Append("create database if not exists ").Append(this.dbName); + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + + sql.Clear(); + sql.Append("use ").Append(this.dbName); + res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + + sql.Clear(); + sql.Append("create table if not exists ").Append(this.stableName).Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10)) tags(t1 int)"); + res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + + for (int i = 0; i < this.tableCount; i++) + { + sql.Clear(); + sql = sql.Append("create table if not exists ").Append(this.tablePrefix).Append(i) + .Append(" using ").Append(this.stableName).Append(" tags(").Append(i).Append(")"); + res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + } + + Console.WriteLine("create db and table success"); + } + + public void ExecuteInsert() + { + if (!this.isInsertData) + { + return; + } + + System.DateTime start = new System.DateTime(); + long loopCount = this.totalRows / this.batchRows; + + for (int table = 0; table < this.tableCount; ++table) + { + for (long loop = 0; loop < loopCount; loop++) + { + StringBuilder sql = new StringBuilder(); + sql.Append("insert into ").Append(this.tablePrefix).Append(table).Append(" values"); + for (int batch = 0; batch < this.batchRows; ++batch) + { + + long rows = loop * this.batchRows + batch; + sql.Append("(") + .Append(this.beginTimestamp + rows) + .Append(", 1, 2, 3,") + .Append(rows) + .Append(", 5, 6, 7, 'abc', 'def')"); + } + IntPtr res = TDengine.Query(this.conn,sql.ToString() ); + + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + } + + int affectRows = TDengine.AffectRows(res); + this.rowsInserted += affectRows; + + TDengine.FreeResult(res); + } + } + + System.DateTime end = new System.DateTime(); + TimeSpan ts = end - start; + + Console.Write("Total {0:G} rows inserted, {1:G} rows failed, time spend {2:G} seconds.\n" + , this.rowsInserted, this.totalRows * this.tableCount - this.rowsInserted, ts.TotalSeconds); + } + + public void ExecuteQuery() + { + if (!this.isQueryData) + { + return; + } + + System.DateTime start = new System.DateTime(); + long queryRows = 0; + + for (int i = 0; i < 1/*this.tableCount*/; ++i) + { + String sql = "select * from " + this.dbName + "." + tablePrefix + i; + Console.WriteLine(sql); + + IntPtr res = TDengine.Query(conn, sql); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + + int fieldCount = TDengine.FieldCount(res); + Console.WriteLine("field count: " + fieldCount); + + List metas = TDengine.FetchFields(res); + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + Console.WriteLine("index:" + j + ", type:" + meta.type + ", typename:" + meta.TypeName() + ", name:" + meta.name + ", size:" + meta.size); + } + + IntPtr rowdata; + StringBuilder builder = new StringBuilder(); + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + builder.Append("---"); + + if (data == IntPtr.Zero) + { + builder.Append("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + builder.Append(v1); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + byte v2 = Marshal.ReadByte(data); + builder.Append(v2); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + builder.Append(v3); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + builder.Append(v4); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + builder.Append(v5); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + builder.Append(v6); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + builder.Append(v7); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data); + builder.Append(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + builder.Append(v9); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data); + builder.Append(v10); + break; + case TDengineDataType.TSDB_DATA_TYPE_UTINYINT: + byte v11 = Marshal.ReadByte(data); + builder.Append(v11); + break; + case TDengineDataType.TSDB_DATA_TYPE_USMALLINT: + ushort v12 = (ushort)Marshal.ReadInt16(data); + builder.Append(v12); + break; + case TDengineDataType.TSDB_DATA_TYPE_UINT: + uint v13 = (uint)Marshal.ReadInt32(data); + builder.Append(v13); + break; + case TDengineDataType.TSDB_DATA_TYPE_UBIGINT: + ulong v14 = (ulong)Marshal.ReadInt64(data); + builder.Append(v14); + break; + } + } + builder.Append("---"); + + if (queryRows <= 10) + { + Console.WriteLine(builder.ToString()); + } + builder.Clear(); + } + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", + TDengine.ErrorNo(res), TDengine.Error(res)); + } + Console.WriteLine(""); + + TDengine.FreeResult(res); + } + + System.DateTime end = new System.DateTime(); + TimeSpan ts = end - start; + + Console.Write("Total {0:G} rows inserted, {1:G} rows query, time spend {2:G} seconds.\n" + , this.rowsInserted, queryRows, ts.TotalSeconds); + } + + public void CloseConnection() + { + if (this.conn != IntPtr.Zero) + { + TDengine.Close(this.conn); + } + } + + static void ExitProgram() + { + TDengine.Cleanup(); + System.Environment.Exit(0); + } + } +} diff --git a/examples/C#/TDengineTest/TDengineTest.csproj b/examples/C#/TDengineTest/TDengineTest.csproj new file mode 100644 index 0000000000000000000000000000000000000000..211c927d3d36df5941291319e3c85707610c6a8f --- /dev/null +++ b/examples/C#/TDengineTest/TDengineTest.csproj @@ -0,0 +1,12 @@ + + + + Exe + net5.0 + + + + + + + diff --git a/examples/C#/schemaless/TDengineDriver.cs b/examples/C#/schemaless/TDengineDriver.cs new file mode 100644 index 0000000000000000000000000000000000000000..8dd9ce0c929df66fd82bd40d6ff77a868c630efe --- /dev/null +++ b/examples/C#/schemaless/TDengineDriver.cs @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace TDengineDriver +{ + enum TDengineDataType + { + TSDB_DATA_TYPE_NULL = 0, // 1 bytes + TSDB_DATA_TYPE_BOOL = 1, // 1 bytes + TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes + TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes + TSDB_DATA_TYPE_INT = 4, // 4 bytes + TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes + TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes + TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes + TSDB_DATA_TYPE_BINARY = 8, // string + TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes + TSDB_DATA_TYPE_NCHAR = 10, // unicode string + TSDB_DATA_TYPE_UTINYINT = 11,// 1 byte + TSDB_DATA_TYPE_USMALLINT = 12,// 2 bytes + TSDB_DATA_TYPE_UINT = 13, // 4 bytes + TSDB_DATA_TYPE_UBIGINT = 14 // 8 bytes + } + + enum TDengineInitOption + { + TSDB_OPTION_LOCALE = 0, + TSDB_OPTION_CHARSET = 1, + TSDB_OPTION_TIMEZONE = 2, + TDDB_OPTION_CONFIGDIR = 3, + TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4 + } + enum TDengineSchemalessProtocol + { + TSDB_SML_UNKNOWN_PROTOCOL = 0, + TSDB_SML_LINE_PROTOCOL = 1, + TSDB_SML_TELNET_PROTOCOL = 2, + TSDB_SML_JSON_PROTOCOL = 3 + + } + enum TDengineSchemalessPrecision + { + 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 + } + + class TDengineMeta + { + public string name; + public short size; + public byte type; + public string TypeName() + { + switch ((TDengineDataType)type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + return "BOOL"; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + return "TINYINT"; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + return "SMALLINT"; + case TDengineDataType.TSDB_DATA_TYPE_INT: + return "INT"; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + return "BIGINT"; + case TDengineDataType.TSDB_DATA_TYPE_UTINYINT: + return "TINYINT UNSIGNED"; + case TDengineDataType.TSDB_DATA_TYPE_USMALLINT: + return "SMALLINT UNSIGNED"; + case TDengineDataType.TSDB_DATA_TYPE_UINT: + return "INT UNSIGNED"; + case TDengineDataType.TSDB_DATA_TYPE_UBIGINT: + return "BIGINT UNSIGNED"; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + return "FLOAT"; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + return "DOUBLE"; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + return "STRING"; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + return "TIMESTAMP"; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + return "NCHAR"; + default: + return "undefine"; + } + } + } + + class TDengine + { + public const int TSDB_CODE_SUCCESS = 0; + + [DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)] + static extern public void Init(); + + [DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)] + static extern public void Cleanup(); + + [DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)] + static extern public void Options(int option, string value); + + [DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr Connect(string ip, string user, string password, string db, short port); + + [DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)] + static extern private IntPtr taos_errstr(IntPtr res); + static public string Error(IntPtr res) + { + IntPtr errPtr = taos_errstr(res); + return Marshal.PtrToStringAnsi(errPtr); + } + + [DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)] + static extern public int ErrorNo(IntPtr res); + + [DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr Query(IntPtr conn, string sqlstr); + + [DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)] + static extern public int AffectRows(IntPtr res); + + [DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)] + static extern public int FieldCount(IntPtr res); + + [DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)] + static extern private IntPtr taos_fetch_fields(IntPtr res); + static public List FetchFields(IntPtr res) + { + const int fieldSize = 68; + + List metas = new List(); + if (res == IntPtr.Zero) + { + return metas; + } + + int fieldCount = FieldCount(res); + IntPtr fieldsPtr = taos_fetch_fields(res); + + for (int i = 0; i < fieldCount; ++i) + { + int offset = i * fieldSize; + + TDengineMeta meta = new TDengineMeta(); + meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset); + meta.type = Marshal.ReadByte(fieldsPtr + offset + 65); + meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66); + metas.Add(meta); + } + + return metas; + } + + [DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr FetchRows(IntPtr res); + + [DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr FreeResult(IntPtr res); + + [DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)] + static extern public int Close(IntPtr taos); + + //get precision in restultset + [DllImport("taos", EntryPoint = "taos_result_precision", CallingConvention = CallingConvention.Cdecl)] + static extern public int ResultPrecision(IntPtr taos); + + //schemaless API + [DllImport("taos",SetLastError = true, EntryPoint = "taos_schemaless_insert", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr SchemalessInsert(IntPtr taos, string[] lines, int numLines, int protocol, int precision); + } +} diff --git a/examples/C#/schemaless/schemaless.csproj b/examples/C#/schemaless/schemaless.csproj new file mode 100644 index 0000000000000000000000000000000000000000..d132e34589525826d5b0ff0f0055156fad2d5a38 --- /dev/null +++ b/examples/C#/schemaless/schemaless.csproj @@ -0,0 +1,12 @@ + + + + Exe + net5.0 + + + + + + + diff --git a/examples/C#/schemaless/schemalessSample.cs b/examples/C#/schemaless/schemalessSample.cs new file mode 100644 index 0000000000000000000000000000000000000000..f27ac352a6fc8a3fbbaf84966ae3b82e6036e91a --- /dev/null +++ b/examples/C#/schemaless/schemalessSample.cs @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +using System; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Collections; + +namespace TDengineDriver +{ + class SchemalessSample + { + // connect parameters + private string host = "127.0.0.1"; + private string configDir = "C:/TDengine/cfg"; + private string user = "root"; + private string passwd = "taosdata"; + private short port = 0; + + private IntPtr conn = IntPtr.Zero; + private string dbName = "csharp"; + private string dbPrecision = "ms"; + + static void Main(string[] args) + { + string[] lines = { + "stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", + "stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000" + }; + string[] jsonStr = { + "{" + +"\"metric\": \"stb0_0\"," + +"\"timestamp\": 1626006833," + +"\"value\": 10," + +"\"tags\": {" + +" \"t1\": true," + +"\"t2\": false," + +"\"t3\": 10," + +"\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\"" + +"}" + +"}" + }; + + SchemalessSample sample = new SchemalessSample(); + sample.InitTDengine(); + sample.ConnectTDengine(); + sample.dropDatabase(); + sample.createDatabase(); + sample.useDatabase(); + sample.schemalessInsert(lines, 2, (int)TDengineSchemalessProtocol.TSDB_SML_LINE_PROTOCOL, (int)TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_NANO_SECONDS); + sample.checkSelect("stg"); + sample.schemalessInsert(jsonStr,1,(int)TDengineSchemalessProtocol.TSDB_SML_JSON_PROTOCOL,(int)TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_SECONDS); + sample.checkSelect("stb0_0"); + sample.CloseConnection(); + sample.cleanup(); + } + + public void InitTDengine() + { + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir); + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60"); + Console.WriteLine("init..."); + TDengine.Init(); + Console.WriteLine("get connection starting..."); + } + + public void ConnectTDengine() + { + string db = ""; + this.conn = TDengine.Connect(host, this.user, this.passwd, db, this.port); + if (this.conn == IntPtr.Zero) + { + Console.WriteLine("connection failed: " + this.host); + ExitProgram(); + } + else + { + Console.WriteLine("[ OK ] Connection established."); + } + } + public void createDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("create database if not exists ").Append(this.dbName).Append(" precision '").Append(this.dbPrecision).Append("'"); + execute(sql.ToString()); + } + public void useDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("use ").Append(this.dbName); + execute(sql.ToString()); + } + public void checkSelect(String tableName) + { + StringBuilder sql = new StringBuilder(); + sql.Append("select * from ").Append(this.dbName).Append(".").Append(tableName); + ExecuteQuery(sql.ToString()); + } + + public void schemalessInsert(string[] sqlstr, int lineCnt, int protocol, int precision) + { + + IntPtr res = TDengine.SchemalessInsert(this.conn, sqlstr, lineCnt, protocol, precision); + + if (TDengine.ErrorNo(res) != 0) + { + Console.WriteLine("schemaless_insert failed:{0}", TDengine.Error(res)); + Console.WriteLine("line string:{0}", sqlstr); + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine("else"); + Console.WriteLine("schemaless insert success:{0}", TDengine.ErrorNo(res)); + } + DisplayRes(res); + } + public void dropDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("drop database if exists ").Append(this.dbName); + execute(sql.ToString()); + } + public void execute(string sql) + { + DateTime dt1 = DateTime.Now; + + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + + DateTime dt2 = DateTime.Now; + TimeSpan span = dt2 - dt1; + + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + } + public void DisplayRes(IntPtr res) + { + long queryRows = 0; + int fieldCount = TDengine.FieldCount(res); + + List metas = TDengine.FetchFields(res); + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + } + + IntPtr rowdata; + StringBuilder builder = new StringBuilder(); + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + builder.Append("---"); + + if (data == IntPtr.Zero) + { + builder.Append("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + builder.Append(v1); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + byte v2 = Marshal.ReadByte(data); + builder.Append(v2); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + builder.Append(v3); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + builder.Append(v4); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + builder.Append(v5); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + builder.Append(v6); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + builder.Append(v7); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data); + builder.Append(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + builder.Append(v9); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data); + builder.Append(v10); + break; + } + } + builder.Append("---"); + + if (queryRows <= 10) + { + Console.WriteLine(builder.ToString()); + } + builder.Clear(); + } + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res)); + } + Console.WriteLine(""); + + TDengine.FreeResult(res); + + } + public void ExecuteQuery(string sql) + { + + DateTime dt1 = DateTime.Now; + + IntPtr res = TDengine.Query(conn, sql); + + DateTime dt2 = DateTime.Now; + TimeSpan span = dt2 - dt1; + + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + + Console.WriteLine("[OK] time cost: " + span.ToString() + "ms, execute statement ====> " + sql.ToString()); + DisplayRes(res); + + } + + public void CloseConnection() + { + if (this.conn != IntPtr.Zero) + { + TDengine.Close(this.conn); + Console.WriteLine("connection closed."); + } + } + + static void ExitProgram() + { + System.Environment.Exit(0); + } + + public void cleanup() + { + Console.WriteLine("clean up..."); + System.Environment.Exit(0); + } + // method to get db precision + } +} diff --git a/examples/C#/stmt/StmtDemo.cs b/examples/C#/stmt/StmtDemo.cs new file mode 100644 index 0000000000000000000000000000000000000000..c2b299140976ed36f245f5693a2a047607c5b5be --- /dev/null +++ b/examples/C#/stmt/StmtDemo.cs @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ +using System; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Collections; +namespace TDengineDriver +{ + public class StmtDemo + { + //connection parameters + private string host = "127.0.0.1"; + private string configDir = "C:/TDengine/cfg"; + private string user = "root"; + private string passwd = "taosdata"; + private short port = 0; + + private IntPtr conn = IntPtr.Zero; + private IntPtr stmt = IntPtr.Zero; + + static void Main(string[] args) + { + string dropDB = "drop database if exists csharp"; + string createDB = "create database if not exists csharp keep 36500"; + string selectDB = "use csharp"; + string stmtSql = "insert into ? using stmtdemo tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + string createTable = "create stable stmtdemo (ts timestamp " + + ",b bool" + + ",v1 tinyint" + + ",v2 smallint" + + ",v4 int" + + ",v8 bigint" + + ",f4 float" + + ",f8 double" + + ",u1 tinyint unsigned" + + ",u2 smallint unsigned" + + ",u4 int unsigned" + + ",u8 bigint unsigned" + + ",bin binary(200)" + + ",blob nchar(200)" + + ")tags(" + + "bo bool" + + ",tt tinyint" + + ",si smallint" + + ",ii int" + + ",bi bigint" + + ",tu tinyint unsigned" + + ",su smallint unsigned" + + ",iu int unsigned" + + ",bu bigint unsigned" + + ",ff float " + + ",dd double " + + ",bb binary(200)" + + ",nc nchar(200)" + + ")"; + + string dropTable = "drop table if exists stmtdemo"; + + string tableName = "t1"; + StmtDemo stmtDemo = new StmtDemo(); + Console.WriteLine("---------------------------------------------------------------"); + Console.WriteLine("Start StmtDemo insert Testing..."); + Console.WriteLine("---------------------------------------------------------------"); + stmtDemo.InitTDengine(); + //TDengine connect + stmtDemo.ConnectTDengine(); + + //before stmt + stmtDemo.ExecuteQuery(dropDB); + stmtDemo.ExecuteQuery(createDB); + stmtDemo.ExecuteQuery(selectDB); + stmtDemo.ExecuteQuery(dropTable); + stmtDemo.ExecuteQuery(createTable); + + stmtDemo.StmtInit(); + string[] tableList = { "stmtdemo" }; + stmtDemo.loadTableInfo(tableList); + + stmtDemo.StmtPrepare(stmtSql); + TAOS_BIND[] binds = stmtDemo.InitBindArr(); + TAOS_MULTI_BIND[] mbinds = stmtDemo.InitMultBindArr(); + stmtDemo.SetTableNameTags(tableName, binds); + stmtDemo.BindParamBatch(mbinds); + stmtDemo.AddBatch(); + stmtDemo.StmtExecute(); + TaosBind.FreeTaosBind(binds); + TaosMultiBind.FreeTaosBind(mbinds); + stmtDemo.StmtClose(); + + Console.WriteLine("---------------------------------------------------------------"); + Console.WriteLine("start StmtDemo select Testing..."); + Console.WriteLine("---------------------------------------------------------------"); + + stmtDemo.StmtInit(); + string selectSql = "SELECT * FROM stmtdemo WHERE v1 > ? AND v4 < ?"; + + stmtDemo.StmtPrepare(selectSql); + + TAOS_BIND[] queryCondition = new TAOS_BIND[2]; + queryCondition[0] = TaosBind.BindTinyInt(0); + queryCondition[1] = TaosBind.BindInt(1000); + + Console.WriteLine(selectSql); + stmtDemo.BindParam(queryCondition); + stmtDemo.StmtExecute(); + + stmtDemo.StmtUseResult(); + + stmtDemo.StmtClose(); + TaosBind.FreeTaosBind(queryCondition); + Console.WriteLine("---------------------------------------------------------------"); + Console.WriteLine("Stop StmtDemo Testing..."); + Console.WriteLine("---------------------------------------------------------------"); + + stmtDemo.CloseConnection(); + } + public TAOS_BIND[] InitBindArr() + { + TAOS_BIND[] binds = new TAOS_BIND[13]; + binds[0] = TaosBind.BindBool(true); + binds[1] = TaosBind.BindTinyInt(-2); + binds[2] = TaosBind.BindSmallInt(short.MaxValue); + binds[3] = TaosBind.BindInt(int.MaxValue); + binds[4] = TaosBind.BindBigInt(Int64.MaxValue); + binds[5] = TaosBind.BindUTinyInt(byte.MaxValue - 1); + binds[6] = TaosBind.BindUSmallInt(UInt16.MaxValue - 1); + binds[7] = TaosBind.BindUInt(uint.MinValue + 1); + binds[8] = TaosBind.BindUBigInt(UInt64.MinValue + 1); + binds[9] = TaosBind.BindFloat(11.11F); + binds[10] = TaosBind.BindDouble(22.22D); + binds[11] = TaosBind.BindBinary("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}"); + binds[12] = TaosBind.BindNchar("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}"); + return binds; + } + + public TAOS_MULTI_BIND[] InitMultBindArr() + { + TAOS_MULTI_BIND[] mBinds = new TAOS_MULTI_BIND[14]; + long[] tsArr = new long[5] { 1637064040000, 1637064041000, 1637064042000, 1637064043000, 1637064044000 }; + bool?[] boolArr = new bool?[5] { true, false, null, true, true }; + sbyte?[] tinyIntArr = new sbyte?[5] { -127, 0, null, 8, 127 }; + short?[] shortArr = new short?[5] { short.MinValue + 1, -200, null, 100, short.MaxValue }; + int?[] intArr = new int?[5] { -200, -100, null, 0, 300 }; + long?[] longArr = new long?[5] { long.MinValue + 1, -2000, null, 1000, long.MaxValue }; + float?[] floatArr = new float?[5] { float.MinValue + 1, -12.1F, null, 0F, float.MaxValue }; + double?[] doubleArr = new double?[5] { double.MinValue + 1, -19.112D, null, 0D, double.MaxValue }; + byte?[] uTinyIntArr = new byte?[5] { byte.MinValue, 12, null, 89, byte.MaxValue - 1 }; + ushort?[] uShortArr = new ushort?[5] { ushort.MinValue, 200, null, 400, ushort.MaxValue - 1 }; + uint?[] uIntArr = new uint?[5] { uint.MinValue, 100, null, 2, uint.MaxValue - 1 }; + ulong?[] uLongArr = new ulong?[5] { ulong.MinValue, 2000, null, 1000, long.MaxValue - 1 }; + string[] binaryArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", String.Empty, null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?" }; + string[] ncharArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", string.Empty }; + mBinds[0] = TaosMultiBind.MultiBindTimestamp(tsArr); + mBinds[1] = TaosMultiBind.MultiBindBool(boolArr); + mBinds[2] = TaosMultiBind.MultiBindTinyInt(tinyIntArr); + mBinds[3] = TaosMultiBind.MultiBindSmallInt(shortArr); + mBinds[4] = TaosMultiBind.MultiBindInt(intArr); + mBinds[5] = TaosMultiBind.MultiBindBigint(longArr); + mBinds[6] = TaosMultiBind.MultiBindFloat(floatArr); + mBinds[7] = TaosMultiBind.MultiBindDouble(doubleArr); + mBinds[8] = TaosMultiBind.MultiBindUTinyInt(uTinyIntArr); + mBinds[9] = TaosMultiBind.MultiBindUSmallInt(uShortArr); + mBinds[10] = TaosMultiBind.MultiBindUInt(uIntArr); + mBinds[11] = TaosMultiBind.MultiBindUBigInt(uLongArr); + mBinds[12] = TaosMultiBind.MultiBindBinary(binaryArr); + mBinds[13] = TaosMultiBind.MultiBindNchar(ncharArr); + return mBinds; + } + + public void loadTableInfo(string[] arr) + { + if (TDengine.LoadTableInfo(this.conn, arr) == 0) + { + Console.WriteLine("load table info success"); + } + else + { + Console.WriteLine("load table info failed"); + ExitProgram(); + } + } + + public void InitTDengine() + { + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir); + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60"); + TDengine.Init(); + Console.WriteLine("TDengine Initialization finished"); + } + + public void ConnectTDengine() + { + string db = ""; + this.conn = TDengine.Connect(this.host, this.user, this.passwd, db, this.port); + if (this.conn == IntPtr.Zero) + { + Console.WriteLine("Connect to TDengine failed"); + ExitProgram(); + } + else + { + Console.WriteLine("Connect to TDengine success"); + } + } + + public void ExecuteQuery(String sql) + { + IntPtr res = TDengine.Query(conn, sql); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + else + { + Console.WriteLine(sql.ToString() + " success"); + } + TDengine.FreeResult(res); + } + + public void StmtInit() + { + this.stmt = TDengine.StmtInit(conn); + if (this.stmt == IntPtr.Zero) + { + Console.WriteLine("Init stmt failed"); + ExitProgram(); + } + else + { + Console.WriteLine("Init stmt success"); + } + } + + public void StmtPrepare(string sql) + { + int res = TDengine.StmtPrepare(this.stmt, sql); + if (res == 0) + { + Console.WriteLine("stmt prepare success"); + } + else + { + Console.WriteLine("stmt prepare failed " + TDengine.StmtErrorStr(stmt)); + ExitProgram(); + } + } + + public void SetTableName(String tableName) + { + int res = TDengine.StmtSetTbname(this.stmt, tableName); + Console.WriteLine("setTableName():" + res); + if (res == 0) + { + Console.WriteLine("set_tbname success"); + } + else + { + Console.Write("set_tbname failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + + public void SetTableNameTags(String tableName, TAOS_BIND[] tags) + { + int res = TDengine.StmtSetTbnameTags(this.stmt, tableName, tags); + if (res == 0) + { + Console.WriteLine("set tbname && tags success"); + + } + else + { + Console.Write("set tbname && tags failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + + public void SetSubTableName(string name) + { + int res = TDengine.StmtSetSubTbname(this.stmt, name); + if (res == 0) + { + Console.WriteLine("set subtable name success"); + } + else + { + Console.Write("set subtable name failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + + } + + public void BindParam(TAOS_BIND[] binds) + { + Console.WriteLine("in bindParam()"); + + int res = TDengine.StmtBindParam(this.stmt, binds); + if (res == 0) + { + Console.WriteLine("bind para success"); + } + else + { + Console.Write("bind para failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + + public void BindSingleParamBatch(TAOS_MULTI_BIND bind, int index) + { + int res = TDengine.StmtBindSingleParamBatch(this.stmt,ref bind, index); + if (res == 0) + { + Console.WriteLine("single bind batch success"); + } + else + { + Console.Write("single bind batch failed: " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + + public void BindParamBatch(TAOS_MULTI_BIND[] bind) + { + int res = TDengine.StmtBindParamBatch(this.stmt, bind); + if (res == 0) + { + Console.WriteLine("bind parameter batch success"); + } + else + { + Console.WriteLine("bind parameter batch failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + + public void AddBatch() + { + int res = TDengine.StmtAddBatch(this.stmt); + if (res == 0) + { + Console.WriteLine("stmt add batch success"); + } + else + { + Console.Write("stmt add batch failed,reason: " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + public void StmtExecute() + { + int res = TDengine.StmtExecute(this.stmt); + if (res == 0) + { + Console.WriteLine("Execute stmt success"); + } + else + { + Console.Write("Execute stmt failed,reason: " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + public void StmtClose() + { + int res = TDengine.StmtClose(this.stmt); + if (res == 0) + { + Console.WriteLine("close stmt success"); + } + else + { + Console.WriteLine("close stmt failed, " + TDengine.StmtErrorStr(stmt)); + StmtClose(); + ExitProgram(); + } + } + public void CloseConnection() + { + if (this.conn != IntPtr.Zero) + { + if (TDengine.Close(this.conn) == 0) + { + Console.WriteLine("close connection sucess"); + } + else + { + Console.WriteLine("close Connection failed"); + } + } + } + + //select only + public void StmtUseResult() + { + IntPtr res = TDengine.StmtUseResult(this.stmt); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + StmtClose(); + CloseConnection(); + ExitProgram(); + } + else + { + Console.WriteLine("{0},query success"); + DisplayRes(res); + TDengine.FreeResult(res); + } + + } + + public void DisplayRes(IntPtr res) + { + + long queryRows = 0; + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + ExitProgram(); + } + + int fieldCount = TDengine.FieldCount(res); + List metas = TDengine.FetchFields(res); + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + } + + IntPtr rowdata; + StringBuilder builder = new StringBuilder(); + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + builder.Append("---"); + + if (data == IntPtr.Zero) + { + builder.Append("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + builder.Append(v1); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + byte v2 = Marshal.ReadByte(data); + builder.Append(v2); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + builder.Append(v3); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + builder.Append(v4); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + builder.Append(v5); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + builder.Append(v6); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + builder.Append(v7); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data); + builder.Append(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + builder.Append(v9); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data); + builder.Append(v10); + break; + } + } + builder.Append("---"); + + if (queryRows <= 10) + { + Console.WriteLine(builder.ToString()); + } + builder.Clear(); + } + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res)); + } + Console.WriteLine(""); + + } + public static void ExitProgram() + { + TDengine.Cleanup(); + System.Environment.Exit(0); + } + } +} diff --git a/examples/C#/stmt/stmt.csproj b/examples/C#/stmt/stmt.csproj new file mode 100644 index 0000000000000000000000000000000000000000..bc14850edbf9023e885436016141f24d6d042127 --- /dev/null +++ b/examples/C#/stmt/stmt.csproj @@ -0,0 +1,12 @@ + + + + + + + + Exe + net5.0 + + + diff --git a/examples/C#/taosdemo/Dockerfile b/examples/C#/taosdemo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4eefc6c75248b1e1e1d6daf305386cca5b11e606 --- /dev/null +++ b/examples/C#/taosdemo/Dockerfile @@ -0,0 +1,24 @@ +FROM tdengine/tdengine-beta:latest + +ENV DEBIAN_FRONTEND=noninteractive +ARG MIRROR=archive.ubuntu.com +RUN sed -Ei 's/\w+.ubuntu.com/'${MIRROR}'/' /etc/apt/sources.list && apt update && apt install mono-devel -y +RUN apt-get install wget -y \ + && wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-sdk-5.0 +COPY ./*.cs *.csproj /tmp/ +WORKDIR /tmp/ +RUN dotnet build -c Release && cp bin/Release/net5.0/taosdemo bin/Release/net5.0/taosdemo.* /usr/local/bin/ && rm -rf /tmp/* + +FROM tdengine/tdengine-beta:latest + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install wget -y \ + && wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-runtime-5.0 +COPY --from=0 /usr/local/bin/taosdemo* /usr/local/bin/ +CMD ["/usr/local/bin/taosdemo"] diff --git a/examples/C#/taosdemo/README.md b/examples/C#/taosdemo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3cba3529bf513e2bf3d4ab0c169e7f3d03b2e6a8 --- /dev/null +++ b/examples/C#/taosdemo/README.md @@ -0,0 +1,65 @@ +# C# Taosdemo + +## For Mono + +install build environment + +```sh +yum/apt install mono-complete +``` + +build C# version taosdemo. + +```sh +mcs -out:taosdemo *.cs +./taosdemo --help +``` + +## For DotNet + +install dotnet environment. + +```sh +wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-sdk-5.0 +``` + +Build DotNet version taosdemo. + +```sh +dotnet build -c Release +./bin/Release/net5.0/taosdemo --help +``` + +## Usage + +``` +Usage: mono taosdemo.exe [OPTION...] + + --help Show usage. + + -h host, The host to connect to TDengine. Default is localhost. + -p port, The TCP/IP port number to use for the connection. Default is 0. + -u user, The user name to use when connecting to the server. Default is 'root'. + -P password, The password to use when connecting to the server. Default is 'taosdata'. + -d database, Destination database. Default is 'test'. + -a replica, Set the replica parameters of the database, Default 1, min: 1, max: 5. + -m table_prefix, Table prefix name. Default is 't'. + -M stable, Use super table. + -s stable_prefix, STable prefix name. Default is 'st' + -Q query, Execute query command. set 'DEFAULT' means select * from each table + -T num_of_threads, The number of threads. Default is 10. + -r num_of_records_per_req, The number of records per request. Default is 1000. + -t num_of_tables, The number of tables. Default is 1. + -n num_of_records_per_table, The number of records per table. Default is 1. + -c config_directory, Configuration directory. Default is '/etc/taos/'. + -x flag, Insert only flag. + -O order, Insert mode--0: In order, 1: Out of order. Default is in order. + -R rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50. + -D Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database. + -v Print verbose output + -g Print debug output + -y Skip read key for continous test, default is not skip +``` diff --git a/examples/C#/taosdemo/taosdemo.cs b/examples/C#/taosdemo/taosdemo.cs new file mode 100644 index 0000000000000000000000000000000000000000..e62a502d1508c1339e559160b50da39e622a021f --- /dev/null +++ b/examples/C#/taosdemo/taosdemo.cs @@ -0,0 +1,908 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +using System; +using System.Text; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Collections; +using System.Threading; +using System.Diagnostics; + +namespace TDengineDriver +{ + class TDengineTest + { + //connect parameters + private string host = "127.0.0.1"; + private string configDir = "C:/TDengine/cfg"; + private string user = "root"; + private string password = "taosdata"; + private short port = 0; + + //sql parameters + private string dbName = "db"; + private string stablePrefix = "st"; + private string tablePrefix = "t"; + + private bool isInsertOnly = false; + private string query = "NONE"; + private short queryMode = 1; + + private long recordsPerTable = 1; + private int recordsPerRequest = 1; + private int colsPerRecord = 3; + private long batchRows = 1000; + private long numOfTables = 1; + private short replica = 1; + + private IntPtr conn = IntPtr.Zero; + // private long rowsInserted = 0; + private bool useStable = false; + private short methodOfDelete = 0; + private long numOfThreads = 1; + private short rateOfOutorder = 10; + private bool order = true; + private bool skipReadKey = false; + private bool verbose = false; + private bool debug = false; + + + static void HelpPrint(string arg, string desc) + { + string indent = " "; + Console.WriteLine("{0}{1}", indent, arg.PadRight(25) + desc); + } + + static void PrintHelp(String[] argv) + { + for (int i = 0; i < argv.Length; ++i) + { + if ("--help" == argv[i]) + { + Console.WriteLine("Usage: mono taosdemo.exe [OPTION...]"); + Console.WriteLine(""); + HelpPrint("--help", "Show usage."); + Console.WriteLine(""); + + HelpPrint("-h ", "host, The host to connect to TDengine. Default is localhost."); + HelpPrint("-p ", "port, The TCP/IP port number to use for the connection. Default is 0."); + HelpPrint("-u ", "user, The user name to use when connecting to the server. Default is 'root'."); + HelpPrint("-P ", "password, The password to use when connecting to the server. Default is 'taosdata'."); + HelpPrint("-d ", "database, Destination database. Default is 'test'."); + HelpPrint("-a ", "replica, Set the replica parameters of the database, Default 1, min: 1, max: 5."); + HelpPrint("-m
", "table_prefix, Table prefix name. Default is 't'."); + HelpPrint("-M", "stable, Use super table."); + HelpPrint("-s ", "stable_prefix, STable prefix name. Default is 'st'"); + HelpPrint("-Q ", "query, Execute query command. set 'DEFAULT' means select * from each table"); + /* NOT SUPPORT SO FAR + HelpPrint("-o", "outputfile, Direct output to the named file. Default is './output.txt'."); + HelpPrint("-q", "query_mode, Query mode--0: SYNC, 1: ASYNC. Default is SYNC."); + HelpPrint("-b", "type_of_cols, data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'."); + HelpPrint("-w", "length_of_binary, The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8"); + HelpPrint("-l", "num_of_cols_per_record, The number of columns per record. Default is 3."); + */ + HelpPrint("-T ", "num_of_threads, The number of threads. Default is 10."); + HelpPrint("-r ", "num_of_records_per_req, The number of records per request. Default is 1000."); + HelpPrint("-t ", "num_of_tables, The number of tables. Default is 1."); + HelpPrint("-n ", "num_of_records_per_table, The number of records per table. Default is 1."); + HelpPrint("-c ", "config_directory, Configuration directory. Default is '/etc/taos/'."); + HelpPrint("-x", "flag, Insert only flag."); + HelpPrint("-O", "order, Insert mode--0: In order, 1: Out of order. Default is in order."); + HelpPrint("-R ", "rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50."); + HelpPrint("-D ", "Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database."); + HelpPrint("-v", "Print verbose output"); + HelpPrint("-g", "Print debug output"); + HelpPrint("-y", "Skip read key for continous test, default is not skip"); + + System.Environment.Exit(0); + } + } + } + + public void ReadArgument(String[] argv) + { + host = this.GetArgumentAsString(argv, "-h", "127.0.0.1"); + port = (short)this.GetArgumentAsLong(argv, "-p", 0, 65535, 6030); + user = this.GetArgumentAsString(argv, "-u", "root"); + password = this.GetArgumentAsString(argv, "-P", "taosdata"); + dbName = this.GetArgumentAsString(argv, "-d", "taosdemo_cs"); + stablePrefix = this.GetArgumentAsString(argv, "-s", "st"); + tablePrefix = this.GetArgumentAsString(argv, "-m", "t"); + isInsertOnly = this.GetArgumentAsFlag(argv, "-x", true); + query = this.GetArgumentAsString(argv, "-Q", "NONE"); + queryMode = (short)this.GetArgumentAsLong(argv, "-q", 0, 1, 0); + numOfTables = this.GetArgumentAsLong(argv, "-t", 1, 1000000000, 1); + batchRows = this.GetArgumentAsLong(argv, "-r", 1, 10000, 1000); + recordsPerTable = this.GetArgumentAsLong(argv, "-n", 1, 100000000000, 1); + recordsPerRequest = (int)this.GetArgumentAsLong(argv, "-r", 1, 10000, 1); + colsPerRecord = (int)this.GetArgumentAsLong(argv, "-l", 1, 1024, 3); + configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg"); + useStable = this.GetArgumentAsFlag(argv, "-M", true); + + replica = (short)this.GetArgumentAsLong(argv, "-a", 1, 5, 1); + methodOfDelete = (short)this.GetArgumentAsLong(argv, "-D", 0, 3, 0); + numOfThreads = (short)this.GetArgumentAsLong(argv, "-T", 1, 10000, 1); + order = this.GetArgumentAsFlag(argv, "-O", false); + rateOfOutorder = (short)this.GetArgumentAsLong(argv, "-R", 0, 50, 10); + + skipReadKey = this.GetArgumentAsFlag(argv, "-y", true); + verbose = this.GetArgumentAsFlag(argv, "-v", true); + debug = this.GetArgumentAsFlag(argv, "-g", true); + + VerbosePrint("###################################################################\n"); + VerbosePrintFormat("# Server IP: {0}\n", host); + VerbosePrintFormat("# User: {0}\n", user); + VerbosePrintFormat("# Password: {0}\n", password); + VerbosePrintFormat("# Number of Columns per record: {0}\n", colsPerRecord); + VerbosePrintFormat("# Number of Threads: {0}\n", numOfThreads); + VerbosePrintFormat("# Number of Tables: {0}\n", numOfTables); + VerbosePrintFormat("# Number of records per Table: {0}\n", recordsPerTable); + VerbosePrintFormat("# Records/Request: {0}\n", recordsPerRequest); + VerbosePrintFormat("# Database name: {0}\n", dbName); + VerbosePrintFormat("# Replica: {0}\n", replica); + VerbosePrintFormat("# Use STable: {0}\n", useStable); + VerbosePrintFormat("# Table prefix: {0}\n", tablePrefix); + if (useStable == true) + { + VerbosePrintFormat("# STable prefix: {0}\n", stablePrefix); + } + VerbosePrintFormat("# Data order: {0}\n", order); + VerbosePrintFormat("# Data out of order rate: {0}\n", rateOfOutorder); + VerbosePrintFormat("# Delete method: {0}\n", methodOfDelete); + VerbosePrintFormat("# Query command: {0}\n", query); + VerbosePrintFormat("# Query Mode: {0}\n", queryMode); + VerbosePrintFormat("# Insert Only: {0}\n", isInsertOnly); + VerbosePrintFormat("# Verbose output {0}\n", verbose); + VerbosePrintFormat("# Test time: {0}\n", DateTime.Now.ToString("h:mm:ss tt")); + + VerbosePrint("###################################################################\n"); + + if (skipReadKey == false) + { + Console.Write("Press any key to continue..\n"); + Console.ReadKey(); + } + } + + public bool GetArgumentAsFlag(String[] argv, String argName, bool defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName == argv[i]) + { + return defaultValue; + } + } + return !defaultValue; + } + + public long GetArgumentAsLong(String[] argv, String argName, int minVal, long maxVal, int defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", argName); + ExitProgram(1); + } + + long tmpVal = Convert.ToInt64(tmp); + if (tmpVal < minVal || tmpVal > maxVal) + { + Console.WriteLine("option {0:G} value should in range [{1:G}, {2:G}]", argName, minVal, maxVal); + ExitProgram(1); + } + + return tmpVal; + } + } + + return defaultValue; + } + + public String GetArgumentAsString(String[] argv, String argName, String defaultValue) + { + int argc = argv.Length; + for (int i = 0; i < argc; ++i) + { + if (argName != argv[i]) + { + continue; + } + if (i < argc - 1) + { + String tmp = argv[i + 1]; + if (tmp[0] == '-') + { + Console.WriteLine("option {0:G} requires an argument", argName); + ExitProgram(1); + } + return tmp; + } + } + + return defaultValue; + } + + static void CleanAndExitProgram(int ret) + { + TDengine.Cleanup(); + System.Environment.Exit(ret); + } + + static void ExitProgram(int ret) + { + System.Environment.Exit(ret); + } + + private void VerbosePrintFormat(string format, params object[] parameters) + { + if (verbose == true) + { + Console.Write(format, parameters); + } + } + + private void VerbosePrint(string str) + { + if (verbose == true) + { + Console.Write(str); + } + } + + private void DebugPrintFormat(string format, params object[] parameters) + { + if (debug == true) + { + Console.Write(format, parameters); + } + } + + private void DebugPrint(string str) + { + if (debug == true) + { + Console.Write(str); + } + } + + public void InitTDengine() + { + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir); + TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60"); + TDengine.Init(); + VerbosePrint("TDengine Initialization finished\n"); + } + + public void ConnectTDengine() + { + string db = ""; + VerbosePrintFormat("host:{0} user:{1}, pass:{2}; db:{3}, port:{4}\n", + this.host, this.user, this.password, db, this.port); + this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port); + if (this.conn == IntPtr.Zero) + { + Console.WriteLine("Connect to TDengine failed"); + CleanAndExitProgram(1); + } + else + { + VerbosePrint("Connect to TDengine success\n"); + } + } + + public void CreateTablesByThreads() + { + Thread[] threadArr = new Thread[numOfThreads]; + + long quotition = numOfTables / numOfThreads; + if (quotition < 1) + { + numOfThreads = numOfTables; + quotition = 1; + } + + long remainder = 0; + if (numOfThreads != 0) + { + remainder = numOfTables % numOfThreads; + } + + long last = 0; + + for (int i = 0; i < numOfThreads; i++) + { + CreateTableThread createTableThread = new CreateTableThread(); + createTableThread.id = i; + createTableThread.verbose = verbose; + createTableThread.debug = debug; + createTableThread.dbName = this.dbName; + createTableThread.tablePrefix = this.tablePrefix; + createTableThread.useStable = useStable; + if (useStable) + { + createTableThread.stablePrefix = stablePrefix; + } + createTableThread.conn = conn; + + createTableThread.start = last; + if (i < remainder) + { + createTableThread.end = last + quotition; + } + else + { + createTableThread.end = last + quotition - 1; + } + last = createTableThread.end + 1; + + threadArr[i] = new Thread(createTableThread.ThreadMain); + threadArr[i].Start(); + } + for (int j = 0; j < numOfThreads; j++) + { + threadArr[j].Join(); + } + } + + public void dropDatabase() + { + StringBuilder sql = new StringBuilder(); + sql.Append("DROP DATABASE IF EXISTS ").Append(this.dbName); + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + CleanAndExitProgram(1); + } + else + { + VerbosePrint(sql.ToString() + " success\n"); + } + } + + public void CreateDb() + { + StringBuilder sql = new StringBuilder(); + sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName).Append(" replica ").Append(this.replica).Append(" keep 36500"); + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + CleanAndExitProgram(1); + } + else + { + VerbosePrint(sql.ToString() + " success\n"); + } + TDengine.FreeResult(res); + } + + public void CreateStable() + { + StringBuilder sql = new StringBuilder(); + + sql.Clear(); + sql.Append("CREATE TABLE IF NOT EXISTS "). + Append(this.dbName).Append(".").Append(this.stablePrefix). + Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned) tags(t1 int)"); + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + CleanAndExitProgram(1); + } + else + { + VerbosePrint(sql.ToString() + " success\n"); + } + TDengine.FreeResult(res); + } + + public void InsertByThreads() + { + Thread[] threadArr = new Thread[numOfThreads]; + + long quotition = numOfTables / numOfThreads; + if (quotition < 1) + { + numOfThreads = numOfTables; + quotition = 1; + } + + long remainder = 0; + if (numOfThreads != 0) + { + remainder = numOfTables % numOfThreads; + } + + long last = 0; + + for (int i = 0; i < numOfThreads; i++) + { + InsertDataThread insertThread = new InsertDataThread(); + insertThread.id = i; + insertThread.recordsPerTable = recordsPerTable; + insertThread.batchRows = batchRows; + insertThread.numOfTables = numOfTables; + insertThread.verbose = verbose; + insertThread.debug = debug; + insertThread.dbName = this.dbName; + insertThread.tablePrefix = this.tablePrefix; + insertThread.order = this.order; + insertThread.rateOfOutorder = this.rateOfOutorder; + if (useStable) + { + insertThread.stablePrefix = stablePrefix; + } + insertThread.conn = conn; + + insertThread.start = last; + if (i < remainder) + { + insertThread.end = last + quotition; + } + else + { + insertThread.end = last + quotition - 1; + } + last = insertThread.end + 1; + + threadArr[i] = new Thread(insertThread.ThreadMain); + threadArr[i].Start(); + } + for (int j = 0; j < numOfThreads; j++) + { + threadArr[j].Join(); + } + } + + public void ExecuteQuery() + { + long queryRows = 0; + + for (int i = 0; i < this.numOfTables; ++i) + { + string sql; + + if (query == "DEFAULT") + { + sql = "select * from " + this.dbName + "." + tablePrefix + i; + } + else + { + sql = query; + } + DebugPrintFormat("query: {0}, sql:{1}\n", query, sql); + + IntPtr res = TDengine.Query(conn, sql); + DebugPrintFormat("res: {0}\n", res); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + CleanAndExitProgram(1); + } + + int fieldCount = TDengine.FieldCount(res); + DebugPrint("field count: " + fieldCount + "\n"); + + List metas = TDengine.FetchFields(res); + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + DebugPrint("index:" + j + ", type:" + meta.type + ", typename:" + meta.TypeName() + ", name:" + meta.name + ", size:" + meta.size + "\n"); + } + + IntPtr rowdata; + StringBuilder builder = new StringBuilder(); + + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + builder.Append(" | "); + + if (data == IntPtr.Zero) + { + builder.Append("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + builder.Append(v1); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + sbyte v2 = (sbyte)Marshal.ReadByte(data); + builder.Append(v2); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + builder.Append(v3); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + builder.Append(v4); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + builder.Append(v5); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + builder.Append(v6); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + builder.Append(v7); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data); + builder.Append(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + builder.Append(v9); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data); + builder.Append(v10); + break; + case TDengineDataType.TSDB_DATA_TYPE_UTINYINT: + byte v11 = Marshal.ReadByte(data); + builder.Append(v11); + break; + case TDengineDataType.TSDB_DATA_TYPE_USMALLINT: + ushort v12 = (ushort)Marshal.ReadInt16(data); + builder.Append(v12); + break; + case TDengineDataType.TSDB_DATA_TYPE_UINT: + uint v13 = (uint)Marshal.ReadInt32(data); + builder.Append(v13); + break; + case TDengineDataType.TSDB_DATA_TYPE_UBIGINT: + ulong v14 = (ulong)Marshal.ReadInt64(data); + builder.Append(v14); + break; + } + } + builder.Append(" | "); + + VerbosePrint(builder.ToString() + "\n"); + builder.Clear(); + } + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", + TDengine.ErrorNo(res), TDengine.Error(res)); + } + + TDengine.FreeResult(res); + } + } + + public void CloseConnection() + { + if (this.conn != IntPtr.Zero) + { + TDengine.Close(this.conn); + } + } + + // Main entry + static void Main(string[] args) + { + PrintHelp(args); + + TDengineTest tester = new TDengineTest(); + tester.ReadArgument(args); + + tester.InitTDengine(); + tester.ConnectTDengine(); + + if (tester.isInsertOnly == false) + { + tester.dropDatabase(); + tester.CreateDb(); + + + if (tester.useStable == true) + { + tester.CreateStable(); + } + + tester.CreateTablesByThreads(); + } + + Stopwatch watch = Stopwatch.StartNew(); + tester.InsertByThreads(); + watch.Stop(); + double elapsedMs = watch.Elapsed.TotalMilliseconds; + + Console.WriteLine("C# taosdemo: Spent {0} seconds to insert {1} records with {2} record(s) per request: {3} records/second", + elapsedMs / 1000, + tester.recordsPerTable * tester.numOfTables, + tester.batchRows, + (tester.recordsPerTable * tester.numOfTables * 1000) / elapsedMs); + + tester.DebugPrintFormat("query command:{0}\n", tester.query); + if (tester.query != "NONE") + { + watch = Stopwatch.StartNew(); + tester.ExecuteQuery(); + watch.Stop(); + elapsedMs = watch.Elapsed.TotalMilliseconds; + Console.WriteLine("C# taosdemo: Spent {0} seconds to query {1} records.\n", + elapsedMs / 1000, + tester.recordsPerTable * tester.numOfTables + ); + } + tester.CloseConnection(); + + Console.WriteLine("End."); + CleanAndExitProgram(0); + } + + public class InsertDataThread + { + public long id { set; get; } + public long start { set; get; } + public long end { set; get; } + public string dbName { set; get; } + public IntPtr conn { set; get; } + public string tablePrefix { set; get; } + public string stablePrefix { set; get; } + public long recordsPerTable { set; get; } + public long batchRows { set; get; } + public long numOfTables { set; get; } + public bool verbose { set; get; } + public bool debug { set; get; } + public bool order { set; get; } + public short rateOfOutorder { set; get; } + + private void VerbosePrintFormat(string format, params object[] parameters) + { + if (verbose == true) + { + Console.Write(format, parameters); + } + } + + private void VerbosePrint(string str) + { + if (verbose == true) + { + Console.Write(str); + } + } + + private void DebugPrintFormat(string format, params object[] parameters) + { + if (debug == true) + { + Console.Write(format, parameters); + } + } + + private void DebugPrint(string str) + { + if (debug == true) + { + Console.Write(str); + } + } + + public void ThreadMain() + { + VerbosePrintFormat("InsertDataThread {0} from {1} to {2}\n", id, start, end); + StringBuilder sql = new StringBuilder(); + + DateTime now = DateTime.Now; + int h = now.Hour; + int m = now.Minute; + int s = now.Second; + + long baseTimestamp = -16094340000; // 1969-06-29 01:21:00 + VerbosePrintFormat("beginTime is {0} + {1}h:{2}m:{3}s\n", baseTimestamp, h, m, s); + long beginTimestamp = baseTimestamp + ((h * 60 + m) * 60 + s) * 1000; + Random random = new Random(); + + long rowsInserted = 0; + + long i = 0; + while (i < recordsPerTable) + { + for (long table = start; table <= end; ++table) + { + long inserted = i; + + sql.Clear(); + sql.Append("INSERT INTO "). + Append(this.dbName).Append(".").Append(this.tablePrefix).Append(table). + Append(" VALUES"); + if (recordsPerTable < batchRows) + { + batchRows = recordsPerTable; + } + for (int batch = 0; batch < batchRows; ++batch) + { + long writeTimeStamp = beginTimestamp + i + batch; + int rnd = 100; + if (this.order == false) + { + rnd = random.Next(1, 100); + if (rnd <= this.rateOfOutorder) + { + writeTimeStamp = writeTimeStamp + rnd * 10000; + DebugPrint("### "); + } + DebugPrintFormat("order:{0} rnd:{1} timestamp:{2}\n", this.order, rnd, writeTimeStamp); + } + else + { + DebugPrintFormat("order:{0} timestamp:{1}\n", this.order, writeTimeStamp); + } + + sql.Append("(") + .Append(writeTimeStamp) + .Append(", 1, -2, -3,") + .Append(i + batch - 127) + .Append(", -5, -6, -7, 'abc', 'def', 254, 65534,") + .Append(4294967294 - (uint)i - (uint)batch) + .Append(",") + .Append(18446744073709551614 - (ulong)i - (ulong)batch) + .Append(")"); + + } + VerbosePrint(sql.ToString() + "\n"); + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + } + + inserted += this.batchRows; + + int affectRows = TDengine.AffectRows(res); + rowsInserted += affectRows; + + TDengine.FreeResult(res); + if (table == end) + { + i = inserted; + } + } + } + + } + } + + public class CreateTableThread + { + public long id { set; get; } + public long start { set; get; } + public long end { set; get; } + public string dbName { set; get; } + public IntPtr conn { set; get; } + public string tablePrefix { set; get; } + public string stablePrefix { set; get; } + public bool verbose { set; get; } + public bool debug { set; get; } + public bool useStable { set; get; } + + private void VerbosePrintFormat(string format, params object[] parameters) + { + if (verbose == true) + { + Console.Write(format, parameters); + } + } + + private void VerbosePrint(string str) + { + if (verbose == true) + { + Console.Write(str); + } + } + + private void DebugPrintFormat(string format, params object[] parameters) + { + if (debug == true) + { + Console.Write(format, parameters); + } + } + + public void ThreadMain() + { + VerbosePrintFormat("CreateTable {0} from {1} to {2}\n", id, start, end); + + StringBuilder sql = new StringBuilder(); + + for (long tableId = start; tableId <= end; tableId++) + { + sql.Clear(); + sql = sql.Append("CREATE TABLE IF NOT EXISTS "). + Append(this.dbName).Append(".").Append(this.tablePrefix).Append(tableId); + if (useStable == true) + { + sql = sql.Append(" USING ").Append(this.dbName).Append(".").Append(this.stablePrefix). + Append(" TAGS(").Append(tableId).Append(")"); + } + else + { + sql = sql.Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned)"); + } + IntPtr res = TDengine.Query(this.conn, sql.ToString()); + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + Console.Write(sql.ToString() + " failure, "); + if (res != IntPtr.Zero) { + Console.Write("reason: " + TDengine.Error(res)); + } + Console.WriteLine(""); + CleanAndExitProgram(1); + } + else + { + VerbosePrint(sql.ToString() + " success\n"); + } + TDengine.FreeResult(res); + } + + } + } + } +} diff --git a/examples/C#/taosdemo/taosdemo.csproj b/examples/C#/taosdemo/taosdemo.csproj new file mode 100644 index 0000000000000000000000000000000000000000..8d4b786ba3a99b600783a5b4ee55d99f03e47655 --- /dev/null +++ b/examples/C#/taosdemo/taosdemo.csproj @@ -0,0 +1,13 @@ + + + + Exe + net5.0 + false + + + + + + + diff --git a/examples/JDBC/JDBCDemo/README-jdbc-windows.md b/examples/JDBC/JDBCDemo/README-jdbc-windows.md new file mode 100644 index 0000000000000000000000000000000000000000..17c5c8df00ab8727d1adfe493d3fbbd32891a676 --- /dev/null +++ b/examples/JDBC/JDBCDemo/README-jdbc-windows.md @@ -0,0 +1,268 @@ +# 如何在 windows环境下使用jdbc进行TDengine应用开发 + +本文以windows环境为例,介绍java如何进行TDengine开发应用 + +## 环境准备 + +(1)安装jdk + +官网下载jdk-1.8,下载页面:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html + +安装,配置环境变量,把jdk加入到环境变量里。 + +命令行内查看java的版本。 + +```shell +>java -version +java version "1.8.0_131" +Java(TM) SE Runtime Environment (build 1.8.0_131-b11) +Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode) +``` + + +(2)安装配置maven + +官网下载maven,下载地址:http://maven.apache.org/download.cgi + +配置环境变量MAVEN_HOME,将MAVEN_HOME/bin添加到PATH + +命令行里查看maven的版本 + +```shell +>mvn --version +Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-04T03:39:06+08:00) +Maven home: D:\apache-maven-3.5.0\bin\.. +Java version: 1.8.0_131, vendor: Oracle Corporation +Java home: C:\Program Files\Java\jdk1.8.0_131\jre +Default locale: zh_CN, platform encoding: GBK +OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows" +``` + +为了加快maven下载依赖的速度,可以为maven配置mirror,修改MAVEN_HOME\config\settings.xml文件 + +```xml + + + D:\apache-maven-localRepository + + + + + alimaven + aliyun maven + http://maven.aliyun.com/nexus/content/groups/public/ + central + + + + + + + jdk-1.8 + + true + 1.8 + + + 1.8 + 1.8 + 1.8 + + + + +``` + + + +(3)在linux服务器上安装TDengine-server + +在taosdata官网下载TDengine-server,下载地址:https://www.taosdata.com/cn/all-downloads/ + +在linux服务器上安装TDengine-server + +```shell +# tar -zxvf package/TDengine-server-2.0.1.1-Linux-x64.tar.gz +# cd TDengine-server/ +# ./install.sh +``` + +启动taosd + +```shell +# systemctl start taosd +``` + +在server上用taos连接taosd + +```shell +# taos +taos> show dnodes; + id | end_point | vnodes | cores | status | role | create_time | +================================================================================================================== + 1 | td01:6030 | 2 | 4 | ready | any | 2020-08-19 18:40:25.045 | +Query OK, 1 row(s) in set (0.005765s) +``` + +如果可以正确连接到taosd实例,并打印出databases的信息,说明TDengine的server已经正确启动。这里查看server的hostname + +```shell +# hostname -f +td01 +``` + +注意,如果安装TDengine后,使用默认的taos.cfg配置文件,taosd会使用当前server的hostname创建dnode实例。之后,在client也需要使用这个hostname来连接taosd。 + + + +(4)在windows上安装TDengine-client + +在taosdata官网下载taos客户端,下载地址: +https://www.taosdata.com/cn/all-downloads/ +下载后,双击exe安装。 + +修改client的hosts文件(C:\Windows\System32\drivers\etc\hosts),将server的hostname和ip配置到client的hosts文件中 + +``` +192.168.236.136 td01 +``` + +配置完成后,在命令行内使用taos shell连接server端 + +```shell +C:\TDengine>taos -h td01 +Welcome to the TDengine shell from Linux, Client Version:2.0.1.1 +Copyright (c) 2017 by TAOS Data, Inc. All rights reserved. + +taos> show databases; + name | created_time | ntables | vgroups | replica | quorum | days | keep0,keep1,keep(D) | cache(MB) | blocks | minrows | maxrows | wallevel | fsync | comp | precision | status | +=================================================================================================================================================================================================================================================================== + test | 2020-08-19 18:43:50.731 | 1 | 1 | 1 | 1 | 2 | 3650,3650,3650 | 16 | 6 | 100 | 4096 | 1 | 3000 | 2 | ms | ready | + log | 2020-08-19 18:40:28.064 | 4 | 1 | 1 | 1 | 10 | 30,30,30 | 1 | 3 | 100 | 4096 | 1 | 3000 | 2 | us | ready | +Query OK, 2 row(s) in set (0.068000s) +``` + +如果windows上的client能够正常连接,并打印database信息,说明client可以正常连接server了。 + + + +## 应用开发 + +(1)新建maven工程,在pom.xml中引入taos-jdbcdriver依赖。 + +```xml + + + 4.0.0 + + com.taosdata.demo + JdbcDemo + 1.0-SNAPSHOT + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.8 + + + +``` + +(2)使用jdbc查询TDengine数据库 + +下面是示例代码: + +```java +public class JdbcDemo { + + public static void main(String[] args) throws Exception { + Connection conn = getConn(); + Statement stmt = conn.createStatement(); + // create database + stmt.executeUpdate("create database if not exists db"); + // use database + stmt.executeUpdate("use db"); + // create table + stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)"); + // insert data + int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)"); + System.out.println("insert " + affectedRows + " rows."); + // query data + ResultSet resultSet = stmt.executeQuery("select * from tb"); + Timestamp ts = null; + int temperature = 0; + float humidity = 0; + while(resultSet.next()){ + ts = resultSet.getTimestamp(1); + temperature = resultSet.getInt(2); + humidity = resultSet.getFloat("humidity"); + System.out.printf("%s, %d, %s\n", ts, temperature, humidity); + } + } + + public static Connection getConn() throws Exception{ + Class.forName("com.taosdata.jdbc.TSDBDriver"); + String jdbcUrl = "jdbc:TAOS://td01:0/log?user=root&password=taosdata"; + Properties connProps = new Properties(); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + Connection conn = DriverManager.getConnection(jdbcUrl, connProps); + return conn; + } + +} +``` + +(3)测试jdbc访问tdengine的sever实例 + +console输出: + +``` +insert 2 rows. +2020-08-26 00:06:34.575, 23, 10.3 +2020-08-26 00:06:35.575, 20, 9.3 +``` + + + +## 指南 + +(1)如何设置主机名和hosts + +在server上查看hostname和fqdn +```shell +查看hostname +# hostname +taos-server + +查看fqdn +# hostname -f +taos-server +``` + +windows下hosts文件位于: +C:\\Windows\System32\drivers\etc\hosts +修改hosts文件,添加server的ip和hostname + +```s +192.168.56.101 node5 +``` + +(2)什么是fqdn? + + +> 什么是FQDN? +> +> FQDN(Full qualified domain name)全限定域名,fqdn由2部分组成:hostname+domainname。 +> +> 例如,一个邮件服务器的fqdn可能是:mymail.somecollege.edu,其中mymail是hostname(主机名),somcollege.edu是domainname(域名)。本例中,.edu是顶级域名,.somecollege是二级域名。 +> +> 当连接服务器时,必须指定fqdn,然后,dns服务器通过查看dns表,将hostname解析为相应的ip地址。如果只指定hostname(不指定domainname),应用程序可能服务解析主机名。因为如果你试图访问不在本地的远程服务器时,本地的dns服务器和可能没有远程服务器的hostname列表。 +> +> 参考:https://kb.iu.edu/d/aiuv diff --git a/examples/JDBC/JDBCDemo/pom.xml b/examples/JDBC/JDBCDemo/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b0b07d58f4e59645e5ebe78a938d0043558a9c80 --- /dev/null +++ b/examples/JDBC/JDBCDemo/pom.xml @@ -0,0 +1,104 @@ + + + 4.0.0 + + com.taosdata.jdbc + JDBCDemo + SNAPSHOT + jar + + + src/main/resources/assembly + + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.36 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + + JdbcDemo + + JdbcDemo + + + com.taosdata.example.JdbcDemo + + + + jar-with-dependencies + + + package + + single + + + + + JdbcRestfulDemo + + JdbcRestfulDemo + + + com.taosdata.example.JdbcRestfulDemo + + + + jar-with-dependencies + + + package + + single + + + + + SubscribeDemo + + SubscribeDemo + + + com.taosdata.example.SubscribeDemo + + + + jar-with-dependencies + + + package + + single + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + UTF-8 + + + + + + + diff --git a/examples/JDBC/JDBCDemo/readme.md b/examples/JDBC/JDBCDemo/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..da638a0bcc485cb3d73f75b59348ec260cc871d2 --- /dev/null +++ b/examples/JDBC/JDBCDemo/readme.md @@ -0,0 +1,37 @@ +# How to Run the JDBC Demo Code On Linux OS +TDengine's JDBC demo project is organized in a Maven way so that users can easily compile, package and run the project. If you don't have Maven on your server, you may install it using +``` +sudo apt-get install maven +``` + +## Install TDengine Client +Make sure you have already installed a tdengine client on your current develop environment. +Download the tdengine package on our website: ``https://www.taosdata.com/cn/all-downloads/`` and install the client. + +## Run jdbcDemo using mvn plugin +run command: +``` +mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo" +``` + +and run with your customed args +``` +mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo" -Dexec.args="-host [HOSTNAME]" +``` + +## Compile the Demo Code and Run It +To compile taos-jdbcdriver, go to the source directory ``TDengine/src/connector/jdbc`` and execute +``` +mvn clean package -Dmaven.test.skip=true +``` + +To compile the demo project, go to the source directory ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute +``` +mvn clean package assembly:single +``` + +To run JDBCDemo.jar, go to ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute +``` +java -Djava.ext.dirs=../../../../src/connector/jdbc/target:$JAVA_HOME/jre/lib/ext -jar target/JDBCDemo-SNAPSHOT-jar-with-dependencies.jar -host [HOSTNAME] +``` + diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/BatchInsert.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/BatchInsert.java new file mode 100644 index 0000000000000000000000000000000000000000..a2566bd07e96ddd245c9b548a3192d0e4f343147 --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/BatchInsert.java @@ -0,0 +1,87 @@ +package com.taosdata.example; + +import java.sql.*; +import java.util.*; + +public class BatchInsert { + + private static final String host = "127.0.0.1"; + private static final String user = "root"; + private static final String password = "taosdata"; + + + private static final String dbname = "test"; + private static final String stbname = "stb"; + private static final int tables= 100; + private static final int rows = 500; + private static final long ts = 1604877767000l; + + private Connection conn; + + private void init() { + // final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password; + final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=" + user + "&password=" + password; + + // get connection + try { + Properties properties = new Properties(); + properties.setProperty("charset", "UTF-8"); + properties.setProperty("locale", "en_US.UTF-8"); + properties.setProperty("timezone", "UTC-8"); + System.out.println("get connection starting..."); + conn = DriverManager.getConnection(url, properties); + if (conn != null){ + System.out.println("[ OK ] Connection established."); + } + + Statement stmt = conn.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table " + dbname + "." + stbname + "(ts timestamp, col int) tags(id int)"); + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private String generateSql() { + StringBuilder sb = new StringBuilder(); + Random rand = new Random(); + sb.append("insert into "); + for (int i = 0; i < tables; i++) { + sb.append(dbname + ".tb" + i + " using " + dbname + "." + stbname + " tags(" + i + ") values"); + for (int j = 0; j < rows; j++) { + sb.append("("); + sb.append(ts + j); + sb.append(","); + sb.append(rand.nextInt(1000)); + sb.append(") "); + } + } + return sb.toString(); + } + + private void executeQuery(String sql) { + try (Statement stmt = conn.createStatement()) { + long start = System.currentTimeMillis(); + stmt.execute(sql); + long end = System.currentTimeMillis(); + + System.out.println("insert " + tables * rows + " records, cost " + (end - start)+ "ms"); + } catch (SQLException ex) { + ex.printStackTrace(); + } + } + + public static void main(String[] args) { + BatchInsert bi = new BatchInsert(); + + String sql = bi.generateSql(); + bi.init(); + bi.executeQuery(sql); + } + + +} diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ClientParameterSetting.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ClientParameterSetting.java new file mode 100644 index 0000000000000000000000000000000000000000..09fb8f1b19f069305464a52df15f748d29ddd5d8 --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ClientParameterSetting.java @@ -0,0 +1,54 @@ +package com.taosdata.example; + +import com.taosdata.jdbc.TSDBDriver; + +import java.sql.*; +import java.util.Properties; + +public class ClientParameterSetting { + private static final String host = "127.0.0.1"; + + public static void main(String[] args) throws SQLException { + setParameterInJdbcUrl(); + + setParameterInProperties(); + } + + private static void setParameterInJdbcUrl() throws SQLException { + String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?debugFlag=135&asyncLog=0"; + + Connection connection = DriverManager.getConnection(jdbcUrl, "root", "taosdata"); + + printDatabase(connection); + + connection.close(); + } + + private static void setParameterInProperties() throws SQLException { + String jdbcUrl = "jdbc:TAOS://" + host + ":6030/"; + Properties properties = new Properties(); + properties.setProperty("user", "root"); + properties.setProperty("password", "taosdata"); + properties.setProperty("debugFlag", "135"); + properties.setProperty("asyncLog", "0"); + properties.setProperty("maxSQLLength", "1048576"); + + try (Connection conn = DriverManager.getConnection(jdbcUrl, properties)) { + printDatabase(conn); + } + } + + private static void printDatabase(Connection connection) throws SQLException { + try (Statement stmt = connection.createStatement()) { + ResultSet rs = stmt.executeQuery("show databases"); + + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + } + } + } +} diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcDemo.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..5bc23403087578c0791b0a5e6fca74a47aad8184 --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcDemo.java @@ -0,0 +1,141 @@ +package com.taosdata.example; + +import java.sql.*; +import java.util.Properties; + +public class JdbcDemo { + private static String host; + private static final String dbName = "test"; + private static final String tbName = "weather"; + private static final String user = "root"; + private static final String password = "taosdata"; + + private Connection connection; + + public static void main(String[] args) { + for (int i = 0; i < args.length; i++) { + if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) + host = args[++i]; + } + if (host == null) { + printHelp(); + } + JdbcDemo demo = new JdbcDemo(); + demo.init(); + demo.createDatabase(); + demo.useDatabase(); + demo.dropTable(); + demo.createTable(); + demo.insert(); + demo.select(); + demo.dropTable(); + demo.close(); + } + + private void init() { + final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password; + // get connection + try { + Properties properties = new Properties(); + properties.setProperty("charset", "UTF-8"); + properties.setProperty("locale", "en_US.UTF-8"); + properties.setProperty("timezone", "UTC-8"); + System.out.println("get connection starting..."); + connection = DriverManager.getConnection(url, properties); + if (connection != null) + System.out.println("[ OK ] Connection established."); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void createDatabase() { + String sql = "create database if not exists " + dbName; + exuete(sql); + } + + private void useDatabase() { + String sql = "use " + dbName; + exuete(sql); + } + + private void dropTable() { + final String sql = "drop table if exists " + dbName + "." + tbName + ""; + exuete(sql); + } + + private void createTable() { + final String sql = "create table if not exists " + dbName + "." + tbName + " (ts timestamp, temperature float, humidity int)"; + exuete(sql); + } + + private void insert() { + final String sql = "insert into " + dbName + "." + tbName + " (ts, temperature, humidity) values(now, 20.5, 34)"; + exuete(sql); + } + + private void select() { + final String sql = "select * from " + dbName + "." + tbName; + executeQuery(sql); + } + + private void close() { + try { + if (connection != null) { + this.connection.close(); + System.out.println("connection closed."); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void executeQuery(String sql) { + long start = System.currentTimeMillis(); + try (Statement statement = connection.createStatement()) { + ResultSet resultSet = statement.executeQuery(sql); + long end = System.currentTimeMillis(); + printSql(sql, true, (end - start)); + printResult(resultSet); + } catch (SQLException e) { + long end = System.currentTimeMillis(); + printSql(sql, false, (end - start)); + e.printStackTrace(); + } + } + + private void printResult(ResultSet resultSet) throws SQLException { + ResultSetMetaData metaData = resultSet.getMetaData(); + while (resultSet.next()) { + for (int i = 1; i <= metaData.getColumnCount(); i++) { + String columnLabel = metaData.getColumnLabel(i); + String value = resultSet.getString(i); + System.out.printf("%s: %s\t", columnLabel, value); + } + System.out.println(); + } + } + + private void printSql(String sql, boolean succeed, long cost) { + System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); + } + + private void exuete(String sql) { + long start = System.currentTimeMillis(); + try (Statement statement = connection.createStatement()) { + boolean execute = statement.execute(sql); + long end = System.currentTimeMillis(); + printSql(sql, true, (end - start)); + } catch (SQLException e) { + long end = System.currentTimeMillis(); + printSql(sql, false, (end - start)); + e.printStackTrace(); + } + } + + private static void printHelp() { + System.out.println("Usage: java -jar JDBCDemo.jar -host "); + System.exit(0); + } + +} diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcRestfulDemo.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcRestfulDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..d89476b8ca718dab24202e2320e842366533a763 --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcRestfulDemo.java @@ -0,0 +1,46 @@ +package com.taosdata.example; + +import java.sql.*; +import java.util.Properties; + +public class JdbcRestfulDemo { + private static final String host = "localhost"; + private static final String dbname = "test"; + private static final String user = "root"; + private static final String password = "taosdata"; + + public static void main(String[] args) { + try { + // use port 6041 in url when use JDBC-restful + String url = "jdbc:TAOS-RS://" + host + ":6041/?user=" + user + "&password=" + password; + + Properties properties = new Properties(); + properties.setProperty("charset", "UTF-8"); + properties.setProperty("locale", "en_US.UTF-8"); + properties.setProperty("timezone", "UTC-8"); + + Connection conn = DriverManager.getConnection(url, properties); + Statement stmt = conn.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table " + dbname + ".weather(ts timestamp, temperature float) tags(location nchar(64))"); + stmt.executeUpdate("insert into t1 using " + dbname + ".weather tags('北京') values(now, 18.2)"); + ResultSet rs = stmt.executeQuery("select * from " + dbname + ".weather"); + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + } + + rs.close(); + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ParameterBindingDemo.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ParameterBindingDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..726b57b1465f678d703f0dc9c524f92b856e034e --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ParameterBindingDemo.java @@ -0,0 +1,237 @@ +package com.taosdata.example; + +import com.taosdata.jdbc.TSDBPreparedStatement; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Random; + +public class ParameterBindingDemo { + + private static final String host = "127.0.0.1"; + private static final Random random = new Random(System.currentTimeMillis()); + private static final int BINARY_COLUMN_SIZE = 20; + private static final String[] schemaList = { + "create table stable1(ts timestamp, f1 tinyint, f2 smallint, f3 int, f4 bigint) tags(t1 tinyint, t2 smallint, t3 int, t4 bigint)", + "create table stable2(ts timestamp, f1 float, f2 double) tags(t1 float, t2 double)", + "create table stable3(ts timestamp, f1 bool) tags(t1 bool)", + "create table stable4(ts timestamp, f1 binary(" + BINARY_COLUMN_SIZE + ")) tags(t1 binary(" + BINARY_COLUMN_SIZE + "))", + "create table stable5(ts timestamp, f1 nchar(" + BINARY_COLUMN_SIZE + ")) tags(t1 nchar(" + BINARY_COLUMN_SIZE + "))" + }; + private static final int numOfSubTable = 10, numOfRow = 10; + + public static void main(String[] args) throws SQLException { + + String jdbcUrl = "jdbc:TAOS://" + host + ":6030/"; + Connection conn = DriverManager.getConnection(jdbcUrl, "root", "taosdata"); + + init(conn); + + bindInteger(conn); + + bindFloat(conn); + + bindBoolean(conn); + + bindBytes(conn); + + bindString(conn); + + conn.close(); + } + + private static void init(Connection conn) throws SQLException { + try (Statement stmt = conn.createStatement()) { + stmt.execute("drop database if exists test_parabind"); + stmt.execute("create database if not exists test_parabind"); + stmt.execute("use test_parabind"); + for (int i = 0; i < schemaList.length; i++) { + stmt.execute(schemaList[i]); + } + } + } + + private static void bindInteger(Connection conn) throws SQLException { + String sql = "insert into ? using stable1 tags(?,?,?,?) values(?,?,?,?,?)"; + + try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) { + + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("t1_" + i); + // set tags + pstmt.setTagByte(0, Byte.parseByte(Integer.toString(random.nextInt(Byte.MAX_VALUE)))); + pstmt.setTagShort(1, Short.parseShort(Integer.toString(random.nextInt(Short.MAX_VALUE)))); + pstmt.setTagInt(2, random.nextInt(Integer.MAX_VALUE)); + pstmt.setTagLong(3, random.nextLong()); + // set columns + ArrayList tsList = new ArrayList<>(); + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) + tsList.add(current + j); + pstmt.setTimestamp(0, tsList); + + ArrayList f1List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f1List.add(Byte.parseByte(Integer.toString(random.nextInt(Byte.MAX_VALUE)))); + pstmt.setByte(1, f1List); + + ArrayList f2List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f2List.add(Short.parseShort(Integer.toString(random.nextInt(Short.MAX_VALUE)))); + pstmt.setShort(2, f2List); + + ArrayList f3List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f3List.add(random.nextInt(Integer.MAX_VALUE)); + pstmt.setInt(3, f3List); + + ArrayList f4List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f4List.add(random.nextLong()); + pstmt.setLong(4, f4List); + + // add column + pstmt.columnDataAddBatch(); + } + // execute column + pstmt.columnDataExecuteBatch(); + } + + } + + private static void bindFloat(Connection conn) throws SQLException { + String sql = "insert into ? using stable2 tags(?,?) values(?,?,?)"; + + TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class); + + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("t2_" + i); + // set tags + pstmt.setTagFloat(0, random.nextFloat()); + pstmt.setTagDouble(1, random.nextDouble()); + // set columns + ArrayList tsList = new ArrayList<>(); + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) + tsList.add(current + j); + pstmt.setTimestamp(0, tsList); + + ArrayList f1List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f1List.add(random.nextFloat()); + pstmt.setFloat(1, f1List); + + ArrayList f2List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f2List.add(random.nextDouble()); + pstmt.setDouble(2, f2List); + + // add column + pstmt.columnDataAddBatch(); + } + // execute + pstmt.columnDataExecuteBatch(); + // close if no try-with-catch statement is used + pstmt.close(); + } + + private static void bindBoolean(Connection conn) throws SQLException { + String sql = "insert into ? using stable3 tags(?) values(?,?)"; + + try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) { + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("t3_" + i); + // set tags + pstmt.setTagBoolean(0, random.nextBoolean()); + // set columns + ArrayList tsList = new ArrayList<>(); + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) + tsList.add(current + j); + pstmt.setTimestamp(0, tsList); + + ArrayList f1List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) + f1List.add(random.nextBoolean()); + pstmt.setBoolean(1, f1List); + + // add column + pstmt.columnDataAddBatch(); + } + // execute + pstmt.columnDataExecuteBatch(); + } + } + + private static void bindBytes(Connection conn) throws SQLException { + String sql = "insert into ? using stable4 tags(?) values(?,?)"; + + try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) { + + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("t4_" + i); + // set tags + pstmt.setTagString(0, new String("abc")); + + // set columns + ArrayList tsList = new ArrayList<>(); + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) + tsList.add(current + j); + pstmt.setTimestamp(0, tsList); + + ArrayList f1List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) { + f1List.add(new String("abc")); + } + pstmt.setString(1, f1List, BINARY_COLUMN_SIZE); + + // add column + pstmt.columnDataAddBatch(); + } + // execute + pstmt.columnDataExecuteBatch(); + } + } + + private static void bindString(Connection conn) throws SQLException { + String sql = "insert into ? using stable5 tags(?) values(?,?)"; + + try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) { + + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("t5_" + i); + // set tags + pstmt.setTagNString(0, "北京-abc"); + + // set columns + ArrayList tsList = new ArrayList<>(); + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) + tsList.add(current + j); + pstmt.setTimestamp(0, tsList); + + ArrayList f1List = new ArrayList<>(); + for (int j = 0; j < numOfRow; j++) { + f1List.add("北京-abc"); + } + pstmt.setNString(1, f1List, BINARY_COLUMN_SIZE); + + // add column + pstmt.columnDataAddBatch(); + } + // execute + pstmt.columnDataExecuteBatch(); + } + } + + +} diff --git a/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SubscribeDemo.java b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SubscribeDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..4c499b0b3abb518b48b222eca9bbbcb388bd2008 --- /dev/null +++ b/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SubscribeDemo.java @@ -0,0 +1,74 @@ +package com.taosdata.example; + +import com.taosdata.jdbc.TSDBConnection; +import com.taosdata.jdbc.TSDBDriver; +import com.taosdata.jdbc.TSDBResultSet; +import com.taosdata.jdbc.TSDBSubscribe; + +import java.sql.DriverManager; +import java.sql.ResultSetMetaData; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +public class SubscribeDemo { + private static final String usage = "java -jar SubscribeDemo.jar -host -database -topic -sql "; + + public static void main(String[] args) { + // parse args from command line + String host = "", database = "", topic = "", sql = ""; + for (int i = 0; i < args.length; i++) { + if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) { + host = args[++i]; + } + if ("-database".equalsIgnoreCase(args[i]) && i < args.length - 1) { + database = args[++i]; + } + if ("-topic".equalsIgnoreCase(args[i]) && i < args.length - 1) { + topic = args[++i]; + } + if ("-sql".equalsIgnoreCase(args[i]) && i < args.length - 1) { + sql = args[++i]; + } + } + if (host.isEmpty() || database.isEmpty() || topic.isEmpty() || sql.isEmpty()) { + System.out.println(usage); + return; + } + + try { + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + final String url = "jdbc:TAOS://" + host + ":6030/" + database + "?user=root&password=taosdata"; + // get TSDBConnection + TSDBConnection connection = (TSDBConnection) DriverManager.getConnection(url, properties); + // create TSDBSubscribe + TSDBSubscribe sub = connection.subscribe(topic, sql, false); + + int total = 0; + while (true) { + TSDBResultSet rs = sub.consume(); + int count = 0; + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + count++; + } + total += count; +// System.out.printf("%d rows consumed, total %d\n", count, total); + if (total >= 10) + break; + TimeUnit.SECONDS.sleep(1); + } + sub.close(false); + connection.close(); + } catch (Exception e) { + System.out.println("host: " + host + ", database: " + database + ", topic: " + topic + ", sql: " + sql); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/examples/JDBC/SpringJdbcTemplate/.gitignore b/examples/JDBC/SpringJdbcTemplate/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..175de5c653d2f49b2ad1227764e60f741110592d --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +.mvn/ +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/examples/JDBC/SpringJdbcTemplate/pom.xml b/examples/JDBC/SpringJdbcTemplate/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..eac3dec0a92a4c8aa519cd426b9c8d3895047be6 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/pom.xml @@ -0,0 +1,91 @@ + + + + 4.0.0 + + com.taosdata.jdbc + SpringJdbcTemplate + 1.0-SNAPSHOT + + SpringJdbcTemplate + http://www.taosdata.com + + + UTF-8 + 1.8 + 1.8 + + + + + + org.springframework + spring-context + 5.2.8.RELEASE + + + + org.springframework + spring-jdbc + 5.1.9.RELEASE + + + + org.springframework + spring-test + 5.1.9.RELEASE + + + + junit + junit + 4.13.1 + test + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.18 + + + + + + + + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + com.taosdata.example.jdbcTemplate.App + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + diff --git a/examples/JDBC/SpringJdbcTemplate/readme.md b/examples/JDBC/SpringJdbcTemplate/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..b70a6565f88d0a08b8a26a60676e729ecdb39e2e --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/readme.md @@ -0,0 +1,32 @@ + +## TDengine Spring JDBC Template Demo + +`Spring JDBC Template` 简化了原生 JDBC Connection 获取释放等操作,使得操作数据库更加方便。 + +### 配置 + +修改 `src/main/resources/applicationContext.xml` 文件中 TDengine 的配置信息: + +```xml + + + + + + + + + + +``` + +### 打包运行 + +进入 `TDengine/tests/examples/JDBC/SpringJdbcTemplate` 目录下,执行以下命令可以生成可执行 jar 包。 +```shell +mvn clean package +``` +打包成功之后,进入 `target/` 目录下,执行以下命令就可运行测试: +```shell +java -jar SpringJdbcTemplate-1.0-SNAPSHOT-jar-with-dependencies.jar +``` \ No newline at end of file diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/App.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/App.java new file mode 100644 index 0000000000000000000000000000000000000000..6942d62a83adafb85496a81ce93866cd0d53611d --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/App.java @@ -0,0 +1,48 @@ +package com.taosdata.example.jdbcTemplate; + + +import com.taosdata.example.jdbcTemplate.dao.ExecuteAsStatement; +import com.taosdata.example.jdbcTemplate.dao.WeatherDao; +import com.taosdata.example.jdbcTemplate.domain.Weather; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; +import java.util.Random; + +public class App { + + private static Random random = new Random(System.currentTimeMillis()); + + public static void main(String[] args) { + + ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); + + ExecuteAsStatement executor = ctx.getBean(ExecuteAsStatement.class); + // drop database + executor.doExecute("drop database if exists test"); + // create database + executor.doExecute("create database if not exists test"); + //use database + executor.doExecute("use test"); + // create table + executor.doExecute("create table if not exists test.weather (ts timestamp, temperature int, humidity float)"); + + WeatherDao weatherDao = ctx.getBean(WeatherDao.class); + Weather weather = new Weather(new Timestamp(new Date().getTime()), random.nextFloat() * 50.0f, random.nextInt(100)); + // insert rows + int affectedRows = weatherDao.add(weather); + System.out.println("insert success " + affectedRows + " rows."); + + // query for list + int limit = 10, offset = 0; + List weatherList = weatherDao.queryForList(limit, offset); + for (Weather w : weatherList) { + System.out.println(w); + } + + } + +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatement.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatement.java new file mode 100644 index 0000000000000000000000000000000000000000..5947438e408b3b359b138bf989477f60fc327404 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatement.java @@ -0,0 +1,6 @@ +package com.taosdata.example.jdbcTemplate.dao; + +public interface ExecuteAsStatement{ + + void doExecute(String sql); +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatementImpl.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatementImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..059e3dda15ea36bcaad4309a434a06f020d0301b --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/ExecuteAsStatementImpl.java @@ -0,0 +1,18 @@ +package com.taosdata.example.jdbcTemplate.dao; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + + +@Repository +public class ExecuteAsStatementImpl implements ExecuteAsStatement { + + @Autowired + private JdbcTemplate jdbcTemplate; + + @Override + public void doExecute(String sql) { + jdbcTemplate.execute(sql); + } +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDao.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDao.java new file mode 100644 index 0000000000000000000000000000000000000000..19a07597f8df869dada4e258c4951f67132107a0 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDao.java @@ -0,0 +1,17 @@ +package com.taosdata.example.jdbcTemplate.dao; + +import com.taosdata.example.jdbcTemplate.domain.Weather; + +import java.util.List; + +public interface WeatherDao { + + + int add(Weather weather); + + int[] batchInsert(List weatherList); + + List queryForList(int limit, int offset); + + int count(); +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDaoImpl.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDaoImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8d4ca47d5ee5d351a48bcc1554531566116f5a52 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/dao/WeatherDaoImpl.java @@ -0,0 +1,60 @@ +package com.taosdata.example.jdbcTemplate.dao; + +import com.taosdata.example.jdbcTemplate.domain.Weather; +import com.taosdata.example.jdbcTemplate.dao.WeatherDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.List; + +@Repository +public class WeatherDaoImpl implements WeatherDao { + + @Autowired + private JdbcTemplate jdbcTemplate; + + @Override + public int add(Weather weather) { + return jdbcTemplate.update( + "insert into test.weather(ts, temperature, humidity) VALUES(?,?,?)", + weather.getTs(), weather.getTemperature(), weather.getHumidity() + ); + } + + @Override + public int[] batchInsert(List weatherList) { + return jdbcTemplate.batchUpdate("insert into test.weather(ts, temperature, humidity) values( ?, ?, ?)", new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + ps.setTimestamp(1, weatherList.get(i).getTs()); + ps.setFloat(2, weatherList.get(i).getTemperature()); + ps.setInt(3, weatherList.get(i).getHumidity()); + } + + @Override + public int getBatchSize() { + return weatherList.size(); + } + }); + } + + @Override + public List queryForList(int limit, int offset) { + return jdbcTemplate.query("select * from test.weather limit ? offset ?", (rs, rowNum) -> { + Timestamp ts = rs.getTimestamp("ts"); + float temperature = rs.getFloat("temperature"); + int humidity = rs.getInt("humidity"); + return new Weather(ts, temperature, humidity); + }, limit, offset); + } + + @Override + public int count() { + return jdbcTemplate.queryForObject("select count(*) from test.weather", Integer.class); + } +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/domain/Weather.java b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/domain/Weather.java new file mode 100644 index 0000000000000000000000000000000000000000..1787a08c3554e017645fefbd35d7c4fd1bc60bd4 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/java/com/taosdata/example/jdbcTemplate/domain/Weather.java @@ -0,0 +1,54 @@ +package com.taosdata.example.jdbcTemplate.domain; + +import java.sql.Timestamp; + +public class Weather { + + private Timestamp ts; + private float temperature; + private int humidity; + + public Weather() { + } + + public Weather(Timestamp ts, float temperature, int humidity) { + this.ts = ts; + this.temperature = temperature; + this.humidity = humidity; + } + + @Override + public String toString() { + return "Weather{" + + "ts=" + ts + + ", temperature=" + temperature + + ", humidity=" + humidity + + '}'; + } + + public Timestamp getTs() { + return ts; + } + + public void setTs(Timestamp ts) { + this.ts = ts; + } + + public float getTemperature() { + return temperature; + } + + public void setTemperature(float temperature) { + this.temperature = temperature; + } + + public int getHumidity() { + return humidity; + } + + public void setHumidity(int humidity) { + this.humidity = humidity; + } + + +} diff --git a/examples/JDBC/SpringJdbcTemplate/src/main/resources/applicationContext.xml b/examples/JDBC/SpringJdbcTemplate/src/main/resources/applicationContext.xml new file mode 100644 index 0000000000000000000000000000000000000000..6d6cf6047e2545256ffd6f39e1e6160a965a6fa8 --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/main/resources/applicationContext.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + diff --git a/examples/JDBC/SpringJdbcTemplate/src/test/java/com/taosdata/example/jdbcTemplate/BatcherInsertTest.java b/examples/JDBC/SpringJdbcTemplate/src/test/java/com/taosdata/example/jdbcTemplate/BatcherInsertTest.java new file mode 100644 index 0000000000000000000000000000000000000000..29d0f79fd4982d43078e590b4320c0df457ee44c --- /dev/null +++ b/examples/JDBC/SpringJdbcTemplate/src/test/java/com/taosdata/example/jdbcTemplate/BatcherInsertTest.java @@ -0,0 +1,64 @@ +package com.taosdata.example.jdbcTemplate; + + +import com.taosdata.example.jdbcTemplate.dao.ExecuteAsStatement; +import com.taosdata.example.jdbcTemplate.dao.WeatherDao; +import com.taosdata.example.jdbcTemplate.domain.Weather; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"classpath:applicationContext.xml"}) +public class BatcherInsertTest { + + + @Autowired + private WeatherDao weatherDao; + @Autowired + private ExecuteAsStatement executor; + + private static final int numOfRecordsPerTable = 1000; + private static long ts = 1496732686000l; + private static Random random = new Random(System.currentTimeMillis()); + + @Before + public void before() { + // drop database + executor.doExecute("drop database if exists test"); + // create database + executor.doExecute("create database if not exists test"); + //use database + executor.doExecute("use test"); + // create table + executor.doExecute("create table if not exists test.weather (ts timestamp, temperature int, humidity float)"); + } + + @Test + public void batchInsert() { + List weatherList = new ArrayList<>(); + for (int i = 0; i < numOfRecordsPerTable; i++) { + ts += 1000; + Weather weather = new Weather(new Timestamp(ts), random.nextFloat() * 50.0f, random.nextInt(100)); + weatherList.add(weather); + } + long start = System.currentTimeMillis(); + weatherDao.batchInsert(weatherList); + long end = System.currentTimeMillis(); + System.out.println("batch insert(" + numOfRecordsPerTable + " rows) time cost ==========> " + (end - start) + " ms"); + + int count = weatherDao.count(); + assertEquals(count, numOfRecordsPerTable); + } + +} diff --git a/examples/JDBC/connectionPools/README-cn.md b/examples/JDBC/connectionPools/README-cn.md new file mode 100644 index 0000000000000000000000000000000000000000..9b26df3c2eb2c23171a673643891a292af4c920c --- /dev/null +++ b/examples/JDBC/connectionPools/README-cn.md @@ -0,0 +1,32 @@ +这个example中,我们适配了java常见的连接池: +* HikariCP(默认) +* druid +* dbcp +* c3p0 + +### 说明 +ConnectionPoolDemo的程序逻辑: +1. 创建到host的connection连接池 +2. 创建名称为pool_test的database,创建表超级weather,创建tableSize个子表 +3. 总共插入totalNumber条数据。 + +### 如何运行这个例子: + +```shell script +mvn clean package assembly:single +java -jar target/connectionPools-1.0-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1 +``` +使用mvn运行ConnectionPoolDemo的main方法,可以指定参数 +```shell script +Usage: +java -jar target/connectionPools-1.0-SNAPSHOT-jar-with-dependencies.jar +-host : hostname +-poolType +-poolSize +-tableSize +-batchSize : 每条Insert SQL中values的数量 +-sleep : 每次插入任务提交后的 +``` + +### 日志 +使用log4j,将日志和错误分别输出到了debug.log和error.log中 \ No newline at end of file diff --git a/examples/JDBC/connectionPools/pom.xml b/examples/JDBC/connectionPools/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..aad2923b823c1fcf2cb87eba4f18865fede063a1 --- /dev/null +++ b/examples/JDBC/connectionPools/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + + 1.8 + 1.8 + + + com.taosdata.demo + connectionPools + 1.0-SNAPSHOT + + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.34 + + + + com.alibaba + druid + 1.1.17 + + + + com.zaxxer + HikariCP + 3.2.0 + + + + commons-pool + commons-pool + 1.5.4 + + + commons-dbcp + commons-dbcp + 1.4 + + + + com.mchange + c3p0 + 0.9.5.4 + + + + org.apache.logging.log4j + log4j-core + 2.17.0 + + + + com.cloudhopper.proxool + proxool + 0.9.1 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + ConnectionPoolDemo + + ConnectionPoolDemo + + + com.taosdata.example.ConnectionPoolDemo + + + + jar-with-dependencies + + + package + + single + + + + + ProxoolDemo + + ProxoolDemo + + + com.taosdata.example.ProxoolDemo + + + + jar-with-dependencies + + + package + + single + + + + + + + + + diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ConnectionPoolDemo.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ConnectionPoolDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..96ad65aa4fc10bf81f6107a4bb2e5a4224891298 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ConnectionPoolDemo.java @@ -0,0 +1,137 @@ +package com.taosdata.example; + +import com.taosdata.example.common.InsertTask; +import com.taosdata.example.pool.C3p0Builder; +import com.taosdata.example.pool.DbcpBuilder; +import com.taosdata.example.pool.DruidPoolBuilder; +import com.taosdata.example.pool.HikariCpBuilder; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class ConnectionPoolDemo { + + private static Logger logger = LogManager.getLogger(DruidPoolBuilder.class); + private static final String dbName = "pool_test"; + + private static String poolType = "hikari"; + private static long totalSize = 1_000_000l; + private static long tableSize = 1; + private static long batchSize = 1; + + private static int poolSize = 50; + private static int threadCount = 50; + private static int sleep = 0; + + public static void main(String[] args) { + String host = null; + for (int i = 0; i < args.length; i++) { + if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) { + host = args[++i]; + } + if ("-poolType".equalsIgnoreCase(args[i]) && i < args.length - 1) { + poolType = args[++i]; + } + if ("-recordNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) { + totalSize = Long.parseLong(args[++i]); + } + if ("-tableNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) { + tableSize = Long.parseLong(args[++i]); + } + if ("-batchNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) { + batchSize = Long.parseLong(args[++i]); + } + + } + if (host == null) { + System.out.println("Usage: java -jar XXX.jar -host " + + "-poolType " + + "-recordNumber " + + "-tableNumber " + + "-batchNumber " + + "-sleep " + ); + return; + } + + DataSource dataSource; + switch (poolType) { + case "c3p0": + dataSource = C3p0Builder.getDataSource(host, poolSize); + break; + case "dbcp": + dataSource = DbcpBuilder.getDataSource(host, poolSize); + break; + case "druid": + dataSource = DruidPoolBuilder.getDataSource(host, poolSize); + break; + case "hikari": + default: + dataSource = HikariCpBuilder.getDataSource(host, poolSize); + poolType = "hikari"; + } + + logger.info(">>>>>>>>>>>>>> connection pool Type: " + poolType); + init(dataSource); + +// try { +// Connection connection = dataSource.getConnection(); +// Statement statement = connection.createStatement(); +// String sql = "insert into " + dbName + ".t_1 values('2020-01-01 00:00:00.000',12.12,111)"; +// int affectRows = statement.executeUpdate(sql); +// System.out.println("affectRows >>> " + affectRows); +// affectRows = statement.executeUpdate(sql); +// System.out.println("affectRows >>> " + affectRows); +// statement.close(); +// connection.close(); +// } catch (SQLException e) { +// e.printStackTrace(); +// } + + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + for (long i = 0; i < totalSize / tableSize / batchSize; i++) { + executor.execute(new InsertTask(dataSource, dbName, tableSize, batchSize)); + // sleep few seconds + try { + if (sleep > 0) + TimeUnit.MILLISECONDS.sleep(sleep); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + executor.shutdown(); + + } + + private static void init(DataSource dataSource) { + try (Connection conn = dataSource.getConnection()) { + execute(conn, "drop database if exists " + dbName + ""); + execute(conn, "create database if not exists " + dbName + ""); + execute(conn, "use " + dbName + ""); + execute(conn, "create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"); + for (int tb_ind = 1; tb_ind <= tableSize; tb_ind++) { + execute(conn, "create table t_" + tb_ind + " using weather tags('beijing'," + (tb_ind + 1) + ")"); + } + logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>> init finished."); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private static void execute(Connection con, String sql) { + try (Statement stmt = con.createStatement()) { + stmt.executeUpdate(sql); + logger.info("SQL >>> " + sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ProxoolDemo.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ProxoolDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..632ad8c9bf69d13d137d06c1f23c964904c8e050 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/ProxoolDemo.java @@ -0,0 +1,56 @@ +package com.taosdata.example; + +import org.logicalcobwebs.proxool.ProxoolException; +import org.logicalcobwebs.proxool.configuration.JAXPConfigurator; + +import java.sql.*; + +public class ProxoolDemo { + + + public static void main(String[] args) { + + String xml = parseConfigurationXml(args); + if (xml == null) { + printHelp(); + System.exit(0); + } + + try { + JAXPConfigurator.configure(xml, false); + Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); + Connection connection = DriverManager.getConnection("proxool.ds"); + + Statement stmt = connection.createStatement(); + + ResultSet rs = stmt.executeQuery("show databases"); + ResultSetMetaData metaData = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= metaData.getColumnCount(); i++) { + System.out.print(metaData.getColumnLabel(i) + ": " + rs.getString(i)); + } + System.out.println(); + } + + stmt.close(); + + } catch (ClassNotFoundException | SQLException | ProxoolException e) { + e.printStackTrace(); + } + } + + private static String parseConfigurationXml(String[] args) { + String host = null; + for (int i = 0; i < args.length; i++) { + if ("--xml".equalsIgnoreCase(args[i]) && i < args.length - 1) { + host = args[++i]; + } + } + return host; + } + + private static void printHelp() { + System.out.println("Usage: java -jar ProxoolDemo.jar --xml [xml]"); + } + +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/common/InsertTask.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/common/InsertTask.java new file mode 100644 index 0000000000000000000000000000000000000000..f8f1555c08f1f5847bf0a34a56341ef6d22dde50 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/common/InsertTask.java @@ -0,0 +1,47 @@ +package com.taosdata.example.common; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Random; + +public class InsertTask implements Runnable { + private final Random random = new Random(System.currentTimeMillis()); + private static final Logger logger = LogManager.getLogger(InsertTask.class); + + private final DataSource ds; + private final String dbName; + private final long tableSize; + private final long batchSize; + + public InsertTask(DataSource ds, String dbName, long tableSize, long batchSize) { + this.ds = ds; + this.dbName = dbName; + this.tableSize = tableSize; + this.batchSize = batchSize; + } + + @Override + public void run() { + int affectedRows = 0; + long start = System.currentTimeMillis(); + try (Connection conn = ds.getConnection(); Statement stmt = conn.createStatement()) { + for (int tb_index = 1; tb_index <= tableSize; tb_index++) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(dbName).append(".t_").append(tb_index).append("(ts, temperature, humidity) values "); + for (int i = 0; i < batchSize; i++) { + sb.append("(").append(start + i).append(", ").append(random.nextFloat() * 30).append(", ").append(random.nextInt(70)).append(") "); + } + logger.info("SQL >>> " + sb.toString()); + affectedRows += stmt.executeUpdate(sb.toString()); + } + } catch (SQLException e) { + e.printStackTrace(); + } + logger.info(">>> affectedRows:" + affectedRows + " TimeCost:" + (System.currentTimeMillis() - start) + " ms"); + } +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/C3p0Builder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/C3p0Builder.java new file mode 100644 index 0000000000000000000000000000000000000000..235db0bb796ee507b2d93838c8e7bfa7de870fcd --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/C3p0Builder.java @@ -0,0 +1,27 @@ +package com.taosdata.example.pool; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +import javax.sql.DataSource; +import java.beans.PropertyVetoException; + +public class C3p0Builder { + + public static DataSource getDataSource(String host, int poolSize) { + ComboPooledDataSource ds = new ComboPooledDataSource(); + + try { + ds.setDriverClass("com.taosdata.jdbc.TSDBDriver"); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + ds.setJdbcUrl("jdbc:TAOS://" + host + ":6030"); + ds.setUser("root"); + ds.setPassword("taosdata"); + + ds.setMinPoolSize(poolSize); + ds.setMaxPoolSize(poolSize); + ds.setAcquireIncrement(5); + return ds; + } +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DbcpBuilder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DbcpBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..3aa9e4ebcf2d07ba1e6a51a2dae216cf44e88486 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DbcpBuilder.java @@ -0,0 +1,21 @@ +package com.taosdata.example.pool; + +import org.apache.commons.dbcp.BasicDataSource; + +import javax.sql.DataSource; + +public class DbcpBuilder { + + public static DataSource getDataSource(String host, int poolSize) { + BasicDataSource ds = new BasicDataSource(); + ds.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + ds.setUrl("jdbc:TAOS://" + host + ":6030"); + ds.setUsername("root"); + ds.setPassword("taosdata"); + + ds.setMaxActive(poolSize); + ds.setMinIdle(poolSize); + ds.setInitialSize(poolSize); + return ds; + } +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..500f0e9e97cc09c2c5e9990234f051d0bbc72044 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/DruidPoolBuilder.java @@ -0,0 +1,27 @@ +package com.taosdata.example.pool; + +import com.alibaba.druid.pool.DruidDataSource; + +import javax.sql.DataSource; + +public class DruidPoolBuilder { + + public static DataSource getDataSource(String host, int poolSize) { + final String url = "jdbc:TAOS://" + host + ":6030"; + + DruidDataSource dataSource = new DruidDataSource(); + // jdbc properties + dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + dataSource.setUrl(url); + dataSource.setUsername("root"); + dataSource.setPassword("taosdata"); + // pool configurations + dataSource.setInitialSize(poolSize); + dataSource.setMinIdle(poolSize); + dataSource.setMaxActive(poolSize); + dataSource.setMaxWait(30000); + dataSource.setValidationQuery("select server_status()"); + return dataSource; + } + +} diff --git a/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..7e151de3e052495b3ce50ffe042732717fcc38f4 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/java/com/taosdata/example/pool/HikariCpBuilder.java @@ -0,0 +1,28 @@ +package com.taosdata.example.pool; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import javax.sql.DataSource; + +public class HikariCpBuilder { + + public static DataSource getDataSource(String host, int poolSize) { + HikariConfig config = new HikariConfig(); + // jdbc properties + config.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + config.setJdbcUrl("jdbc:TAOS://" + host + ":6030"); + config.setUsername("root"); + config.setPassword("taosdata"); + // pool configurations + config.setMinimumIdle(poolSize); //minimum number of idle connection + config.setMaximumPoolSize(poolSize); //maximum number of connection in the pool + config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool + config.setMaxLifetime(0); // maximum life time for each connection + config.setIdleTimeout(0); // max idle time for recycle idle connection + config.setConnectionTestQuery("select server_status()"); //validation query + + HikariDataSource ds = new HikariDataSource(config); + return ds; + } +} diff --git a/examples/JDBC/connectionPools/src/main/resources/log4j.properties b/examples/JDBC/connectionPools/src/main/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..1299357be3d2e99ca6b79227f14ca7a587718914 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/resources/log4j.properties @@ -0,0 +1,21 @@ +### 设置### +log4j.rootLogger=debug,stdout,DebugLog,ErrorLog +### 输出信息到控制抬 ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n +### 输出DEBUG 级别以上的日志到=logs/debug.log +log4j.appender.DebugLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.DebugLog.File=logs/debug.log +log4j.appender.DebugLog.Append=true +log4j.appender.DebugLog.Threshold=DEBUG +log4j.appender.DebugLog.layout=org.apache.log4j.PatternLayout +log4j.appender.DebugLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n +### 输出ERROR 级别以上的日志到=logs/error.log +log4j.appender.ErrorLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.ErrorLog.File=logs/error.log +log4j.appender.ErrorLog.Append=true +log4j.appender.ErrorLog.Threshold=ERROR +log4j.appender.ErrorLog.layout=org.apache.log4j.PatternLayout +log4j.appender.ErrorLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n \ No newline at end of file diff --git a/examples/JDBC/connectionPools/src/main/resources/proxool.xml b/examples/JDBC/connectionPools/src/main/resources/proxool.xml new file mode 100644 index 0000000000000000000000000000000000000000..67baa1c3931aa57591af8fc306ed441328606978 --- /dev/null +++ b/examples/JDBC/connectionPools/src/main/resources/proxool.xml @@ -0,0 +1,27 @@ + + + + ds + + jdbc:TAOS-RS://127.0.0.1:6041/log + + com.taosdata.jdbc.rs.RestfulDriver + + + + + + + 100 + + 100 + + 1 + + 5 + + 30000 + + select server_status() + + \ No newline at end of file diff --git a/examples/JDBC/mybatisplus-demo/.gitignore b/examples/JDBC/mybatisplus-demo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b56f1dd0d04da4e03f710af3917e4fbdd9be4aa8 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/.gitignore @@ -0,0 +1,33 @@ +README.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/examples/JDBC/mybatisplus-demo/.mvn/wrapper/MavenWrapperDownloader.java b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000000000000000000000000000000000..a45eb6ba269cd38f8965cef786729790945d9537 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.jar b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 Binary files /dev/null and b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.jar differ diff --git a/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.properties b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..642d572ce90e5085986bdd9c9204b9404f028084 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/examples/JDBC/mybatisplus-demo/mvnw b/examples/JDBC/mybatisplus-demo/mvnw new file mode 100755 index 0000000000000000000000000000000000000000..3c8a5537314954d53ec2fb774b34fe5d5a5f253a --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/mvnw @@ -0,0 +1,322 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ]; then + + if [ -f /etc/mavenrc ]; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ]; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false +darwin=false +mingw=false +case "$(uname)" in +CYGWIN*) cygwin=true ;; +MINGW*) mingw=true ;; +Darwin*) + darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="$(/usr/libexec/java_home)" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ]; then + if [ -r /etc/gentoo-release ]; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +if [ -z "$M2_HOME" ]; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG="$(dirname "$PRG")/$link" + fi + done + + saveddir=$(pwd) + + M2_HOME=$(dirname "$PRG")/.. + + # make it fully qualified + M2_HOME=$(cd "$M2_HOME" && pwd) + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=$(cygpath --unix "$M2_HOME") + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw; then + [ -n "$M2_HOME" ] && + M2_HOME="$( ( + cd "$M2_HOME" + pwd + ))" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="$( ( + cd "$JAVA_HOME" + pwd + ))" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then + if $darwin; then + javaHome="$(dirname \"$javaExecutable\")" + javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac" + else + javaExecutable="$(readlink -f \"$javaExecutable\")" + fi + javaHome="$(dirname \"$javaExecutable\")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ]; then + if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(which java)" + fi +fi + +if [ ! -x "$JAVACMD" ]; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ]; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ]; then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ]; do + if [ -d "$wdir"/.mvn ]; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$( + cd "$wdir/.." + pwd + ) + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' <"$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(pwd)") +if [ -z "$BASE_DIR" ]; then + exit 1 +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in wrapperUrl) + jarUrl="$value" + break + ;; + esac + done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=$(cygpath --path --windows "$M2_HOME") + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/examples/JDBC/mybatisplus-demo/mvnw.cmd b/examples/JDBC/mybatisplus-demo/mvnw.cmd new file mode 100644 index 0000000000000000000000000000000000000000..c8d43372c986d97911cdc21bd87e0cbe3d83bdda --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/examples/JDBC/mybatisplus-demo/pom.xml b/examples/JDBC/mybatisplus-demo/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ad6a63e800fb73dd3c768a8aca941f70cec235b3 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + com.taosdata.example + mybatisplus-demo + 0.0.1-SNAPSHOT + mybatisplus-demo + Demo project for tdengine + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.projectlombok + lombok + true + + + com.baomidou + mybatis-plus-boot-starter + 3.1.2 + + + com.h2database + h2 + runtime + + + com.alibaba + druid + 1.1.17 + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.18 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + 4.13.1 + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.17 + + + **/*Test.java + + + **/Abstract*.java + + + + + + + + diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/MybatisplusDemoApplication.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/MybatisplusDemoApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..7aaebca0846c15c2055596c95ae76d0cee773e41 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/MybatisplusDemoApplication.java @@ -0,0 +1,15 @@ +package com.taosdata.example.mybatisplusdemo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.taosdata.example.mybatisplusdemo.mapper") +public class MybatisplusDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(MybatisplusDemoApplication.class, args); + } + +} \ No newline at end of file diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/config/MybatisPlusConfig.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/config/MybatisPlusConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..a6ac7f7fc247a361286333de4b3c03ffba306336 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/config/MybatisPlusConfig.java @@ -0,0 +1,34 @@ +package com.taosdata.example.mybatisplusdemo.config; + +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisPlusConfig { + + + /** mybatis 3.4.1 pagination config start ***/ +// @Bean +// public MybatisPlusInterceptor mybatisPlusInterceptor() { +// MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); +// interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); +// return interceptor; +// } + +// @Bean +// public ConfigurationCustomizer configurationCustomizer() { +// return configuration -> configuration.setUseDeprecatedExecutor(false); +// } + + @Bean + public PaginationInterceptor paginationInterceptor() { +// return new PaginationInterceptor(); + PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); + //TODO: mybatis-plus do not support TDengine, use postgresql Dialect + paginationInterceptor.setDialectType("postgresql"); + + return paginationInterceptor; + } + +} diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Temperature.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Temperature.java new file mode 100644 index 0000000000000000000000000000000000000000..97e50b06f6b71c26d1edd65c5ae9e7ff29a03e4d --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Temperature.java @@ -0,0 +1,15 @@ +package com.taosdata.example.mybatisplusdemo.domain; + +import lombok.Data; + +import java.sql.Timestamp; + +@Data +public class Temperature { + + private Timestamp ts; + private float temperature; + private String location; + private int tbIndex; + +} diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Weather.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Weather.java new file mode 100644 index 0000000000000000000000000000000000000000..361757411a15d29e742a07a92060e20190921223 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/domain/Weather.java @@ -0,0 +1,15 @@ +package com.taosdata.example.mybatisplusdemo.domain; + +import lombok.Data; + +import java.sql.Timestamp; + +@Data +public class Weather { + + private Timestamp ts; + private float temperature; + private int humidity; + private String location; + +} diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapper.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3e122524d57b5a54e08ff1cfc54101d517f32c32 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapper.java @@ -0,0 +1,23 @@ +package com.taosdata.example.mybatisplusdemo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.taosdata.example.mybatisplusdemo.domain.Temperature; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +public interface TemperatureMapper extends BaseMapper { + + @Update("CREATE TABLE if not exists temperature(ts timestamp, temperature float) tags(location nchar(64), tbIndex int)") + int createSuperTable(); + + @Update("create table #{tbName} using temperature tags( #{location}, #{tbindex})") + int createTable(@Param("tbName") String tbName, @Param("location") String location, @Param("tbindex") int tbindex); + + @Update("drop table if exists temperature") + void dropSuperTable(); + + @Insert("insert into t${tbIndex}(ts, temperature) values(#{ts}, #{temperature})") + int insertOne(Temperature one); + +} diff --git a/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapper.java b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..6733cbded9d1d180408eccaad9e8badad7d39a3d --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapper.java @@ -0,0 +1,8 @@ +package com.taosdata.example.mybatisplusdemo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.taosdata.example.mybatisplusdemo.domain.Weather; + +public interface WeatherMapper extends BaseMapper { + +} diff --git a/examples/JDBC/mybatisplus-demo/src/main/resources/application.yml b/examples/JDBC/mybatisplus-demo/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..38180c6d75a620a63bcaab9ec350d97e65f9dd16 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/main/resources/application.yml @@ -0,0 +1,24 @@ +spring: + datasource: + driver-class-name: com.taosdata.jdbc.TSDBDriver + url: jdbc:TAOS://localhost:6030/mp_test?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8 + user: root + password: taosdata + + druid: + initial-size: 5 + min-idle: 5 + max-active: 5 + +mybatis-plus: + configuration: + map-underscore-to-camel-case: false + +logging: + level: + com: + taosdata: + example: + mybatisplusdemo: + mapper: debug + diff --git a/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapperTest.java b/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4331d15d3476d3428e72a186664ed77cc59aad3e --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/TemperatureMapperTest.java @@ -0,0 +1,140 @@ +package com.taosdata.example.mybatisplusdemo.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.taosdata.example.mybatisplusdemo.domain.Temperature; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +public class TemperatureMapperTest { + + private static Random random = new Random(System.currentTimeMillis()); + private static String[] locations = {"北京", "上海", "深圳", "广州", "杭州"}; + + @Before + public void before() { + mapper.dropSuperTable(); + // create table temperature + mapper.createSuperTable(); + // create table t_X using temperature + for (int i = 0; i < 10; i++) { + mapper.createTable("t" + i, locations[random.nextInt(locations.length)], i); + } + // insert into table + int affectRows = 0; + // insert 10 tables + for (int i = 0; i < 10; i++) { + // each table insert 5 rows + for (int j = 0; j < 5; j++) { + Temperature one = new Temperature(); + one.setTs(new Timestamp(1605024000000l)); + one.setTemperature(random.nextFloat() * 50); + one.setLocation("望京"); + one.setTbIndex(i); + affectRows += mapper.insertOne(one); + } + } + Assert.assertEquals(50, affectRows); + } + + @After + public void after() { + mapper.dropSuperTable(); + } + + @Autowired + private TemperatureMapper mapper; + + /*** + * test SelectList + * **/ + @Test + public void testSelectList() { + List temperatureList = mapper.selectList(null); + temperatureList.forEach(System.out::println); + } + + /*** + * test InsertOne which is a custom metheod + * ***/ + @Test + public void testInsert() { + Temperature one = new Temperature(); + one.setTs(new Timestamp(1605024000000l)); + one.setTemperature(random.nextFloat() * 50); + one.setLocation("望京"); + int affectRows = mapper.insertOne(one); + Assert.assertEquals(1, affectRows); + } + + /*** + * test SelectOne + * **/ + @Test + public void testSelectOne() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("location", "beijing"); + Temperature one = mapper.selectOne(wrapper); + System.out.println(one); + Assert.assertNotNull(one); + } + + /*** + * test select By map + * ***/ + @Test + public void testSelectByMap() { + Map map = new HashMap<>(); + map.put("location", "beijing"); + List temperatures = mapper.selectByMap(map); + Assert.assertEquals(1, temperatures.size()); + } + + /*** + * test selectObjs + * **/ + @Test + public void testSelectObjs() { + List ts = mapper.selectObjs(null); + System.out.println(ts); + } + + /** + * test selectC ount + * **/ + @Test + public void testSelectCount() { + int count = mapper.selectCount(null); + Assert.assertEquals(5, count); + } + + /**** + * 分页 + */ + @Test + public void testSelectPage() { + IPage page = new Page(1, 2); + IPage temperatureIPage = mapper.selectPage(page, null); + System.out.println("total : " + temperatureIPage.getTotal()); + System.out.println("pages : " + temperatureIPage.getPages()); + for (Temperature temperature : temperatureIPage.getRecords()) { + System.out.println(temperature); + } + } + +} \ No newline at end of file diff --git a/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapperTest.java b/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1699344552f89e1595d1317019c992dcd3820e77 --- /dev/null +++ b/examples/JDBC/mybatisplus-demo/src/test/java/com/taosdata/example/mybatisplusdemo/mapper/WeatherMapperTest.java @@ -0,0 +1,88 @@ +package com.taosdata.example.mybatisplusdemo.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.taosdata.example.mybatisplusdemo.domain.Weather; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +public class WeatherMapperTest { + + private static Random random = new Random(System.currentTimeMillis()); + + @Autowired + private WeatherMapper mapper; + + @Test + public void testSelectList() { + List weathers = mapper.selectList(null); + weathers.forEach(System.out::println); + } + + @Test + public void testInsert() { + Weather one = new Weather(); + one.setTs(new Timestamp(1605024000000l)); + one.setTemperature(random.nextFloat() * 50); + one.setHumidity(random.nextInt(100)); + one.setLocation("望京"); + int affectRows = mapper.insert(one); + Assert.assertEquals(1, affectRows); + } + + @Test + public void testSelectOne() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("location", "beijing"); + Weather one = mapper.selectOne(wrapper); + System.out.println(one); + Assert.assertEquals(12.22f, one.getTemperature(), 0.00f); + Assert.assertEquals("beijing", one.getLocation()); + } + + @Test + public void testSelectByMap() { + Map map = new HashMap<>(); + map.put("location", "beijing"); + List weathers = mapper.selectByMap(map); + Assert.assertEquals(1, weathers.size()); + } + + @Test + public void testSelectObjs() { + List ts = mapper.selectObjs(null); + System.out.println(ts); + } + + @Test + public void testSelectCount() { + int count = mapper.selectCount(null); +// Assert.assertEquals(5, count); + System.out.println(count); + } + + @Test + public void testSelectPage() { + IPage page = new Page(1, 2); + IPage weatherIPage = mapper.selectPage(page, null); + System.out.println("total : " + weatherIPage.getTotal()); + System.out.println("pages : " + weatherIPage.getPages()); + for (Weather weather : weatherIPage.getRecords()) { + System.out.println(weather); + } + } + +} \ No newline at end of file diff --git a/examples/JDBC/readme.md b/examples/JDBC/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..35dfb341d7d62bb283897523f928e04dabea962d --- /dev/null +++ b/examples/JDBC/readme.md @@ -0,0 +1,13 @@ +# TDengine examples + +| No. | Name | Describe | +| :--: | :----------------: | ------------------------------------------------------------ | +| 1 | JDBCDemo | Example codes for JDBC-JNI, JDBC-RESTful, Subscribe | +| 2 | connectionPools | Example codes for HikariCP, Druid, dbcp, c3p0 connection pools | +| 3 | SpringJdbcTemplate | Example codes for spring jdbcTemplate | +| 4 | mybatisplus-demo | Example codes for mybatis | +| 5 | springbootdemo | Example codes for springboot | +| 6 | taosdemo | This is an internal tool for testing Our JDBC-JNI, JDBC-RESTful, RESTful interfaces | + + +more detail: https://www.taosdata.com/cn/documentation20/connector/java diff --git a/examples/JDBC/springbootdemo/.gitignore b/examples/JDBC/springbootdemo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b8a47adccb623c653c547481ff9d3221210f31ef --- /dev/null +++ b/examples/JDBC/springbootdemo/.gitignore @@ -0,0 +1,30 @@ +.mvn/ +target/ +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/examples/JDBC/springbootdemo/mvnw b/examples/JDBC/springbootdemo/mvnw new file mode 100755 index 0000000000000000000000000000000000000000..21d3ee84568ff68c4712677da7c3b06f61ab5543 --- /dev/null +++ b/examples/JDBC/springbootdemo/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/examples/JDBC/springbootdemo/mvnw.cmd b/examples/JDBC/springbootdemo/mvnw.cmd new file mode 100644 index 0000000000000000000000000000000000000000..84d60abc339b13f80f3300b00387f2d4cc4eb328 --- /dev/null +++ b/examples/JDBC/springbootdemo/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/examples/JDBC/springbootdemo/pom.xml b/examples/JDBC/springbootdemo/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..9126813b67e71691692109920f891a6fb4cc5ab5 --- /dev/null +++ b/examples/JDBC/springbootdemo/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.1.RELEASE + + + com.taosdata.example + springbootdemo + 0.0.1-SNAPSHOT + springbootdemo + Demo project for using tdengine with Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.1 + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + org.springframework.boot + spring-boot-starter-aop + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.34 + + + + com.alibaba + druid-spring-boot-starter + 1.1.17 + + + + + + + src/main/resources + + **/*.properties + **/*.xml + + true + + + src/main/java + + **/*.properties + **/*.xml + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/examples/JDBC/springbootdemo/readme.md b/examples/JDBC/springbootdemo/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..67a28947d2dfb8fc069bf94fd139a7006d35a22b --- /dev/null +++ b/examples/JDBC/springbootdemo/readme.md @@ -0,0 +1,96 @@ +## TDengine SpringBoot + Mybatis Demo + +### 配置 application.properties +```properties +# datasource config +spring.datasource.driver-class-name=com.taosdata.jdbc.TSDBDriver +spring.datasource.url=jdbc:TAOS://127.0.0.1:6030/log +spring.datasource.username=root +spring.datasource.password=taosdata + +spring.datasource.druid.initial-size=5 +spring.datasource.druid.min-idle=5 +spring.datasource.druid.max-active=5 +# max wait time for get connection, ms +spring.datasource.druid.max-wait=60000 + +spring.datasource.druid.validation-query=select server_status(); +spring.datasource.druid.validation-query-timeout=5000 +spring.datasource.druid.test-on-borrow=false +spring.datasource.druid.test-on-return=false +spring.datasource.druid.test-while-idle=true +spring.datasource.druid.time-between-eviction-runs-millis=60000 +spring.datasource.druid.min-evictable-idle-time-millis=600000 +spring.datasource.druid.max-evictable-idle-time-millis=900000 + +# mybatis +mybatis.mapper-locations=classpath:mapper/*.xml + +# log +logging.level.com.taosdata.jdbc.springbootdemo.dao=debug +``` + +### 主要功能 + +* 创建数据库和表 +```xml + + + create database if not exists test; + + + + create table if not exists test.weather(ts timestamp, temperature int, humidity float); + +``` + +* 插入单条记录 +```xml + + + insert into test.weather (ts, temperature, humidity) values (now, #{temperature,jdbcType=INTEGER}, #{humidity,jdbcType=FLOAT}) + +``` +* 插入多条记录 +```xml + + + insert into test.weather (ts, temperature, humidity) values + + (now + #{index}a, #{weather.temperature}, #{weather.humidity}) + + +``` +* 分页查询 +```xml + + + + + + + + + + + + + + ts, temperature, humidity + + + + +``` + diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..53edaa5796cccc7e4a4f274048c83a9ca7bbc7bb --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/SpringbootdemoApplication.java @@ -0,0 +1,14 @@ +package com.taosdata.example.springbootdemo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan(basePackages = {"com.taosdata.example.springbootdemo"}) +@SpringBootApplication +public class SpringbootdemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootdemoApplication.class, args); + } +} \ No newline at end of file diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java new file mode 100644 index 0000000000000000000000000000000000000000..ed720fe6c02dd3a7eba6e645ea1e76d704c04d0c --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/controller/WeatherController.java @@ -0,0 +1,53 @@ +package com.taosdata.example.springbootdemo.controller; + +import com.taosdata.example.springbootdemo.domain.Weather; +import com.taosdata.example.springbootdemo.service.WeatherService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RequestMapping("/weather") +@RestController +public class WeatherController { + + @Autowired + private WeatherService weatherService; + + @GetMapping("/lastOne") + public Weather lastOne() { + return weatherService.lastOne(); + } + + @GetMapping("/init") + public int init() { + return weatherService.init(); + } + + @GetMapping("/{limit}/{offset}") + public List queryWeather(@PathVariable Long limit, @PathVariable Long offset) { + return weatherService.query(limit, offset); + } + + @PostMapping("/{temperature}/{humidity}") + public int saveWeather(@PathVariable float temperature, @PathVariable float humidity) { + return weatherService.save(temperature, humidity); + } + + @GetMapping("/count") + public int count() { + return weatherService.count(); + } + + @GetMapping("/subTables") + public List getSubTables() { + return weatherService.getSubTables(); + } + + @GetMapping("/avg") + public List avg() { + return weatherService.avg(); + } + +} diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..d9202b45b4cc3dddf8e5a082ac339c1f88d4ec01 --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.java @@ -0,0 +1,31 @@ +package com.taosdata.example.springbootdemo.dao; + +import com.taosdata.example.springbootdemo.domain.Weather; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +public interface WeatherMapper { + + Map lastOne(); + + void dropDB(); + + void createDB(); + + void createSuperTable(); + + void createTable(Weather weather); + + List select(@Param("limit") Long limit, @Param("offset") Long offset); + + int insert(Weather weather); + + int count(); + + List getSubTables(); + + List avg(); + +} diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..91938ca24e3cf9c3e0f2895cf40f214d484c55d5 --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + drop + database if exists test + + + + create + database if not exists test + + + + create table if not exists test.weather + ( + ts + timestamp, + temperature + float, + humidity + float, + note + binary + ( + 64 + )) tags + ( + location nchar + ( + 64 + ), groupId int) + + + + create table if not exists test.t#{groupId} using test.weather tags + ( + #{location}, + #{groupId} + ) + + + + + + insert into test.t#{groupId} (ts, temperature, humidity, note) + values (#{ts}, ${temperature}, ${humidity}, #{note}) + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java new file mode 100644 index 0000000000000000000000000000000000000000..e4238127bd32b0f6ad21a514f3a1f07f6069b6d5 --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/domain/Weather.java @@ -0,0 +1,73 @@ +package com.taosdata.example.springbootdemo.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.sql.Timestamp; + +public class Weather { + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8") + private Timestamp ts; + private Float temperature; + private Float humidity; + private String location; + private String note; + private int groupId; + + public Weather() { + } + + public Weather(Timestamp ts, float temperature, float humidity) { + this.ts = ts; + this.temperature = temperature; + this.humidity = humidity; + } + + public Timestamp getTs() { + return ts; + } + + public void setTs(Timestamp ts) { + this.ts = ts; + } + + public Float getTemperature() { + return temperature; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public Float getHumidity() { + return humidity; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } +} diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java new file mode 100644 index 0000000000000000000000000000000000000000..2264b200afc3e0c2b7dd8e496e607649f940581d --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/service/WeatherService.java @@ -0,0 +1,79 @@ +package com.taosdata.example.springbootdemo.service; + +import com.taosdata.example.springbootdemo.dao.WeatherMapper; +import com.taosdata.example.springbootdemo.domain.Weather; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.util.List; +import java.util.Map; +import java.util.Random; + +@Service +public class WeatherService { + + @Autowired + private WeatherMapper weatherMapper; + private Random random = new Random(System.currentTimeMillis()); + private String[] locations = {"北京", "上海", "广州", "深圳", "天津"}; + + public int init() { + weatherMapper.dropDB(); + weatherMapper.createDB(); + weatherMapper.createSuperTable(); + long ts = System.currentTimeMillis(); + long thirtySec = 1000 * 30; + int count = 0; + for (int i = 0; i < 20; i++) { + Weather weather = new Weather(new Timestamp(ts + (thirtySec * i)), 30 * random.nextFloat(), random.nextInt(100)); + weather.setLocation(locations[random.nextInt(locations.length)]); + weather.setGroupId(i % locations.length); + weather.setNote("note-" + i); + weatherMapper.createTable(weather); + count += weatherMapper.insert(weather); + } + return count; + } + + public List query(Long limit, Long offset) { + return weatherMapper.select(limit, offset); + } + + public int save(float temperature, float humidity) { + Weather weather = new Weather(); + weather.setTemperature(temperature); + weather.setHumidity(humidity); + + return weatherMapper.insert(weather); + } + + public int count() { + return weatherMapper.count(); + } + + public List getSubTables() { + return weatherMapper.getSubTables(); + } + + public List avg() { + return weatherMapper.avg(); + } + + public Weather lastOne() { + Map result = weatherMapper.lastOne(); + + long ts = (long) result.get("ts"); + float temperature = (float) result.get("temperature"); + float humidity = (float) result.get("humidity"); + String note = (String) result.get("note"); + int groupId = (int) result.get("groupid"); + String location = (String) result.get("location"); + + Weather weather = new Weather(new Timestamp(ts), temperature, humidity); + weather.setNote(note); + weather.setGroupId(groupId); + weather.setLocation(location); + return weather; + } +} diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/util/TaosAspect.java b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/util/TaosAspect.java new file mode 100644 index 0000000000000000000000000000000000000000..80dad1bd7d669ba6b912c7e5fa816c29b7e37c87 --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/util/TaosAspect.java @@ -0,0 +1,36 @@ +package com.taosdata.example.springbootdemo.util; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +import java.sql.Timestamp; +import java.util.Map; + +@Aspect +@Component +public class TaosAspect { + + @Around("execution(java.util.Map com.taosdata.example.springbootdemo.dao.*.*(..))") + public Object handleType(ProceedingJoinPoint joinPoint) { + Map result = null; + try { + result = (Map) joinPoint.proceed(); + for (String key : result.keySet()) { + Object obj = result.get(key); + if (obj instanceof byte[]) { + obj = new String((byte[]) obj); + result.put(key, obj); + } + if (obj instanceof Timestamp) { + obj = ((Timestamp) obj).getTime(); + result.put(key, obj); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/examples/JDBC/springbootdemo/src/main/resources/application.properties b/examples/JDBC/springbootdemo/src/main/resources/application.properties new file mode 100644 index 0000000000000000000000000000000000000000..06daa81bbb06450d99ab3f6e640c9795c0ad5d2e --- /dev/null +++ b/examples/JDBC/springbootdemo/src/main/resources/application.properties @@ -0,0 +1,20 @@ +# datasource config - JDBC-JNI +#spring.datasource.driver-class-name=com.taosdata.jdbc.TSDBDriver +#spring.datasource.url=jdbc:TAOS://localhost:6030/?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8 +#spring.datasource.username=root +#spring.datasource.password=taosdata +# datasource config - JDBC-RESTful +spring.datasource.driver-class-name=com.taosdata.jdbc.rs.RestfulDriver +spring.datasource.url=jdbc:TAOS-RS://localhsot:6041/test?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8 +spring.datasource.username=root +spring.datasource.password=taosdata +spring.datasource.druid.initial-size=5 +spring.datasource.druid.min-idle=5 +spring.datasource.druid.max-active=5 +spring.datasource.druid.max-wait=30000 +spring.datasource.druid.validation-query=select server_status(); +spring.aop.auto=true +spring.aop.proxy-target-class=true +#mybatis +mybatis.mapper-locations=classpath:mapper/*.xml +logging.level.com.taosdata.jdbc.springbootdemo.dao=debug diff --git a/examples/JDBC/taosdemo/.gitignore b/examples/JDBC/taosdemo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..549e00a2a96fa9d7c5dbc9859664a78d980158c2 --- /dev/null +++ b/examples/JDBC/taosdemo/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/examples/JDBC/taosdemo/.mvn/wrapper/MavenWrapperDownloader.java b/examples/JDBC/taosdemo/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000000000000000000000000000000000..a45eb6ba269cd38f8965cef786729790945d9537 --- /dev/null +++ b/examples/JDBC/taosdemo/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.jar b/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 Binary files /dev/null and b/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.jar differ diff --git a/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.properties b/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..642d572ce90e5085986bdd9c9204b9404f028084 --- /dev/null +++ b/examples/JDBC/taosdemo/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/examples/JDBC/taosdemo/mvnw b/examples/JDBC/taosdemo/mvnw new file mode 100755 index 0000000000000000000000000000000000000000..3c8a5537314954d53ec2fb774b34fe5d5a5f253a --- /dev/null +++ b/examples/JDBC/taosdemo/mvnw @@ -0,0 +1,322 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ]; then + + if [ -f /etc/mavenrc ]; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ]; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false +darwin=false +mingw=false +case "$(uname)" in +CYGWIN*) cygwin=true ;; +MINGW*) mingw=true ;; +Darwin*) + darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="$(/usr/libexec/java_home)" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ]; then + if [ -r /etc/gentoo-release ]; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +if [ -z "$M2_HOME" ]; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG="$(dirname "$PRG")/$link" + fi + done + + saveddir=$(pwd) + + M2_HOME=$(dirname "$PRG")/.. + + # make it fully qualified + M2_HOME=$(cd "$M2_HOME" && pwd) + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=$(cygpath --unix "$M2_HOME") + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw; then + [ -n "$M2_HOME" ] && + M2_HOME="$( ( + cd "$M2_HOME" + pwd + ))" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="$( ( + cd "$JAVA_HOME" + pwd + ))" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then + if $darwin; then + javaHome="$(dirname \"$javaExecutable\")" + javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac" + else + javaExecutable="$(readlink -f \"$javaExecutable\")" + fi + javaHome="$(dirname \"$javaExecutable\")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ]; then + if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(which java)" + fi +fi + +if [ ! -x "$JAVACMD" ]; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ]; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ]; then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ]; do + if [ -d "$wdir"/.mvn ]; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$( + cd "$wdir/.." + pwd + ) + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' <"$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(pwd)") +if [ -z "$BASE_DIR" ]; then + exit 1 +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in wrapperUrl) + jarUrl="$value" + break + ;; + esac + done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=$(cygpath --path --windows "$M2_HOME") + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/examples/JDBC/taosdemo/mvnw.cmd b/examples/JDBC/taosdemo/mvnw.cmd new file mode 100644 index 0000000000000000000000000000000000000000..c8d43372c986d97911cdc21bd87e0cbe3d83bdda --- /dev/null +++ b/examples/JDBC/taosdemo/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/examples/JDBC/taosdemo/pom.xml b/examples/JDBC/taosdemo/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..23c74ef1b72e0f2fd8b2a647a798872062a9c216 --- /dev/null +++ b/examples/JDBC/taosdemo/pom.xml @@ -0,0 +1,168 @@ + + + 4.0.0 + com.taosdata + taosdemo + 2.0.1 + taosdemo + jar + Demo project for TDengine + + + 5.3.2 + + + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-expression + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework + spring-aspects + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework + spring-jdbc + ${spring.version} + + + + + com.zaxxer + HikariCP + 3.4.5 + + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.20 + + + + + + com.alibaba + fastjson + 1.2.75 + + + + mysql + mysql-connector-java + 8.0.16 + test + + + + org.apache.logging.log4j + log4j-core + 2.17.0 + + + + junit + junit + 4.13.1 + test + + + + org.projectlombok + lombok + 1.18.16 + provided + + + + + + + src/main/resources + + **/*.properties + **/*.xml + **/*.jar + + true + + + src/main/java + + **/*.properties + **/*.xml + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + + com.taosdata.taosdemo.TaosDemoApplication + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + + + diff --git a/examples/JDBC/taosdemo/readme.md b/examples/JDBC/taosdemo/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..451fa2960adb98e2deb8499732aefde11f4810a1 --- /dev/null +++ b/examples/JDBC/taosdemo/readme.md @@ -0,0 +1,13 @@ +``` +cd tests/examples/JDBC/taosdemo +mvn clean package -Dmaven.test.skip=true +# 先建表,再插入的 +java -jar target/taosdemo-2.0-jar-with-dependencies.jar -host [hostname] -database [database] -doCreateTable true -superTableSQL "create table weather(ts timestamp, f1 int) tags(t1 nchar(4))" -numOfTables 1000 -numOfRowsPerTable 100000000 -numOfThreadsForInsert 10 -numOfTablesPerSQL 10 -numOfValuesPerSQL 100 +# 不建表,直接插入的 +java -jar target/taosdemo-2.0-jar-with-dependencies.jar -host [hostname] -database [database] -doCreateTable false -superTableSQL "create table weather(ts timestamp, f1 int) tags(t1 nchar(4))" -numOfTables 1000 -numOfRowsPerTable 100000000 -numOfThreadsForInsert 10 -numOfTablesPerSQL 10 -numOfValuesPerSQL 100 +``` + +需求: +1. 可以读lowa的配置文件 +2. 支持JDBC-JNI和JDBC-restful +3. 读取配置文件,持续执行查询 \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/TaosDemoApplication.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/TaosDemoApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..d4f5ff26886b9f90a4235d47bfd004dae9de93f6 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/TaosDemoApplication.java @@ -0,0 +1,128 @@ +package com.taosdata.taosdemo; + +import com.taosdata.taosdemo.components.DataSourceFactory; +import com.taosdata.taosdemo.components.JdbcTaosdemoConfig; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.service.DatabaseService; +import com.taosdata.taosdemo.service.SqlExecuteTask; +import com.taosdata.taosdemo.service.SubTableService; +import com.taosdata.taosdemo.service.SuperTableService; +import com.taosdata.taosdemo.service.data.SuperTableMetaGenerator; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import javax.sql.DataSource; +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class TaosDemoApplication { + + private static final Logger logger = LogManager.getLogger(TaosDemoApplication.class); + + public static void main(String[] args) throws IOException { + // 读配置参数 + JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args); + boolean isHelp = Arrays.asList(args).contains("--help"); + if (isHelp || config.host == null || config.host.isEmpty()) { + JdbcTaosdemoConfig.printHelp(); + System.exit(0); + } + // 初始化 + final DataSource dataSource = DataSourceFactory.getInstance(config.host, config.port, config.user, config.password); + if (config.executeSql != null && !config.executeSql.isEmpty() && !config.executeSql.replaceAll("\\s", "").isEmpty()) { + Thread task = new Thread(new SqlExecuteTask(dataSource, config.executeSql)); + task.start(); + try { + task.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return; + } + + final DatabaseService databaseService = new DatabaseService(dataSource); + final SuperTableService superTableService = new SuperTableService(dataSource); + final SubTableService subTableService = new SubTableService(dataSource); + + // 创建数据库 + long start = System.currentTimeMillis(); + Map databaseParam = new HashMap<>(); + databaseParam.put("database", config.database); + databaseParam.put("keep", Integer.toString(config.keep)); + databaseParam.put("days", Integer.toString(config.days)); + databaseParam.put("replica", Integer.toString(config.replica)); + //TODO: other database parameters + databaseService.createDatabase(databaseParam); + databaseService.useDatabase(config.database); + long end = System.currentTimeMillis(); + logger.info(">>> create database time cost : " + (end - start) + " ms."); + /**********************************************************************************/ + // 构造超级表的meta + SuperTableMeta superTableMeta; + // create super table + if (config.superTableSQL != null) { + // use a sql to create super table + superTableMeta = SuperTableMetaGenerator.generate(config.superTableSQL); + if (config.database != null && !config.database.isEmpty()) + superTableMeta.setDatabase(config.database); + } else if (config.numOfFields == 0) { + String sql = "create table " + config.database + "." + config.superTable + " (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"; + superTableMeta = SuperTableMetaGenerator.generate(sql); + } else { + // create super table with specified field size and tag size + superTableMeta = SuperTableMetaGenerator.generate(config.database, config.superTable, config.numOfFields, config.prefixOfFields, config.numOfTags, config.prefixOfTags); + } + /**********************************************************************************/ + // 建表 + start = System.currentTimeMillis(); + if (config.doCreateTable) { + superTableService.drop(superTableMeta.getDatabase(), superTableMeta.getName()); + superTableService.create(superTableMeta); + if (!config.autoCreateTable) { + // 批量建子表 + subTableService.createSubTable(superTableMeta, config.numOfTables, config.prefixOfTable, config.numOfThreadsForCreate); + } + } + end = System.currentTimeMillis(); + logger.info(">>> create table time cost : " + (end - start) + " ms."); + /**********************************************************************************/ + // 插入 + long tableSize = config.numOfTables; + int threadSize = config.numOfThreadsForInsert; + long startTime = getProperStartTime(config.startTime, config.keep); + + if (tableSize < threadSize) + threadSize = (int) tableSize; + long gap = (long) Math.ceil((0.0d + tableSize) / threadSize); + + start = System.currentTimeMillis(); + // multi threads to insert + int affectedRows = subTableService.insertMultiThreads(superTableMeta, threadSize, tableSize, startTime, gap, config); + end = System.currentTimeMillis(); + logger.info("insert " + affectedRows + " rows, time cost: " + (end - start) + " ms"); + /**********************************************************************************/ + // 查询 + + + /**********************************************************************************/ + // 删除表 + if (config.dropTable) { + superTableService.drop(config.database, config.superTable); + } + System.exit(0); + } + + private static long getProperStartTime(long startTime, int keep) { + Instant now = Instant.now(); + long earliest = now.minus(Duration.ofDays(keep - 1)).toEpochMilli(); + if (startTime == 0 || startTime < earliest) { + startTime = earliest; + } + return startTime; + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/DataSourceFactory.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/DataSourceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a7d08e96ea373c4773e872bcaf9b3a7b98d5bf9a --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/DataSourceFactory.java @@ -0,0 +1,62 @@ +package com.taosdata.taosdemo.components; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +@Component +public class DataSourceFactory { + + private static DataSource instance; + + public static DataSource getInstance(String host, int port, String user, String password) throws IOException { + if (instance == null) { + synchronized (DataSourceFactory.class) { + if (instance == null) { + InputStream is = DataSourceFactory.class.getClassLoader().getResourceAsStream("application.properties"); + Properties properties = new Properties(); + properties.load(is); + + HikariConfig config = new HikariConfig(); + if (properties.containsKey("jdbc.driver")) { +// String driverName = properties.getProperty("jdbc.driver"); +// System.out.println(">>> load driver : " + driverName); +// try { +// Class.forName(driverName); +// } catch (ClassNotFoundException e) { +// e.printStackTrace(); +// } + config.setDriverClassName(properties.getProperty("jdbc.driver")); + } else { + config.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + } + if ("com.taosdata.jdbc.rs.RestfulDriver".equalsIgnoreCase(properties.getProperty("jdbc.driver"))) + config.setJdbcUrl("jdbc:TAOS-RS://" + host + ":6041/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8"); + else + config.setJdbcUrl("jdbc:TAOS://" + host + ":" + port + "/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8"); + config.setUsername(user); + config.setPassword(password); + // maximum-pool-size + if (properties.containsKey("hikari.maximum-pool-size")) + config.setMaximumPoolSize(Integer.parseInt(properties.getProperty("hikari.maximum-pool-size"))); + else + config.setMaximumPoolSize(500); + // minimum-idle + if (properties.containsKey("hikari.minimum-idle")) + config.setMinimumIdle(Integer.parseInt(properties.getProperty("hikari.minimum-idle"))); + else + config.setMinimumIdle(100); + config.setMaxLifetime(0); + instance = new HikariDataSource(config); + } + } + } + return instance; + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JdbcTaosdemoConfig.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JdbcTaosdemoConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..974a2755a5a029d3a5fc681bc8c59b0aca1a7ca4 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JdbcTaosdemoConfig.java @@ -0,0 +1,221 @@ +package com.taosdata.taosdemo.components; + +import com.taosdata.taosdemo.utils.TimeStampUtil; + +public final class JdbcTaosdemoConfig { + // instance + public String host; //host + public int port = 6030; //port + public String user = "root"; //user + public String password = "taosdata"; //password + // database + public String database = "jdbcdb"; //database + public int keep = 3650; //keep + public int days = 30; //days + public int replica = 1; //replica + public int blocks = 16; + public int cache = 8; + public String precision = "ms"; + + //super table + public boolean doCreateTable = true; + public String superTable = "weather"; //super table name + public String prefixOfFields = "col"; + public int numOfFields; + public String prefixOfTags = "tag"; + public int numOfTags; + public String superTableSQL; + //sub table + public String prefixOfTable = "t"; + // insert task + public boolean autoCreateTable; + public long numOfTables = 10; + public long numOfRowsPerTable = 10; + public int numOfTablesPerSQL = 1; + public int numOfValuesPerSQL = 1; + public int numOfThreadsForCreate = 1; + public int numOfThreadsForInsert = 1; + public long startTime; + public long timeGap = 1; + public int frequency; + public int order; + public int rate = 10; + public long range = 1000l; + // select task + public String executeSql; + // drop task + public boolean dropTable = false; + + public static void printHelp() { + System.out.println("Usage: java -jar jdbc-taosdemo-2.0.jar [OPTION...]"); + // instance + System.out.println("-host The host to connect to TDengine which you must specify"); + System.out.println("-port The TCP/IP port number to use for the connection. Default is 6030"); + System.out.println("-user The TDengine user name to use when connecting to the server. Default is 'root'"); + System.out.println("-password The password to use when connecting to the server.Default is 'taosdata'"); + // database + System.out.println("-database Destination database. Default is 'jdbcdb'"); + System.out.println("-keep database keep parameter. Default is 3650"); + System.out.println("-days database days parameter. Default is 30"); + System.out.println("-replica database replica parameter. Default 1, min: 1, max: 3"); + System.out.println("-blocks database blocks parameter. Default is 16"); + System.out.println("-cache database cache parameter. Default is 8"); + System.out.println("-precision database precision parameter. Default is ms"); + + // super table + System.out.println("-doCreateTable do create super table and sub table, true or false, Default true"); + System.out.println("-superTable super table name. Default 'weather'"); + System.out.println("-prefixOfFields The prefix of field in super table. Default is 'col'"); + System.out.println("-numOfFields The number of field in super table. Default is (ts timestamp, temperature float, humidity int)."); + System.out.println("-prefixOfTags The prefix of tag in super table. Default is 'tag'"); + System.out.println("-numOfTags The number of tag in super table. Default is (location nchar(64), groupId int)."); + System.out.println("-superTableSQL specify a sql statement for the super table.\n" + + " Default is 'create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int). \n" + + " if you use this parameter, the numOfFields and numOfTags will be invalid'"); + // sub table + System.out.println("-prefixOfTable The prefix of sub tables. Default is 't'"); + System.out.println("-numOfTables The number of tables. Default is 1"); + System.out.println("-numOfThreadsForCreate The number of thread during create sub table. Default is 1"); + // insert task + System.out.println("-autoCreateTable Use auto Create sub tables SQL. Default is false"); + System.out.println("-numOfRowsPerTable The number of records per table. Default is 1"); + System.out.println("-numOfThreadsForInsert The number of threads during insert row. Default is 1"); + System.out.println("-numOfTablesPerSQL The number of table per SQL. Default is 1"); + System.out.println("-numOfValuesPerSQL The number of value per SQL. Default is 1"); + System.out.println("-startTime start time for insert task, The format is \"yyyy-MM-dd HH:mm:ss.SSS\"."); + System.out.println("-timeGap the number of time gap. Default is 1000 ms"); + System.out.println("-frequency the number of records per second inserted into one table. default is 0, do not control frequency"); + System.out.println("-order Insert mode--0: In order, 1: Out of order. Default is in order"); + System.out.println("-rate The proportion of data out of order. effective only if order is 1. min 0, max 100, default is 10"); + System.out.println("-range The range of data out of order. effective only if order is 1. default is 1000 ms"); + // query task + System.out.println("-executeSql execute a specific sql."); + // drop task + System.out.println("-dropTable Drop data before quit. Default is false"); + System.out.println("--help Give this help list"); + } + + /** + * parse args from command line + * + * @param args command line args + * @return JdbcTaosdemoConfig + */ + public JdbcTaosdemoConfig(String[] args) { + for (int i = 0; i < args.length; i++) { + // instance + if ("-host".equals(args[i]) && i < args.length - 1) { + host = args[++i]; + } + if ("-port".equals(args[i]) && i < args.length - 1) { + port = Integer.parseInt(args[++i]); + } + if ("-user".equals(args[i]) && i < args.length - 1) { + user = args[++i]; + } + if ("-password".equals(args[i]) && i < args.length - 1) { + password = args[++i]; + } + // database + if ("-database".equals(args[i]) && i < args.length - 1) { + database = args[++i]; + } + if ("-keep".equals(args[i]) && i < args.length - 1) { + keep = Integer.parseInt(args[++i]); + } + if ("-days".equals(args[i]) && i < args.length - 1) { + days = Integer.parseInt(args[++i]); + } + if ("-replica".equals(args[i]) && i < args.length - 1) { + replica = Integer.parseInt(args[++i]); + } + if ("-blocks".equals(args[i]) && i < args.length - 1) { + blocks = Integer.parseInt(args[++i]); + } + if ("-cache".equals(args[i]) && i < args.length - 1) { + cache = Integer.parseInt(args[++i]); + } + if ("-precision".equals(args[i]) && i < args.length - 1) { + precision = args[++i]; + } + // super table + if ("-doCreateTable".equals(args[i]) && i < args.length - 1) { + doCreateTable = Boolean.parseBoolean(args[++i]); + } + if ("-superTable".equals(args[i]) && i < args.length - 1) { + superTable = args[++i]; + } + if ("-prefixOfFields".equals(args[i]) && i < args.length - 1) { + prefixOfFields = args[++i]; + } + if ("-numOfFields".equals(args[i]) && i < args.length - 1) { + numOfFields = Integer.parseInt(args[++i]); + } + if ("-prefixOfTags".equals(args[i]) && i < args.length - 1) { + prefixOfTags = args[++i]; + } + if ("-numOfTags".equals(args[i]) && i < args.length - 1) { + numOfTags = Integer.parseInt(args[++i]); + } + if ("-superTableSQL".equals(args[i]) && i < args.length - 1) { + superTableSQL = args[++i]; + } + // sub table + if ("-prefixOfTable".equals(args[i]) && i < args.length - 1) { + prefixOfTable = args[++i]; + } + if ("-numOfTables".equals(args[i]) && i < args.length - 1) { + numOfTables = Long.parseLong(args[++i]); + } + if ("-autoCreateTable".equals(args[i]) && i < args.length - 1) { + autoCreateTable = Boolean.parseBoolean(args[++i]); + } + if ("-numOfThreadsForCreate".equals(args[i]) && i < args.length - 1) { + numOfThreadsForCreate = Integer.parseInt(args[++i]); + } + // insert task + if ("-numOfRowsPerTable".equals(args[i]) && i < args.length - 1) { + numOfRowsPerTable = Long.parseLong(args[++i]); + } + if ("-numOfThreadsForInsert".equals(args[i]) && i < args.length - 1) { + numOfThreadsForInsert = Integer.parseInt(args[++i]); + } + if ("-numOfTablesPerSQL".equals(args[i]) && i < args.length - 1) { + numOfTablesPerSQL = Integer.parseInt(args[++i]); + } + if ("-numOfValuesPerSQL".equals(args[i]) && i < args.length - 1) { + numOfValuesPerSQL = Integer.parseInt(args[++i]); + } + if ("-startTime".equals(args[i]) && i < args.length - 1) { + startTime = TimeStampUtil.datetimeToLong(args[++i]); + } + if ("-timeGap".equals(args[i]) && i < args.length - 1) { + timeGap = Long.parseLong(args[++i]); + } + if ("-frequency".equals(args[i]) && i < args.length - 1) { + frequency = Integer.parseInt(args[++i]); + } + if ("-order".equals(args[i]) && i < args.length - 1) { + order = Integer.parseInt(args[++i]); + } + if ("-rate".equals(args[i]) && i < args.length - 1) { + rate = Integer.parseInt(args[++i]); + if (rate < 0 || rate > 100) + throw new IllegalArgumentException("rate must between 0 and 100"); + } + if ("-range".equals(args[i]) && i < args.length - 1) { + range = Integer.parseInt(args[++i]); + } + // select task + if ("-executeSql".equals(args[i]) && i < args.length - 1) { + executeSql = args[++i]; + } + + // drop task + if ("-dropTable".equals(args[i]) && i < args.length - 1) { + dropTable = Boolean.parseBoolean(args[++i]); + } + } + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JsonConfig.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JsonConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..1c44610095f4b383f82a74dfdc11030a28afb246 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/components/JsonConfig.java @@ -0,0 +1,39 @@ +package com.taosdata.taosdemo.components; + +import com.alibaba.fastjson.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class JsonConfig { + + public static void main(String[] args) { + + JsonConfig config = new JsonConfig(); + String str = config.read("insert.json"); + JSONObject jsonObject = JSONObject.parseObject(str); + System.out.println(jsonObject); + + } + + private String read(String fileName) { + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(JsonConfig.class.getClassLoader().getResourceAsStream(fileName)) + ); + StringBuilder sb = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } catch (IOException e) { + e.printStackTrace(); + } + + return fileName; + } + + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapper.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..56e38d2bfce8ba5801d0f8dc48093d198852fbca --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapper.java @@ -0,0 +1,23 @@ +package com.taosdata.taosdemo.dao; + +import java.util.Map; + +public interface DatabaseMapper { + + // create database if not exists XXX + void createDatabase(String dbname); + + // drop database if exists XXX + void dropDatabase(String dbname); + + // create database if not exists XXX keep XX days XX replica XX + void createDatabaseWithParameters(Map map); + + // use XXX + void useDatabase(String dbname); + + //TODO: alter database + + //TODO: show database + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapperImpl.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapperImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..9340fc3fdd0ce7242d4121a5fb259af48f7ada5f --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/DatabaseMapperImpl.java @@ -0,0 +1,48 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.utils.SqlSpeller; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; +import java.util.Map; + +public class DatabaseMapperImpl implements DatabaseMapper { + private static final Logger logger = LogManager.getLogger(DatabaseMapperImpl.class); + + private final JdbcTemplate jdbcTemplate; + + public DatabaseMapperImpl(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Override + public void createDatabase(String dbname) { + String sql = "create database if not exists " + dbname; + jdbcTemplate.execute(sql); + logger.debug("SQL >>> " + sql); + } + + @Override + public void dropDatabase(String dbname) { + String sql = "drop database if exists " + dbname; + jdbcTemplate.update(sql); + logger.debug("SQL >>> " + sql); + } + + @Override + public void createDatabaseWithParameters(Map map) { + String sql = SqlSpeller.createDatabase(map); + jdbcTemplate.execute(sql); + logger.debug("SQL >>> " + sql); + } + + @Override + public void useDatabase(String dbname) { + String sql = "use " + dbname; + jdbcTemplate.execute(sql); + logger.debug("SQL >>> " + sql); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapper.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e0ddd220c19066afd1cc332f007a82e2fdab2b07 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapper.java @@ -0,0 +1,29 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.SubTableValue; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface SubTableMapper { + + // 创建:子表 + void createUsingSuperTable(SubTableMeta subTableMeta); + + // 插入:一张子表多个values + int insertOneTableMultiValues(SubTableValue subTableValue); + + // 插入:一张子表多个values, 自动建表 + int insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue); + + // 插入:多张表多个values + int insertMultiTableMultiValues(List tables); + + // 插入:多张表多个values,自动建表 + int insertMultiTableMultiValuesUsingSuperTable(List tables); + + // + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapperImpl.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapperImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..db0d43ff05a56b673ed08a522b645d3388f8e091 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SubTableMapperImpl.java @@ -0,0 +1,82 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.SubTableValue; +import com.taosdata.taosdemo.utils.SqlSpeller; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; +import java.util.List; + +public class SubTableMapperImpl implements SubTableMapper { + + private static final Logger logger = LogManager.getLogger(SubTableMapperImpl.class); + private final JdbcTemplate jdbcTemplate; + + public SubTableMapperImpl(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public void createUsingSuperTable(SubTableMeta subTableMeta) { + String sql = SqlSpeller.createTableUsingSuperTable(subTableMeta); + logger.debug("SQL >>> " + sql); + jdbcTemplate.execute(sql); + } + + @Override + public int insertOneTableMultiValues(SubTableValue subTableValue) { + String sql = SqlSpeller.insertOneTableMultiValues(subTableValue); + logger.debug("SQL >>> " + sql); + + int affectRows = 0; + try { + affectRows = jdbcTemplate.update(sql); + } catch (Exception e) { + e.printStackTrace(); + } + return affectRows; + } + + @Override + public int insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue) { + String sql = SqlSpeller.insertOneTableMultiValuesUsingSuperTable(subTableValue); + logger.debug("SQL >>> " + sql); + + int affectRows = 0; + try { + affectRows = jdbcTemplate.update(sql); + } catch (Exception e) { + e.printStackTrace(); + } + return affectRows; + } + + @Override + public int insertMultiTableMultiValues(List tables) { + String sql = SqlSpeller.insertMultiSubTableMultiValues(tables); + logger.debug("SQL >>> " + sql); + int affectRows = 0; + try { + affectRows = jdbcTemplate.update(sql); + } catch (Exception e) { + e.printStackTrace(); + } + return affectRows; + } + + @Override + public int insertMultiTableMultiValuesUsingSuperTable(List tables) { + String sql = SqlSpeller.insertMultiTableMultiValuesUsingSuperTable(tables); + logger.debug("SQL >>> " + sql); + int affectRows = 0; + try { + affectRows = jdbcTemplate.update(sql); + } catch (Exception e) { + e.printStackTrace(); + } + return affectRows; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapper.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..9f8cec9e8fa5af8741d9efbdce72f240aa7a09aa --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapper.java @@ -0,0 +1,29 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.SuperTableMeta; +import org.springframework.stereotype.Repository; + +@Repository +public interface SuperTableMapper { + + // 创建超级表 create table if not exists xxx.xxx (f1 type1, f2 type2, ... ) tags( t1 type1, t2 type2 ...) + void createSuperTable(SuperTableMeta tableMetadata); + + // 删除超级表 drop table if exists xxx; + void dropSuperTable(String database, String name); + + // + + // + + // + + // + + // + + // + + // + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapperImpl.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapperImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..658a403a0ca3883831bca1ad2b6d579ef4713f7d --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/SuperTableMapperImpl.java @@ -0,0 +1,32 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.utils.SqlSpeller; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +public class SuperTableMapperImpl implements SuperTableMapper { + private static final Logger logger = LogManager.getLogger(SuperTableMapperImpl.class); + private JdbcTemplate jdbcTemplate; + + public SuperTableMapperImpl(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public void createSuperTable(SuperTableMeta tableMetadata) { + String sql = SqlSpeller.createSuperTable(tableMetadata); + logger.debug("SQL >>> " + sql); + jdbcTemplate.execute(sql); + } + + @Override + public void dropSuperTable(String database, String name) { + String sql = "drop table if exists " + database + "." + name; + logger.debug("SQL >>> " + sql); + jdbcTemplate.execute(sql); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapper.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..32d1875e4d1a82f7dfb658d68ed0e63a5cbfa040 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapper.java @@ -0,0 +1,27 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.TableMeta; +import com.taosdata.taosdemo.domain.TableValue; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface TableMapper { + + // 创建:普通表 + void create(TableMeta tableMeta); + + // 插入:一张表多个value + int insertOneTableMultiValues(TableValue values); + + // 插入: 一张表多个value,指定的列 + int insertOneTableMultiValuesWithColumns(TableValue values); + + // 插入:多个表多个value + int insertMultiTableMultiValues(List tables); + + // 插入:多个表多个value, 指定的列 + int insertMultiTableMultiValuesWithColumns(List tables); + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapperImpl.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapperImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..16bc094848f6ff585e826bf3181cc4e8c03ee822 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/dao/TableMapperImpl.java @@ -0,0 +1,50 @@ +package com.taosdata.taosdemo.dao; + +import com.taosdata.taosdemo.domain.TableMeta; +import com.taosdata.taosdemo.domain.TableValue; +import com.taosdata.taosdemo.utils.SqlSpeller; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; + +public class TableMapperImpl implements TableMapper { + private static final Logger logger = LogManager.getLogger(TableMapperImpl.class); + private JdbcTemplate template; + + @Override + public void create(TableMeta tableMeta) { + String sql = SqlSpeller.createTable(tableMeta); + logger.debug("SQL >>> " + sql); + template.execute(sql); + } + + @Override + public int insertOneTableMultiValues(TableValue values) { + String sql = SqlSpeller.insertOneTableMultiValues(values); + logger.debug("SQL >>> " + sql); + return template.update(sql); + } + + @Override + public int insertOneTableMultiValuesWithColumns(TableValue values) { + String sql = SqlSpeller.insertOneTableMultiValuesWithColumns(values); + logger.debug("SQL >>> " + sql); + return template.update(sql); + } + + @Override + public int insertMultiTableMultiValues(List tables) { + String sql = SqlSpeller.insertMultiTableMultiValues(tables); + logger.debug("SQL >>> " + sql); + return template.update(sql); + } + + @Override + public int insertMultiTableMultiValuesWithColumns(List tables) { + String sql = SqlSpeller.insertMultiTableMultiValuesWithColumns(tables); + logger.debug("SQL >>> " + sql); + return template.update(sql); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldMeta.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..8a45e99989821562fdf9333b90a2972388cf6003 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldMeta.java @@ -0,0 +1,17 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +@Data +public class FieldMeta { + private String name; + private String type; + + public FieldMeta() { + } + + public FieldMeta(String name, String type) { + this.name = name; + this.type = type; + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldValue.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldValue.java new file mode 100644 index 0000000000000000000000000000000000000000..44805c0d7c2f4e0df60d723afd598f2aa788ee65 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/FieldValue.java @@ -0,0 +1,17 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +@Data +public class FieldValue { + private String name; + private T value; + + public FieldValue() { + } + + public FieldValue(String name, T value) { + this.name = name; + this.value = value; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/RowValue.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/RowValue.java new file mode 100644 index 0000000000000000000000000000000000000000..a444fa78dcdeb8f1bb76974a29051c98348a055b --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/RowValue.java @@ -0,0 +1,14 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class RowValue { + private List fields; + + public RowValue(List fields) { + this.fields = fields; + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableMeta.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..81de882448121532a3c840296702d1fb24c37326 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableMeta.java @@ -0,0 +1,15 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class SubTableMeta { + + private String database; + private String supertable; + private String name; + private List tags; + private List fields; +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableValue.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableValue.java new file mode 100644 index 0000000000000000000000000000000000000000..74fb9598bc8e920123180f948b88fb98baf9218e --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SubTableValue.java @@ -0,0 +1,15 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class SubTableValue { + + private String database; + private String supertable; + private String name; + private List tags; + private List values; +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SuperTableMeta.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SuperTableMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..c5c65a4599b776faeead19ffbf065361b293b44b --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/SuperTableMeta.java @@ -0,0 +1,14 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class SuperTableMeta { + + private String database; + private String name; + private List fields; + private List tags; +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableMeta.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..3ab0a75c0b8ddda46f016c93e0a4893ff1ef21fa --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableMeta.java @@ -0,0 +1,13 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class TableMeta { + + private String database; + private String name; + private List fields; +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableValue.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableValue.java new file mode 100644 index 0000000000000000000000000000000000000000..d5502aa46f3508d2f6dcc3668e741adde5b0a4f0 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TableValue.java @@ -0,0 +1,15 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +import java.util.List; + +@Data +public class TableValue { + + private String database; + private String name; + private List columns; + private List values; + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagMeta.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..a385bb4e125e46fe37c1f9542817a4d81301d72f --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagMeta.java @@ -0,0 +1,18 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +@Data +public class TagMeta { + private String name; + private String type; + + public TagMeta() { + + } + + public TagMeta(String name, String type) { + this.name = name; + this.type = type; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagValue.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagValue.java new file mode 100644 index 0000000000000000000000000000000000000000..98ea8c0dc97ebfd330c57f8852eaf2fa379aef50 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/domain/TagValue.java @@ -0,0 +1,17 @@ +package com.taosdata.taosdemo.domain; + +import lombok.Data; + +@Data +public class TagValue { + private String name; + private T value; + + public TagValue() { + } + + public TagValue(String name, T value) { + this.name = name; + this.value = value; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/AbstractService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/AbstractService.java new file mode 100644 index 0000000000000000000000000000000000000000..4afbe9dae82516e050eb7d729d6ecb8eb1e59d6b --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/AbstractService.java @@ -0,0 +1,35 @@ +package com.taosdata.taosdemo.service; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class AbstractService { + + protected int getAffectRows(List> futureList) { + int count = 0; + for (Future future : futureList) { + try { + count += future.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + return count; + } + + protected int getAffectRows(Future future) { + int count = 0; + try { + count += future.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return count; + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/DatabaseService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/DatabaseService.java new file mode 100644 index 0000000000000000000000000000000000000000..3c8e9624066bf629a74ebcaa3959a2e15338c363 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/DatabaseService.java @@ -0,0 +1,42 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.dao.DatabaseMapper; +import com.taosdata.taosdemo.dao.DatabaseMapperImpl; + +import javax.sql.DataSource; +import java.util.Map; + +public class DatabaseService { + + private final DatabaseMapper databaseMapper; + + public DatabaseService(DataSource dataSource) { + this.databaseMapper = new DatabaseMapperImpl(dataSource); + } + + // 建库,指定 name + public void createDatabase(String database) { + databaseMapper.createDatabase(database); + } + + // 建库,指定参数 keep,days,replica等 + public void createDatabase(Map map) { + if (map.isEmpty()) + return; + if (map.containsKey("database") && map.size() == 1) { + createDatabase(map.get("database")); + return; + } + databaseMapper.createDatabaseWithParameters(map); + } + + // drop database + public void dropDatabase(String dbname) { + databaseMapper.dropDatabase(dbname); + } + + // use database + public void useDatabase(String dbname) { + databaseMapper.useDatabase(dbname); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/QueryService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/QueryService.java new file mode 100644 index 0000000000000000000000000000000000000000..efabff6afe904516ad9682cd7197412dc02765ef --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/QueryService.java @@ -0,0 +1,104 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.jdbc.utils.SqlSyntaxValidator; + +import javax.sql.DataSource; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class QueryService { + + private final DataSource dataSource; + + public QueryService(DataSource dataSource) { + this.dataSource = dataSource; + } + + /* only select or show SQL Statement is valid for executeQuery */ + public Boolean[] areValidQueries(String[] sqls) { + Boolean[] ret = new Boolean[sqls.length]; + for (int i = 0; i < sqls.length; i++) { + ret[i] = true; + if (!SqlSyntaxValidator.isValidForExecuteQuery(sqls[i])) { + ret[i] = false; + continue; + } + try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { + stmt.executeQuery(sqls[i]); + } catch (SQLException e) { + ret[i] = false; + continue; + } + } + return ret; + } + + public String[] generateSuperTableQueries(String dbName) { + List sqls = new ArrayList<>(); + try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { + stmt.execute("use " + dbName); + ResultSet rs = stmt.executeQuery("show stables"); + while (rs.next()) { + String name = rs.getString("name"); + sqls.add("select count(*) from " + dbName + "." + name); + sqls.add("select first(*) from " + dbName + "." + name); + sqls.add("select last(*) from " + dbName + "." + name); + sqls.add("select last_row(*) from " + dbName + "." + name); + } + } catch (SQLException e) { + e.printStackTrace(); + } + String[] sqlArr = new String[sqls.size()]; + return sqls.toArray(sqlArr); + } + + public void querySuperTable(String[] sqls, int interval, int threadCount, long queryTimes) { + List threads = IntStream.range(0, threadCount).mapToObj(i -> new Thread(() -> { + // do query + try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { + long count = queryTimes; + if (count == 0) + count = Long.MAX_VALUE; + while (count > 0) { + for (String sql : sqls) { + long start = System.currentTimeMillis(); + ResultSet rs = stmt.executeQuery(sql); + printResultSet(rs); + long end = System.currentTimeMillis(); + long timecost = end - start; + if (interval - timecost > 0) { + TimeUnit.MILLISECONDS.sleep(interval - timecost); + } + } + count--; + } + + } catch (SQLException | InterruptedException e) { + e.printStackTrace(); + } + + })).collect(Collectors.toList()); + threads.stream().forEach(Thread::start); + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void printResultSet(ResultSet rs) throws SQLException { + ResultSetMetaData meta = rs.getMetaData(); + while (rs.next()) { + for (int i = 1; i <= meta.getColumnCount(); i++) { + System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t"); + } + System.out.println(); + } + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SqlExecuteTask.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SqlExecuteTask.java new file mode 100644 index 0000000000000000000000000000000000000000..ff2e4d0af068a10e62933837817d2d2df0712a4c --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SqlExecuteTask.java @@ -0,0 +1,36 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.utils.Printer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class SqlExecuteTask implements Runnable { + private final DataSource dataSource; + private final String sql; + + public SqlExecuteTask(DataSource dataSource, String sql) { + this.dataSource = dataSource; + this.sql = sql; + } + + @Override + public void run() { + try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { + long start = System.currentTimeMillis(); + boolean execute = stmt.execute(sql); + long end = System.currentTimeMillis(); + if (execute) { + ResultSet rs = stmt.getResultSet(); + Printer.printResult(rs); + } else { + Printer.printSql(sql, true, (end - start)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SubTableService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SubTableService.java new file mode 100644 index 0000000000000000000000000000000000000000..b0a79dea78f429d85804bae4cb0bbec9e712ec1a --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SubTableService.java @@ -0,0 +1,209 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.components.JdbcTaosdemoConfig; +import com.taosdata.taosdemo.dao.SubTableMapper; +import com.taosdata.taosdemo.dao.SubTableMapperImpl; +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.SubTableValue; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.service.data.SubTableMetaGenerator; +import com.taosdata.taosdemo.service.data.SubTableValueGenerator; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import javax.sql.DataSource; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class SubTableService extends AbstractService { + + private SubTableMapper mapper; + private static final Logger logger = LogManager.getLogger(SubTableService.class); + + public SubTableService(DataSource datasource) { + this.mapper = new SubTableMapperImpl(datasource); + } + + public void createSubTable(SuperTableMeta superTableMeta, long numOfTables, String prefixOfTable, int numOfThreadsForCreate) { + ExecutorService executor = Executors.newFixedThreadPool(numOfThreadsForCreate); + for (long i = 0; i < numOfTables; i++) { + long tableIndex = i; + executor.execute(() -> createSubTable(superTableMeta, prefixOfTable + (tableIndex + 1))); + } + executor.shutdown(); + try { + executor.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void createSubTable(SuperTableMeta superTableMeta, String tableName) { + // 构造数据 + SubTableMeta meta = SubTableMetaGenerator.generate(superTableMeta, tableName); + createSubTable(meta); + } + + // 创建一张子表,可以指定database,supertable,tablename,tag值 + public void createSubTable(SubTableMeta subTableMeta) { + mapper.createUsingSuperTable(subTableMeta); + } + + /*************************************************************************************************************************/ + // 插入:多线程,多表 + public int insert(List subTableValues, int threadSize, int frequency) { + ExecutorService executor = Executors.newFixedThreadPool(threadSize); + Future future = executor.submit(() -> insert(subTableValues)); + executor.shutdown(); + //TODO:frequency + return getAffectRows(future); + } + + // 插入:单表,insert into xxx values(),()... + public int insert(SubTableValue subTableValue) { + return mapper.insertOneTableMultiValues(subTableValue); + } + + // 插入: 多表,insert into xxx values(),()... xxx values(),()... + public int insert(List subTableValues) { + return mapper.insertMultiTableMultiValues(subTableValues); + } + + // 插入:单表,自动建表, insert into xxx using xxx tags(...) values(),()... + public int insertAutoCreateTable(SubTableValue subTableValue) { + return mapper.insertOneTableMultiValuesUsingSuperTable(subTableValue); + } + + // 插入:多表,自动建表, insert into xxx using XXX tags(...) values(),()... xxx using XXX tags(...) values(),()... + public int insertAutoCreateTable(List subTableValues) { + return mapper.insertMultiTableMultiValuesUsingSuperTable(subTableValues); + } + + public int insertMultiThreads(SuperTableMeta superTableMeta, int threadSize, long tableSize, long startTime, long gap, JdbcTaosdemoConfig config) { + List taskList = new ArrayList<>(); + List threads = IntStream.range(0, threadSize) + .mapToObj(i -> { + long startInd = i * gap; + long endInd = (i + 1) * gap < tableSize ? (i + 1) * gap : tableSize; + FutureTask task = new FutureTask<>( + new InsertTask(superTableMeta, + startInd, endInd, + startTime, config.timeGap, + config.numOfRowsPerTable, config.numOfTablesPerSQL, config.numOfValuesPerSQL, + config.order, config.rate, config.range, + config.prefixOfTable, config.autoCreateTable) + ); + taskList.add(task); + return new Thread(task, "InsertThread-" + i); + }).collect(Collectors.toList()); + + threads.stream().forEach(Thread::start); + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + int affectedRows = 0; + for (FutureTask task : taskList) { + try { + affectedRows += task.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + return affectedRows; + } + + private class InsertTask implements Callable { + + private final long startTableInd; // included + private final long endTableInd; // excluded + private final long startTime; + private final long timeGap; + private final long numOfRowsPerTable; + private long numOfTablesPerSQL; + private long numOfValuesPerSQL; + private final SuperTableMeta superTableMeta; + private final int order; + private final int rate; + private final long range; + private final String prefixOfTable; + private final boolean autoCreateTable; + + public InsertTask(SuperTableMeta superTableMeta, long startTableInd, long endTableInd, + long startTime, long timeGap, + long numOfRowsPerTable, long numOfTablesPerSQL, long numOfValuesPerSQL, + int order, int rate, long range, + String prefixOfTable, boolean autoCreateTable) { + this.superTableMeta = superTableMeta; + this.startTableInd = startTableInd; + this.endTableInd = endTableInd; + this.startTime = startTime; + this.timeGap = timeGap; + this.numOfRowsPerTable = numOfRowsPerTable; + this.numOfTablesPerSQL = numOfTablesPerSQL; + this.numOfValuesPerSQL = numOfValuesPerSQL; + this.order = order; + this.rate = rate; + this.range = range; + this.prefixOfTable = prefixOfTable; + this.autoCreateTable = autoCreateTable; + } + + + @Override + public Integer call() { + + long numOfTables = endTableInd - startTableInd; + if (numOfRowsPerTable < numOfValuesPerSQL) + numOfValuesPerSQL = (int) numOfRowsPerTable; + if (numOfTables < numOfTablesPerSQL) + numOfTablesPerSQL = (int) numOfTables; + + int affectRows = 0; + // row + for (long rowCnt = 0; rowCnt < numOfRowsPerTable; ) { + long rowSize = numOfValuesPerSQL; + if (rowCnt + rowSize > numOfRowsPerTable) { + rowSize = numOfRowsPerTable - rowCnt; + } + //table + for (long tableCnt = startTableInd; tableCnt < endTableInd; ) { + long tableSize = numOfTablesPerSQL; + if (tableCnt + tableSize > endTableInd) { + tableSize = endTableInd - tableCnt; + } + long startTime = this.startTime + rowCnt * timeGap; +// System.out.println(Thread.currentThread().getName() + " >>> " + "rowCnt: " + rowCnt + ", rowSize: " + rowSize + ", " + "tableCnt: " + tableCnt + ",tableSize: " + tableSize + ", " + "startTime: " + startTime + ",timeGap: " + timeGap + ""); + /***********************************************/ + // 生成数据 + List data = SubTableValueGenerator.generate(superTableMeta, prefixOfTable, tableCnt, tableSize, rowSize, startTime, timeGap); + // 乱序 + if (order != 0) + SubTableValueGenerator.disrupt(data, rate, range); + // insert + if (autoCreateTable) + affectRows += insertAutoCreateTable(data); + else + affectRows += insert(data); + /***********************************************/ + tableCnt += tableSize; + } + rowCnt += rowSize; + } + + return affectRows; + } + } + + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SuperTableService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SuperTableService.java new file mode 100644 index 0000000000000000000000000000000000000000..b91348e2d008bc1ac32faffc5912a8509adf42bd --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/SuperTableService.java @@ -0,0 +1,25 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.dao.SuperTableMapper; +import com.taosdata.taosdemo.dao.SuperTableMapperImpl; +import com.taosdata.taosdemo.domain.SuperTableMeta; + +import javax.sql.DataSource; + +public class SuperTableService { + + private SuperTableMapper superTableMapper; + + public SuperTableService(DataSource dataSource) { + this.superTableMapper = new SuperTableMapperImpl(dataSource); + } + + // 创建超级表,指定每个field的名称和类型,每个tag的名称和类型 + public void create(SuperTableMeta superTableMeta) { + superTableMapper.createSuperTable(superTableMeta); + } + + public void drop(String database, String name) { + superTableMapper.dropSuperTable(database, name); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/TableService.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/TableService.java new file mode 100644 index 0000000000000000000000000000000000000000..2504fdb0b4cd48ec263d94ec377e1bb8902ea9a7 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/TableService.java @@ -0,0 +1,25 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.dao.TableMapper; +import com.taosdata.taosdemo.domain.TableMeta; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class TableService extends AbstractService { + + private TableMapper tableMapper; + + //创建一张表 + public void create(TableMeta tableMeta) { + tableMapper.create(tableMeta); + } + + //创建多张表 + public void create(List tables) { + tables.stream().forEach(this::create); + } + + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/FieldValueGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/FieldValueGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..73cd981a4651bf589d636b8f57c0af44979f09f1 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/FieldValueGenerator.java @@ -0,0 +1,48 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.FieldValue; +import com.taosdata.taosdemo.domain.RowValue; +import com.taosdata.taosdemo.utils.DataGenerator; + +import java.util.*; + +public class FieldValueGenerator { + + public static Random random = new Random(System.currentTimeMillis()); + + // 生成start到end的时间序列,时间戳为顺序,不含有乱序,field的value为随机生成 + public static List generate(long start, long end, long timeGap, List fieldMetaList) { + List values = new ArrayList<>(); + + for (long ts = start; ts < end; ts += timeGap) { + List fieldValues = new ArrayList<>(); + // timestamp + fieldValues.add(new FieldValue(fieldMetaList.get(0).getName(), ts)); + // other values + for (int fieldInd = 1; fieldInd < fieldMetaList.size(); fieldInd++) { + FieldMeta fieldMeta = fieldMetaList.get(fieldInd); + fieldValues.add(new FieldValue(fieldMeta.getName(), DataGenerator.randomValue(fieldMeta.getType()))); + } + values.add(new RowValue(fieldValues)); + } + return values; + } + + // 生成start到end的时间序列,时间戳为顺序,含有乱序,rate为乱序的比例,range为乱序前跳范围,field的value为随机生成 + public static List disrupt(List values, int rate, long range) { + long timeGap = (long) (values.get(1).getFields().get(0).getValue()) - (long) (values.get(0).getFields().get(0).getValue()); + int bugSize = values.size() * rate / 100; + Set bugIndSet = new HashSet<>(); + while (bugIndSet.size() < bugSize) { + bugIndSet.add(random.nextInt(values.size())); + } + for (Integer bugInd : bugIndSet) { + Long timestamp = (Long) values.get(bugInd).getFields().get(0).getValue(); + Long newTimestamp = timestamp - timeGap - random.nextInt((int) range); + values.get(bugInd).getFields().get(0).setValue(newTimestamp); + } + + return values; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableMetaGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableMetaGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..88e3c0d26a5a7558c1c07f0fc38ae21710438dbe --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableMetaGenerator.java @@ -0,0 +1,42 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.domain.TagValue; + +import java.util.ArrayList; +import java.util.List; + +public class SubTableMetaGenerator { + + // 创建tableSize张子表,使用tablePrefix作为子表名的前缀,使用superTableMeta的元数据 + // create table xxx using XXX tags(XXX) + public static List generate(SuperTableMeta superTableMeta, int tableSize, String tablePrefix) { + List subTableMetaList = new ArrayList<>(); + for (int i = 1; i <= tableSize; i++) { + SubTableMeta subTableMeta = new SubTableMeta(); + // create table xxx.xxx using xxx tags(...) + subTableMeta.setDatabase(superTableMeta.getDatabase()); + subTableMeta.setName(tablePrefix + i); + subTableMeta.setSupertable(superTableMeta.getName()); + subTableMeta.setFields(superTableMeta.getFields()); + List tagValues = TagValueGenerator.generate(superTableMeta.getTags()); + subTableMeta.setTags(tagValues); + subTableMetaList.add(subTableMeta); + } + return subTableMetaList; + } + + public static SubTableMeta generate(SuperTableMeta superTableMeta, String tableName) { + SubTableMeta subTableMeta = new SubTableMeta(); + // create table xxx.xxx using xxx tags(...) + subTableMeta.setDatabase(superTableMeta.getDatabase()); + subTableMeta.setName(tableName); + subTableMeta.setSupertable(superTableMeta.getName()); + subTableMeta.setFields(superTableMeta.getFields()); + List tagValues = TagValueGenerator.generate(superTableMeta.getTags()); + subTableMeta.setTags(tagValues); + return subTableMeta; + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableValueGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableValueGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..8c318dbd3abf2ddfec8b51e83f32246421c49d51 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SubTableValueGenerator.java @@ -0,0 +1,100 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.*; +import com.taosdata.taosdemo.utils.TimeStampUtil; +import org.springframework.beans.BeanUtils; + +import java.util.ArrayList; +import java.util.List; + +public class SubTableValueGenerator { + + public static List generate(SuperTableMeta superTableMeta, String prefixOfTables, long tableIndex, long tableSize, long valueSize, long startTime, long timeGap) { + List subTableValues = new ArrayList<>(); + for (int i = 1; i <= tableSize; i++) { + SubTableValue subTableValue = new SubTableValue(); + subTableValue.setDatabase(superTableMeta.getDatabase()); + subTableValue.setName(prefixOfTables + (tableIndex + i)); + subTableValue.setSupertable(superTableMeta.getName()); + TimeStampUtil.TimeTuple tuple = TimeStampUtil.range(startTime, timeGap, valueSize); + List tags = TagValueGenerator.generate(superTableMeta.getTags()); + subTableValue.setTags(tags); + List values = FieldValueGenerator.generate(tuple.start, tuple.end, tuple.timeGap, superTableMeta.getFields()); + subTableValue.setValues(values); + + subTableValues.add(subTableValue); + } + return subTableValues; + } + + public static List generate(List subTableMetaList, int numOfRowsPerTable, long start, long timeGap) { + return generate(subTableMetaList, 0, subTableMetaList.size(), numOfRowsPerTable, start, timeGap); + } + + public static void disrupt(List subTableValueList, int rate, long range) { + subTableValueList.stream().forEach((tableValue) -> { + List values = tableValue.getValues(); + FieldValueGenerator.disrupt(values, rate, range); + }); + } + + public static List> split(List subTableValueList, int numOfTables, int numOfTablesPerSQL, int numOfRowsPerTable, int numOfValuesPerSQL) { + List> dataList = new ArrayList<>(); + if (numOfRowsPerTable < numOfValuesPerSQL) + numOfValuesPerSQL = numOfRowsPerTable; + if (numOfTables < numOfTablesPerSQL) + numOfTablesPerSQL = numOfTables; + //table + for (int tableCnt = 0; tableCnt < numOfTables; ) { + int tableSize = numOfTablesPerSQL; + if (tableCnt + tableSize > numOfTables) { + tableSize = numOfTables - tableCnt; + } + // row + for (int rowCnt = 0; rowCnt < numOfRowsPerTable; ) { + int rowSize = numOfValuesPerSQL; + if (rowCnt + rowSize > numOfRowsPerTable) { + rowSize = numOfRowsPerTable - rowCnt; + } + // System.out.println("rowCnt: " + rowCnt + ", rowSize: " + rowSize + ", tableCnt: " + tableCnt + ", tableSize: " + tableSize); + // split + List blocks = subTableValueList.subList(tableCnt, tableCnt + tableSize); + List newBlocks = new ArrayList<>(); + for (int i = 0; i < blocks.size(); i++) { + SubTableValue subTableValue = blocks.get(i); + SubTableValue newSubTableValue = new SubTableValue(); + BeanUtils.copyProperties(subTableValue, newSubTableValue); + List values = subTableValue.getValues().subList(rowCnt, rowCnt + rowSize); + newSubTableValue.setValues(values); + newBlocks.add(newSubTableValue); + } + dataList.add(newBlocks); + + rowCnt += rowSize; + } + tableCnt += tableSize; + } + return dataList; + } + + public static void main(String[] args) { + split(null, 99, 10, 99, 10); + } + + public static List generate(List subTableMetaList, int tableCnt, int tableSize, int rowSize, long startTime, long timeGap) { + List subTableValueList = new ArrayList<>(); + for (int i = 0; i < tableSize; i++) { + SubTableMeta subTableMeta = subTableMetaList.get(tableCnt + i); + SubTableValue subTableValue = new SubTableValue(); + subTableValue.setDatabase(subTableMeta.getDatabase()); + subTableValue.setName(subTableMeta.getName()); + subTableValue.setSupertable(subTableMeta.getSupertable()); + subTableValue.setTags(subTableMeta.getTags()); + TimeStampUtil.TimeTuple tuple = TimeStampUtil.range(startTime, timeGap, rowSize); + List values = FieldValueGenerator.generate(tuple.start, tuple.end, tuple.timeGap, subTableMeta.getFields()); + subTableValue.setValues(values); + subTableValueList.add(subTableValue); + } + return subTableValueList; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SuperTableMetaGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SuperTableMetaGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..05aefd01ac8ef5c0bd2d4952e16f557ee7aef8ce --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/SuperTableMetaGenerator.java @@ -0,0 +1,80 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.domain.TagMeta; +import com.taosdata.taosdemo.utils.TaosConstants; + +import java.util.ArrayList; +import java.util.List; + +public class SuperTableMetaGenerator { + + // 创建超级表,使用指定SQL语句 + public static SuperTableMeta generate(String superTableSQL) { + SuperTableMeta tableMeta = new SuperTableMeta(); + // for example : create table superTable (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int) + superTableSQL = superTableSQL.trim().toLowerCase(); + if (!superTableSQL.startsWith("create")) + throw new RuntimeException("invalid create super table SQL"); + + if (superTableSQL.contains("tags")) { + String tagSQL = superTableSQL.substring(superTableSQL.indexOf("tags") + 4).trim(); + tagSQL = tagSQL.substring(tagSQL.indexOf("(") + 1, tagSQL.lastIndexOf(")")); + String[] tagPairs = tagSQL.split(","); + List tagMetaList = new ArrayList<>(); + for (String tagPair : tagPairs) { + String name = tagPair.trim().split("\\s+")[0]; + String type = tagPair.trim().split("\\s+")[1]; + tagMetaList.add(new TagMeta(name, type)); + } + tableMeta.setTags(tagMetaList); + superTableSQL = superTableSQL.substring(0, superTableSQL.indexOf("tags")); + } + if (superTableSQL.contains("(")) { + String fieldSQL = superTableSQL.substring(superTableSQL.indexOf("(") + 1, superTableSQL.indexOf(")")); + String[] fieldPairs = fieldSQL.split(","); + List fieldList = new ArrayList<>(); + for (String fieldPair : fieldPairs) { + String name = fieldPair.trim().split("\\s+")[0]; + String type = fieldPair.trim().split("\\s+")[1]; + fieldList.add(new FieldMeta(name, type)); + } + tableMeta.setFields(fieldList); + superTableSQL = superTableSQL.substring(0, superTableSQL.indexOf("(")); + } + superTableSQL = superTableSQL.substring(superTableSQL.indexOf("table") + 5).trim(); + if (superTableSQL.contains(".")) { + String database = superTableSQL.split("\\.")[0]; + tableMeta.setDatabase(database); + superTableSQL = superTableSQL.substring(superTableSQL.indexOf(".") + 1); + } + tableMeta.setName(superTableSQL.trim()); + + return tableMeta; + } + + // 创建超级表,指定field和tag的个数 + public static SuperTableMeta generate(String database, String name, int fieldSize, String fieldPrefix, int tagSize, String tagPrefix) { + if (fieldSize < 2 || tagSize < 1) { + throw new RuntimeException("create super table but fieldSize less than 2 or tagSize less than 1"); + } + SuperTableMeta tableMetadata = new SuperTableMeta(); + tableMetadata.setDatabase(database); + tableMetadata.setName(name); + // fields + List fields = new ArrayList<>(); + fields.add(new FieldMeta("ts", "timestamp")); + for (int i = 1; i <= fieldSize; i++) { + fields.add(new FieldMeta(fieldPrefix + "" + i, TaosConstants.DATA_TYPES[i % TaosConstants.DATA_TYPES.length])); + } + tableMetadata.setFields(fields); + // tags + List tags = new ArrayList<>(); + for (int i = 1; i <= tagSize; i++) { + tags.add(new TagMeta(tagPrefix + "" + i, TaosConstants.DATA_TYPES[i % TaosConstants.DATA_TYPES.length])); + } + tableMetadata.setTags(tags); + return tableMetadata; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/TagValueGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/TagValueGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..b8024fea45c000d7d0944f0ba2d47449d3907d89 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/service/data/TagValueGenerator.java @@ -0,0 +1,24 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.TagMeta; +import com.taosdata.taosdemo.domain.TagValue; +import com.taosdata.taosdemo.utils.DataGenerator; + +import java.util.ArrayList; +import java.util.List; + +public class TagValueGenerator { + + // 创建标签值:使用tagMetas + public static List generate(List tagMetas) { + List tagValues = new ArrayList<>(); + for (int i = 0; i < tagMetas.size(); i++) { + TagMeta tagMeta = tagMetas.get(i); + TagValue tagValue = new TagValue(); + tagValue.setName(tagMeta.getName()); + tagValue.setValue(DataGenerator.randomValue(tagMeta.getType())); + tagValues.add(tagValue); + } + return tagValues; + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/DataGenerator.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/DataGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..a200d17ef6c4c4987160c9966a50737773153bc9 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/DataGenerator.java @@ -0,0 +1,120 @@ +package com.taosdata.taosdemo.utils; + +import java.util.Random; + +public class DataGenerator { + private static Random random = new Random(System.currentTimeMillis()); + private static final String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + + // "timestamp", "int", "bigint", "float", "double", "binary(64)", "smallint", "tinyint", "bool", "nchar(64)", + + public static Object randomValue(String type) { + int length = 64; + if (type.contains("(")) { + length = Integer.parseInt(type.substring(type.indexOf("(") + 1, type.indexOf(")"))); + type = type.substring(0, type.indexOf("(")); + } + switch (type.trim().toLowerCase()) { + case "timestamp": + return randomTimestamp(); + case "int": + return randomInt(); + case "bigint": + return randomBigint(); + case "float": + return randomFloat(); + case "double": + return randomDouble(); + case "binary": + return randomBinary(length); + case "smallint": + return randomSmallint(); + case "tinyint": + return randomTinyint(); + case "bool": + return randomBoolean(); + case "nchar": + return randomNchar(length); + default: + throw new IllegalArgumentException("Unexpected value: " + type); + } + } + + public static Long randomTimestamp() { + long start = System.currentTimeMillis(); + return randomTimestamp(start, start + 60l * 60l * 1000l); + } + + public static Long randomTimestamp(Long start, Long end) { + return start + (long) random.nextInt((int) (end - start)); + } + + public static String randomNchar(int length) { + return randomChinese(length); + } + + public static Boolean randomBoolean() { + return random.nextBoolean(); + } + + public static Integer randomTinyint() { + return randomInt(-127, 127); + } + + public static Integer randomSmallint() { + return randomInt(-32767, 32767); + } + + public static String randomBinary(int length) { + return randomString(length); + } + + public static String randomString(int length) { + String zh_en = ""; + for (int i = 0; i < length; i++) { + zh_en += alphabet.charAt(random.nextInt(alphabet.length())); + } + return zh_en; + } + + public static String randomChinese(int length) { + String zh_cn = ""; + int bottom = Integer.parseInt("4e00", 16); + int top = Integer.parseInt("9fa5", 16); + + for (int i = 0; i < length; i++) { + char c = (char) (random.nextInt(top - bottom + 1) + bottom); + zh_cn += new String(new char[]{c}); + } + return zh_cn; + } + + public static Double randomDouble() { + return randomDouble(0, 100); + } + + public static Double randomDouble(double bottom, double top) { + return bottom + (top - bottom) * random.nextDouble(); + } + + public static Float randomFloat() { + return randomFloat(0, 100); + } + + public static Float randomFloat(float bottom, float top) { + return bottom + (top - bottom) * random.nextFloat(); + } + + public static Long randomBigint() { + return random.nextLong(); + } + + public static Integer randomInt(int bottom, int top) { + return bottom + random.nextInt((top - bottom)); + } + + public static Integer randomInt() { + return randomInt(0, 100); + } + +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/Printer.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/Printer.java new file mode 100644 index 0000000000000000000000000000000000000000..a4627463ec5cd1bbccdb64b67506ba38f712de8f --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/Printer.java @@ -0,0 +1,27 @@ +package com.taosdata.taosdemo.utils; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +public class Printer { + + public static void printResult(ResultSet resultSet) throws SQLException { + ResultSetMetaData metaData = resultSet.getMetaData(); + while (resultSet.next()) { + for (int i = 1; i <= metaData.getColumnCount(); i++) { + String columnLabel = metaData.getColumnLabel(i); + String value = resultSet.getString(i); + System.out.printf("%s: %s\t", columnLabel, value); + } + System.out.println(); + } + } + + public static void printSql(String sql, boolean succeed, long cost) { + System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); + } + + private Printer() { + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/SqlSpeller.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/SqlSpeller.java new file mode 100644 index 0000000000000000000000000000000000000000..a60f0641d3a4441195c3a60639fbe3a197115dc3 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/SqlSpeller.java @@ -0,0 +1,194 @@ +package com.taosdata.taosdemo.utils; + +import com.taosdata.taosdemo.domain.*; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class SqlSpeller { + + // create database if not exists xxx keep xx days xx replica xx cache xx... + public static String createDatabase(Map map) { + StringBuilder sb = new StringBuilder(); + sb.append("create database if not exists ").append(map.get("database")).append(" "); + if (map.containsKey("keep")) + sb.append("keep ").append(map.get("keep")).append(" "); + if (map.containsKey("days")) + sb.append("days ").append(map.get("days")).append(" "); + if (map.containsKey("replica")) + sb.append("replica ").append(map.get("replica")).append(" "); + if (map.containsKey("cache")) + sb.append("cache ").append(map.get("cache")).append(" "); + if (map.containsKey("blocks")) + sb.append("blocks ").append(map.get("blocks")).append(" "); + if (map.containsKey("minrows")) + sb.append("minrows ").append(map.get("minrows")).append(" "); + if (map.containsKey("maxrows")) + sb.append("maxrows ").append(map.get("maxrows")).append(" "); + if (map.containsKey("precision")) + sb.append("precision ").append(map.get("precision")).append(" "); + if (map.containsKey("comp")) + sb.append("comp ").append(map.get("comp")).append(" "); + if (map.containsKey("walLevel")) + sb.append("walLevel ").append(map.get("walLevel")).append(" "); + if (map.containsKey("quorum")) + sb.append("quorum ").append(map.get("quorum")).append(" "); + if (map.containsKey("fsync")) + sb.append("fsync ").append(map.get("fsync")).append(" "); + if (map.containsKey("update")) + sb.append("update ").append(map.get("update")).append(" "); + return sb.toString(); + } + + // create table if not exists xx.xx using xx.xx tags(x,x,x) + public static String createTableUsingSuperTable(SubTableMeta subTableMeta) { + StringBuilder sb = new StringBuilder(); + sb.append("create table if not exists ").append(subTableMeta.getDatabase()).append(".").append(subTableMeta.getName()).append(" "); + sb.append("using ").append(subTableMeta.getDatabase()).append(".").append(subTableMeta.getSupertable()).append(" "); +// String tagStr = subTableMeta.getTags().stream().filter(Objects::nonNull) +// .map(tagValue -> tagValue.getName() + " '" + tagValue.getValue() + "' ") +// .collect(Collectors.joining(",", "(", ")")); + sb.append("tags ").append(tagValues(subTableMeta.getTags())); + return sb.toString(); + } + + // insert into xx.xxx values(x,x,x),(x,x,x)... + public static String insertOneTableMultiValues(SubTableValue subTableValue) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getName() + " "); + sb.append("values").append(rowValues(subTableValue.getValues())); + return sb.toString(); + } + + //f1, f2, f3 + private static String fieldValues(List fields) { + return IntStream.range(0, fields.size()).mapToObj(i -> { + if (i == 0) { + return "" + fields.get(i).getValue() + ""; + } else { + return "'" + fields.get(i).getValue() + "'"; + } + }).collect(Collectors.joining(",", "(", ")")); + +// return fields.stream() +// .filter(Objects::nonNull) +// .map(fieldValue -> "'" + fieldValue.getValue() + "'") +// .collect(Collectors.joining(",", "(", ")")); + } + + //(f1, f2, f3),(f1, f2, f3) + private static String rowValues(List rowValues) { + return rowValues.stream().filter(Objects::nonNull) + .map(rowValue -> fieldValues(rowValue.getFields())) + .collect(Collectors.joining(",", "", "")); + } + + // insert into xx.xxx using xx.xx tags(x,x,x) values(x,x,x),(x,x,x)... + public static String insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getName()).append(" "); + sb.append("using ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getSupertable()).append(" "); + sb.append("tags ").append(tagValues(subTableValue.getTags()) + " "); + sb.append("values ").append(rowValues(subTableValue.getValues())); + return sb.toString(); + } + + // (t1,t2,t3...) + private static String tagValues(List tags) { + return tags.stream().filter(Objects::nonNull) + .map(tagValue -> "'" + tagValue.getValue() + "'") + .collect(Collectors.joining(",", "(", ")")); + } + + // insert into xx.xx values(),(),()... xx.xx values(),()... + public static String insertMultiSubTableMultiValues(List tables) { + return "insert into " + tables.stream().filter(Objects::nonNull) + .map(table -> table.getDatabase() + "." + table.getName() + " values " + rowValues(table.getValues())) + .collect(Collectors.joining(" ", "", "")); + } + + // insert into xx.xx using xx.xx tags(xx,xx) values(),()... + public static String insertMultiTableMultiValuesUsingSuperTable(List tables) { + return "insert into " + tables.stream().filter(Objects::nonNull) + .map(table -> { + StringBuilder sb = new StringBuilder(); + sb.append(table.getDatabase()).append(".").append(table.getName()); + sb.append(" using ").append(table.getDatabase()).append(".").append(table.getSupertable()); + sb.append(" tags ").append(tagValues(table.getTags())); + sb.append(" values ").append(rowValues(table.getValues())); + return sb.toString(); + }).collect(Collectors.joining(" ")); + } + + // create table if not exists xx.xx (f1 xx,f2 xx...) tags(t1 xx, t2 xx...) + public static String createSuperTable(SuperTableMeta tableMetadata) { + StringBuilder sb = new StringBuilder(); + sb.append("create table if not exists ").append(tableMetadata.getDatabase()).append(".").append(tableMetadata.getName()); + String fields = tableMetadata.getFields().stream() + .filter(Objects::nonNull).map(field -> field.getName() + " " + field.getType() + " ") + .collect(Collectors.joining(",", "(", ")")); + sb.append(fields); + sb.append(" tags "); + String tags = tableMetadata.getTags().stream().filter(Objects::nonNull) + .map(tag -> tag.getName() + " " + tag.getType() + " ") + .collect(Collectors.joining(",", "(", ")")); + sb.append(tags); + return sb.toString(); + } + + + public static String createTable(TableMeta tableMeta) { + StringBuilder sb = new StringBuilder(); + sb.append("create table if not exists ").append(tableMeta.getDatabase()).append(".").append(tableMeta.getName()).append(" "); + String fields = tableMeta.getFields().stream() + .filter(Objects::nonNull).map(field -> field.getName() + " " + field.getType() + " ") + .collect(Collectors.joining(",", "(", ")")); + sb.append(fields); + return sb.toString(); + } + + // insert into xx.xx values() + public static String insertOneTableMultiValues(TableValue table) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(table.getDatabase()).append(".").append(table.getName() + " "); + sb.append("values").append(rowValues(table.getValues())); + return sb.toString(); + + } + + // insert into xx.xx (f1, f2, f3...) values(xx,xx,xx),(xx,xx,xx)... + public static String insertOneTableMultiValuesWithColumns(TableValue table) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(table.getDatabase()).append(".").append(table.getName()).append(" "); + sb.append(columnNames(table.getColumns())); + sb.append(" values ").append(rowValues(table.getValues())); + return sb.toString(); + } + + // (f1, f2, f3...) + private static String columnNames(List fields) { + return fields.stream() + .filter(Objects::nonNull) + .map(column -> column.getName() + " ") + .collect(Collectors.joining(",", "(", ")")); + } + + public static String insertMultiTableMultiValuesWithColumns(List tables) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(tables.stream().filter(Objects::nonNull) + .map(table -> table.getDatabase() + "." + table.getName() + " " + columnNames(table.getColumns()) + " values " + rowValues(table.getValues())) + .collect(Collectors.joining(" "))); + return sb.toString(); + } + + public static String insertMultiTableMultiValues(List tables) { + StringBuilder sb = new StringBuilder(); + sb.append("insert into ").append(tables.stream().filter(Objects::nonNull).map(table -> + table.getDatabase() + "." + table.getName() + " values " + rowValues(table.getValues()) + ).collect(Collectors.joining(" "))); + return sb.toString(); + } +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TaosConstants.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TaosConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..23c3c5279a15a1dbe529c66398d1378c826ce99a --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TaosConstants.java @@ -0,0 +1,8 @@ +package com.taosdata.taosdemo.utils; + +public class TaosConstants { + public static final String[] DATA_TYPES = { + "timestamp", "int", "bigint", "float", "double", + "binary(64)", "smallint", "tinyint", "bool", "nchar(64)", + }; +} diff --git a/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TimeStampUtil.java b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TimeStampUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..9cfce16d828510be2c62a9a383e8e3d3badb622e --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/java/com/taosdata/taosdemo/utils/TimeStampUtil.java @@ -0,0 +1,67 @@ +package com.taosdata.taosdemo.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class TimeStampUtil { + + private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss.SSS"; + + public static long datetimeToLong(String dateTime) { + SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat); + try { + return sdf.parse(dateTime).getTime(); + } catch (ParseException e) { + throw new IllegalArgumentException("invalid datetime string >>> " + dateTime); + } + } + + public static String longToDatetime(long time) { + SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat); + return sdf.format(new Date(time)); + } + + public static class TimeTuple { + public Long start; + public Long end; + public Long timeGap; + + TimeTuple(long start, long end, long timeGap) { + this.start = start; + this.end = end; + this.timeGap = timeGap; + } + } + + public static TimeTuple range(long start, long timeGap, long size) { + long now = System.currentTimeMillis(); + if (timeGap < 1) + timeGap = 1; + if (start == 0) + start = now - size * timeGap; + + // 如果size小于1异常 + if (size < 1) + throw new IllegalArgumentException("size less than 1."); + // 如果timeGap为1,已经超长,需要前移start + if (start + size > now) { + start = now - size; + return new TimeTuple(start, now, 1); + } + long end = start + (long) (timeGap * size); + if (end > now) { + //压缩timeGap + end = now; + double gap = (end - start) / (size * 1.0f); + if (gap < 1.0f) { + timeGap = 1; + start = end - size; + } else { + timeGap = (long) gap; + end = start + (long) (timeGap * size); + } + } + return new TimeTuple(start, end, timeGap); + } +} diff --git a/examples/JDBC/taosdemo/src/main/resources/application.properties b/examples/JDBC/taosdemo/src/main/resources/application.properties new file mode 100644 index 0000000000000000000000000000000000000000..488185196f1d2325fd9896d30068cbb202180a3f --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/resources/application.properties @@ -0,0 +1,5 @@ +jdbc.driver=com.taosdata.jdbc.rs.RestfulDriver +#jdbc.driver=com.taosdata.jdbc.TSDBDriver +hikari.maximum-pool-size=20 +hikari.minimum-idle=20 +hikari.max-lifetime=0 \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/resources/insert.json b/examples/JDBC/taosdemo/src/main/resources/insert.json new file mode 100644 index 0000000000000000000000000000000000000000..7578083d33c73829ecce1678358e04d2a50d528f --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/resources/insert.json @@ -0,0 +1,117 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 2, + "databases": [ + { + "dbinfo": { + "name": "db04", + "drop": "no", + "replica": 1, + "days": 2, + "cache": 16, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp": 2, + "walLevel": 1, + "quorum": 1, + "fsync": 3000, + "update": 0 + }, + "super_tables": [ + { + "name": "stb04", + "child_table_exists": "no", + "childtable_count": 10, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "data_source": "rand", + "insert_mode": "taosc", + "insert_rate": 0, + "insert_rows": 100, + "interlace_rows": 3, + "max_sql_len": 1024, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 10, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [ + { + "type": "TINYINT" + }, + { + "type": "SMALLINT" + }, + { + "type": "INT" + }, + { + "type": "BIGINT" + }, + { + "type": "BOOL" + }, + { + "type": "FLOAT" + }, + { + "type": "DOUBLE" + }, + { + "type": "TIMESTAMP" + }, + { + "type": "BINARY", + "len": 16 + }, + { + "type": "NCHAR", + "len": 4 + } + ], + "tags": [ + { + "type": "TINYINT" + }, + { + "type": "SMALLINT" + }, + { + "type": "INT" + }, + { + "type": "BIGINT" + }, + { + "type": "BOOL" + }, + { + "type": "FLOAT" + }, + { + "type": "DOUBLE" + }, + { + "type": "BINARY", + "len": 16 + }, + { + "type": "NCHAR", + "len": 4 + } + ] + } + ] + } + ] +} diff --git a/examples/JDBC/taosdemo/src/main/resources/log4j.properties b/examples/JDBC/taosdemo/src/main/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..352545854d0f68f07e4da6a98504ffa7754b03b1 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/resources/log4j.properties @@ -0,0 +1,21 @@ +### 设置### +log4j.rootLogger=info,stdout +### 输出信息到控制抬 ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n +### 输出DEBUG 级别以上的日志到=logs/debug.log +log4j.appender.DebugLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.DebugLog.File=logs/debug.log +log4j.appender.DebugLog.Append=true +log4j.appender.DebugLog.Threshold=DEBUG +log4j.appender.DebugLog.layout=org.apache.log4j.PatternLayout +log4j.appender.DebugLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n +### 输出ERROR 级别以上的日志到=logs/error.log +log4j.appender.ErrorLog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.ErrorLog.File=logs/error.log +log4j.appender.ErrorLog.Append=true +log4j.appender.ErrorLog.Threshold=ERROR +log4j.appender.ErrorLog.layout=org.apache.log4j.PatternLayout +log4j.appender.ErrorLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/main/resources/query.json b/examples/JDBC/taosdemo/src/main/resources/query.json new file mode 100644 index 0000000000000000000000000000000000000000..cc6900d77c3941e6af3274efdfe782c42a557990 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/resources/query.json @@ -0,0 +1,17 @@ +{ + "filetype":"query", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "databases": "db01", + "super_table_query": + {"rate":1, "concurrent":1,"time":10000, + "sqls": [{"sql": "select count(*) from stb01", "result": "./query_res0.txt"}] + }, + "sub_table_query": + {"stblname": "stb01", "rate":1, "threads":1, + "sqls": [{"sql": "select count(*) from xxxx", "result": "./query_res1.txt"}] + } +} diff --git a/examples/JDBC/taosdemo/src/main/resources/templates/index.html b/examples/JDBC/taosdemo/src/main/resources/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..953a058032612c7eac8eacc68f738d5fef03ec39 --- /dev/null +++ b/examples/JDBC/taosdemo/src/main/resources/templates/index.html @@ -0,0 +1,10 @@ + + + + + Index + + +

Developing~~~

+ + \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/DatabaseServiceTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/DatabaseServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..621ba7df5da4bb29747a5a4af1f91d51f6a1d7d4 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/DatabaseServiceTest.java @@ -0,0 +1,23 @@ +package com.taosdata.taosdemo.service; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class DatabaseServiceTest { + private DatabaseService service; + + @Test + public void testCreateDatabase1() { + service.createDatabase("testXXXX"); + } + + @Test + public void dropDatabase() { + service.dropDatabase("testXXXX"); + } + + @Test + public void useDatabase() { + service.useDatabase("test"); + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/QueryServiceTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/QueryServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f2ad25710c1a82136d6316ed69e379bc3925897d --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/QueryServiceTest.java @@ -0,0 +1,41 @@ +package com.taosdata.taosdemo.service; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.junit.BeforeClass; +import org.junit.Test; + +public class QueryServiceTest { + private static QueryService queryService; + + @Test + public void areValidQueries() { + + } + + @Test + public void generateSuperTableQueries() { + String[] sqls = queryService.generateSuperTableQueries("restful_test"); + for (String sql : sqls) { + System.out.println(sql); + } + } + + @Test + public void querySuperTable() { + String[] sqls = queryService.generateSuperTableQueries("restful_test"); + queryService.querySuperTable(sqls, 1000, 10, 10); + } + + @BeforeClass + public static void beforeClass() throws ClassNotFoundException { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8"); + config.setUsername("root"); + config.setPassword("taosdata"); + HikariDataSource dataSource = new HikariDataSource(config); + queryService = new QueryService(dataSource); + } + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SubTableServiceTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SubTableServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f7e5cd45057472602ad6e7a43a8d8bdb31a02b40 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SubTableServiceTest.java @@ -0,0 +1,42 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.TagValue; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SubTableServiceTest { + + private SubTableService service; + + private List subTables; + + @Before + public void before() { + subTables = new ArrayList<>(); + for (int i = 1; i <= 1; i++) { + SubTableMeta subTableMeta = new SubTableMeta(); + subTableMeta.setDatabase("test"); + subTableMeta.setSupertable("weather"); + subTableMeta.setName("t" + i); + List tags = new ArrayList<>(); + tags.add(new TagValue("location", "beijing")); + tags.add(new TagValue("groupId", i)); + subTableMeta.setTags(tags); + subTables.add(subTableMeta); + } + } + + @Test + public void testCreateSubTable() { + + } + + @Test + public void testCreateSubTableList() { + + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SuperTableServiceTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SuperTableServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..33e52af1eaa779e7ed402a63633bf0dbb9fbadd7 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/SuperTableServiceTest.java @@ -0,0 +1,32 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.domain.TagMeta; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SuperTableServiceTest { + + private SuperTableService service; + + @Test + public void testCreate() { + SuperTableMeta superTableMeta = new SuperTableMeta(); + superTableMeta.setDatabase("test"); + superTableMeta.setName("weather"); + List fields = new ArrayList<>(); + fields.add(new FieldMeta("ts", "timestamp")); + fields.add(new FieldMeta("temperature", "float")); + fields.add(new FieldMeta("humidity", "int")); + superTableMeta.setFields(fields); + List tags = new ArrayList<>(); + tags.add(new TagMeta("location", "nchar(64)")); + tags.add(new TagMeta("groupId", "int")); + superTableMeta.setTags(tags); + service.create(superTableMeta); + } + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/TableServiceTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/TableServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1f52198d68823326dd81d8c419fc02d89e15ef2d --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/TableServiceTest.java @@ -0,0 +1,31 @@ +package com.taosdata.taosdemo.service; + +import com.taosdata.taosdemo.domain.TableMeta; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class TableServiceTest { + private TableService tableService; + + private List tables; + + @Before + public void before() { + tables = new ArrayList<>(); + for (int i = 0; i < 1; i++) { + TableMeta tableMeta = new TableMeta(); + tableMeta.setDatabase("test"); + tableMeta.setName("weather" + (i + 1)); + tables.add(tableMeta); + } + } + + @Test + public void testCreate() { + tableService.create(tables); + } + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/FieldValueGeneratorTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/FieldValueGeneratorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aea3cc76ca74951a6bbcc91fe3c6b5c7e078f0df --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/FieldValueGeneratorTest.java @@ -0,0 +1,59 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.RowValue; +import com.taosdata.taosdemo.utils.TimeStampUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class FieldValueGeneratorTest { + + private List rowValues; + + @Test + public void generate() { + List fieldMetas = new ArrayList<>(); + fieldMetas.add(new FieldMeta("ts", "timestamp")); + fieldMetas.add(new FieldMeta("temperature", "float")); + fieldMetas.add(new FieldMeta("humidity", "int")); + + long start = TimeStampUtil.datetimeToLong("2020-01-01 00:00:00.000"); + long end = TimeStampUtil.datetimeToLong("2020-01-01 10:00:00.000"); + + rowValues = FieldValueGenerator.generate(start, end, 1000l * 3600, fieldMetas); + Assert.assertEquals(10, rowValues.size()); + } + + @Test + public void disrupt() { + List fieldMetas = new ArrayList<>(); + fieldMetas.add(new FieldMeta("ts", "timestamp")); + fieldMetas.add(new FieldMeta("temperature", "float")); + fieldMetas.add(new FieldMeta("humidity", "int")); + + long start = TimeStampUtil.datetimeToLong("2020-01-01 00:00:00.000"); + long end = TimeStampUtil.datetimeToLong("2020-01-01 10:00:00.000"); + + rowValues = FieldValueGenerator.generate(start, end, 1000l * 3600l, fieldMetas); + + FieldValueGenerator.disrupt(rowValues, 20, 1000); + Assert.assertEquals(10, rowValues.size()); + } + + @After + public void after() { + for (RowValue row : rowValues) { + row.getFields().stream().forEach(field -> { + if (field.getName().equals("ts")) { + System.out.print(TimeStampUtil.longToDatetime((Long) field.getValue())); + } else + System.out.print(" ," + field.getValue()); + }); + System.out.println(); + } + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SubTableMetaGeneratorTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SubTableMetaGeneratorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..78c8e9283f9a045b251419e5a07b1c97bd105254 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SubTableMetaGeneratorTest.java @@ -0,0 +1,52 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.SubTableMeta; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.domain.TagMeta; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SubTableMetaGeneratorTest { + List subTableMetas; + + @Test + public void generate() { + SuperTableMeta superTableMeta = new SuperTableMeta(); + superTableMeta.setDatabase("test"); + superTableMeta.setName("weather"); + List fields = new ArrayList<>(); + fields.add(new FieldMeta("ts", "timestamp")); + fields.add(new FieldMeta("temperature", "float")); + fields.add(new FieldMeta("humidity", "int")); + superTableMeta.setFields(fields); + List tags = new ArrayList<>(); + tags.add(new TagMeta("location", "nchar(64)")); + tags.add(new TagMeta("groupId", "int")); + superTableMeta.setTags(tags); + + subTableMetas = SubTableMetaGenerator.generate(superTableMeta, 10, "t"); + Assert.assertEquals(10, subTableMetas.size()); + Assert.assertEquals("t1", subTableMetas.get(0).getName()); + Assert.assertEquals("t2", subTableMetas.get(1).getName()); + Assert.assertEquals("t3", subTableMetas.get(2).getName()); + Assert.assertEquals("t4", subTableMetas.get(3).getName()); + Assert.assertEquals("t5", subTableMetas.get(4).getName()); + Assert.assertEquals("t6", subTableMetas.get(5).getName()); + Assert.assertEquals("t7", subTableMetas.get(6).getName()); + Assert.assertEquals("t8", subTableMetas.get(7).getName()); + Assert.assertEquals("t9", subTableMetas.get(8).getName()); + Assert.assertEquals("t10", subTableMetas.get(9).getName()); + } + + @After + public void after() { + for (SubTableMeta subTableMeta : subTableMetas) { + System.out.println(subTableMeta); + } + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SuperTableMetaGeneratorImplTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SuperTableMetaGeneratorImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..11c5312cf6c9b4893681728115519509985a42a2 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/SuperTableMetaGeneratorImplTest.java @@ -0,0 +1,60 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.FieldMeta; +import com.taosdata.taosdemo.domain.SuperTableMeta; +import com.taosdata.taosdemo.domain.TagMeta; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +public class SuperTableMetaGeneratorImplTest { + private SuperTableMeta meta; + + @Test + public void generate() { + String sql = "create table test.weather (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)"; + meta = SuperTableMetaGenerator.generate(sql); + Assert.assertEquals("test", meta.getDatabase()); + Assert.assertEquals("weather", meta.getName()); + Assert.assertEquals(3, meta.getFields().size()); + Assert.assertEquals("ts", meta.getFields().get(0).getName()); + Assert.assertEquals("timestamp", meta.getFields().get(0).getType()); + Assert.assertEquals("temperature", meta.getFields().get(1).getName()); + Assert.assertEquals("float", meta.getFields().get(1).getType()); + Assert.assertEquals("humidity", meta.getFields().get(2).getName()); + Assert.assertEquals("int", meta.getFields().get(2).getType()); + + Assert.assertEquals("location", meta.getTags().get(0).getName()); + Assert.assertEquals("nchar(64)", meta.getTags().get(0).getType()); + Assert.assertEquals("groupid", meta.getTags().get(1).getName()); + Assert.assertEquals("int", meta.getTags().get(1).getType()); + } + + @Test + public void generate2() { + meta = SuperTableMetaGenerator.generate("test", "weather", 10, "col", 10, "tag"); + Assert.assertEquals("test", meta.getDatabase()); + Assert.assertEquals("weather", meta.getName()); + Assert.assertEquals(11, meta.getFields().size()); + for (FieldMeta fieldMeta : meta.getFields()) { + Assert.assertNotNull(fieldMeta.getName()); + Assert.assertNotNull(fieldMeta.getType()); + } + for (TagMeta tagMeta : meta.getTags()) { + Assert.assertNotNull(tagMeta.getName()); + Assert.assertNotNull(tagMeta.getType()); + } + } + + @After + public void after() { + System.out.println(meta.getDatabase()); + System.out.println(meta.getName()); + for (FieldMeta fieldMeta : meta.getFields()) { + System.out.println(fieldMeta); + } + for (TagMeta tagMeta : meta.getTags()) { + System.out.println(tagMeta); + } + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/TagValueGeneratorTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/TagValueGeneratorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..37c9051c941b3540fd24371cff20be426d4fecba --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/service/data/TagValueGeneratorTest.java @@ -0,0 +1,37 @@ +package com.taosdata.taosdemo.service.data; + +import com.taosdata.taosdemo.domain.TagMeta; +import com.taosdata.taosdemo.domain.TagValue; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class TagValueGeneratorTest { + List tagvalues; + + @Test + public void generate() { + List tagMetaList = new ArrayList<>(); + tagMetaList.add(new TagMeta("location", "nchar(10)")); + tagMetaList.add(new TagMeta("groupId", "int")); + tagMetaList.add(new TagMeta("ts", "timestamp")); + tagMetaList.add(new TagMeta("temperature", "float")); + tagMetaList.add(new TagMeta("humidity", "double")); + tagMetaList.add(new TagMeta("text", "binary(10)")); + tagvalues = TagValueGenerator.generate(tagMetaList); + Assert.assertEquals("location", tagvalues.get(0).getName()); + Assert.assertEquals("groupId", tagvalues.get(1).getName()); + Assert.assertEquals("ts", tagvalues.get(2).getName()); + Assert.assertEquals("temperature", tagvalues.get(3).getName()); + Assert.assertEquals("humidity", tagvalues.get(4).getName()); + Assert.assertEquals("text", tagvalues.get(5).getName()); + } + + @After + public void after() { + tagvalues.stream().forEach(System.out::println); + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/DataGeneratorTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/DataGeneratorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7d12782526e4d64e120ba5e4c72809846356cd00 --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/DataGeneratorTest.java @@ -0,0 +1,20 @@ +package com.taosdata.taosdemo.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class DataGeneratorTest { + + @Test + public void randomValue() { + for (int i = 0; i < TaosConstants.DATA_TYPES.length; i++) { + System.out.println(TaosConstants.DATA_TYPES[i] + " >>> " + DataGenerator.randomValue(TaosConstants.DATA_TYPES[i])); + } + } + + @Test + public void randomNchar() { + String s = DataGenerator.randomNchar(10); + Assert.assertEquals(10, s.length()); + } +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/SqlSpellerTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/SqlSpellerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..daabd51ca75a6c9f4bfeead0b747c4de69f40a7a --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/SqlSpellerTest.java @@ -0,0 +1,254 @@ +package com.taosdata.taosdemo.utils; + +import com.taosdata.taosdemo.domain.*; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class SqlSpellerTest { + + @Test + public void createDatabase() { + HashMap map = new HashMap<>(); + map.put("database", "jdbcdb"); + map.put("keep", "3650"); + map.put("days", "30"); + map.put("replica", "1"); + map.put("minRows", "100"); + map.put("maxRows", "1000"); + map.put("cache", "16"); + map.put("blocks", "8"); + map.put("precision", "ms"); + map.put("comp", "2"); + map.put("walLevel", "1"); + map.put("quorum", "1"); + map.put("fsync", "3000"); + map.put("update", "0"); + String sql = SqlSpeller.createDatabase(map); + System.out.println(sql); + } + + @Test + public void createTableUsingSuperTable() { + SubTableMeta subTableMeta = new SubTableMeta(); + subTableMeta.setDatabase("test"); + subTableMeta.setSupertable("weather"); + subTableMeta.setName("t1"); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(new TagValue("tag" + (i + 1), "nchar(64)")); + } + subTableMeta.setTags(tags); + String sql = SqlSpeller.createTableUsingSuperTable(subTableMeta); + System.out.println(sql); + } + + @Test + public void insertOneTableMultiValues() { + String sql = SqlSpeller.insertOneTableMultiValues(tables.get(0)); + System.out.println(sql); + } + + @Test + public void insertOneTableMultiValuesUsingSuperTable() { + String sql = SqlSpeller.insertOneTableMultiValuesUsingSuperTable(tables.get(0)); + System.out.println(sql); + } + + @Test + public void insertMultiTableMultiValues() { + String sql = SqlSpeller.insertMultiSubTableMultiValues(tables); + System.out.println(sql); + } + + @Test + public void insertMultiTableMultiValuesUsingSuperTable() { + String sql = SqlSpeller.insertMultiTableMultiValuesUsingSuperTable(tables); + System.out.println(sql); + } + + private List tables; + + @Before + public void before() { + tables = new ArrayList<>(); + for (int ind = 0; ind < 3; ind++) { + SubTableValue table = new SubTableValue(); + table.setDatabase("test"); + // supertable + table.setSupertable("weather"); + table.setName("t" + (ind + 1)); + // tags + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(new TagValue("tag" + (i + 1), "beijing")); + } + table.setTags(tags); + // values + List values = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + List fields = new ArrayList<>(); + for (int j = 0; j < 4; j++) { + fields.add(new FieldValue("f" + (j + 1), (j + 1) * 10)); + } + values.add(new RowValue(fields)); + } + table.setValues(values); + + tables.add(table); + } + } + + @Test + public void createSuperTable() { + SuperTableMeta superTableMeta = new SuperTableMeta(); + superTableMeta.setDatabase("test"); + superTableMeta.setName("weather"); + List fields = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + fields.add(new FieldMeta("f" + (i + 1), "int")); + } + superTableMeta.setFields(fields); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(new TagMeta("t" + (i + 1), "nchar(64)")); + } + superTableMeta.setTags(tags); + + String sql = SqlSpeller.createSuperTable(superTableMeta); + System.out.println(sql); + } + + @Test + public void createTable() { + TableMeta table = new TableMeta(); + table.setDatabase("test"); + table.setName("t1"); + List fields = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + FieldMeta field = new FieldMeta(); + field.setName("f" + (i + 1)); + field.setType("nchar(64)"); + fields.add(field); + } + table.setFields(fields); + String sql = SqlSpeller.createTable(table); + System.out.println(sql); + } + + + @Test + public void testInsertOneTableMultiValues() { + TableValue table = new TableValue(); + table.setDatabase("test"); + table.setName("t1"); + List values = new ArrayList<>(); + for (int j = 0; j < 5; j++) { + List fields = new ArrayList<>(); + for (int k = 0; k < 2; k++) { + FieldValue field = new FieldValue<>(); + field.setValue((k + 1) * 100); + fields.add(field); + } + values.add(new RowValue(fields)); + } + table.setValues(values); + + String sql = SqlSpeller.insertOneTableMultiValues(table); + System.out.println(sql); + } + + @Test + public void insertOneTableMultiValuesWithColumns() { + TableValue tableValue = new TableValue(); + tableValue.setDatabase("test"); + tableValue.setName("weather"); + // columns + List columns = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + FieldMeta field = new FieldMeta(); + field.setName("f" + (i + 1)); + columns.add(field); + } + tableValue.setColumns(columns); + // values + List values = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + List fields = new ArrayList<>(); + for (int j = 0; j < 3; j++) { + FieldValue field = new FieldValue(); + field.setValue(j); + fields.add(field); + } + values.add(new RowValue(fields)); + } + tableValue.setValues(values); + + String sql = SqlSpeller.insertOneTableMultiValuesWithColumns(tableValue); + System.out.println(sql); + } + + @Test + public void insertMultiTableMultiValuesWithColumns() { + List tables = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + TableValue table = new TableValue(); + table.setDatabase("test"); + table.setName("t" + (i + 1)); + // columns + List columns = new ArrayList<>(); + for (int j = 0; j < 3; j++) { + FieldMeta field = new FieldMeta(); + field.setName("f" + (j + 1)); + columns.add(field); + } + table.setColumns(columns); + // values + List values = new ArrayList<>(); + for (int j = 0; j < 5; j++) { + List fields = new ArrayList<>(); + for (int k = 0; k < columns.size(); k++) { + FieldValue field = new FieldValue<>(); + field.setValue((k + 1) * 10); + fields.add(field); + } + values.add(new RowValue(fields)); + } + table.setValues(values); + tables.add(table); + } + + String sql = SqlSpeller.insertMultiTableMultiValuesWithColumns(tables); + System.out.println(sql); + } + + @Test + public void testInsertMultiTableMultiValues() { + List tables = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + TableValue table = new TableValue(); + table.setDatabase("test"); + table.setName("t" + (i + 1)); + List values = new ArrayList<>(); + for (int j = 0; j < 5; j++) { + List fields = new ArrayList<>(); + for (int k = 0; k < 2; k++) { + FieldValue field = new FieldValue<>(); + field.setValue((k + 1) * 10); + fields.add(field); + } + values.add(new RowValue(fields)); + } + table.setValues(values); + + tables.add(table); + } + + String sql = SqlSpeller.insertMultiTableMultiValues(tables); + System.out.println(sql); + } + +} \ No newline at end of file diff --git a/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/TimeStampUtilTest.java b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/TimeStampUtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a4845677c55897c71791eba40104ea23de644f5c --- /dev/null +++ b/examples/JDBC/taosdemo/src/test/java/com/taosdata/taosdemo/utils/TimeStampUtilTest.java @@ -0,0 +1,40 @@ +package com.taosdata.taosdemo.utils; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class TimeStampUtilTest { + + @Test + public void datetimeToLong() { + final String startTime = "2005-01-01 00:00:00.000"; + long start = TimeStampUtil.datetimeToLong(startTime); + assertEquals(1104508800000l, start); + String dateTimeStr = TimeStampUtil.longToDatetime(start); + assertEquals("2005-01-01 00:00:00.000", dateTimeStr); + } + + @Test + public void longToDatetime() { + System.out.println(TimeStampUtil.longToDatetime(1293334499006l)); + + String datetime = TimeStampUtil.longToDatetime(1510000000000L); + assertEquals("2017-11-07 04:26:40.000", datetime); + long timestamp = TimeStampUtil.datetimeToLong(datetime); + assertEquals(1510000000000L, timestamp); + } + + @Test + public void range() { + long start = TimeStampUtil.datetimeToLong("2020-10-01 00:00:00.000"); + long timeGap = 1000; + long numOfRowsPerTable = 1000l * 3600l * 24l * 90l; + TimeStampUtil.TimeTuple timeTuple = TimeStampUtil.range(start, timeGap, numOfRowsPerTable); + System.out.println(TimeStampUtil.longToDatetime(timeTuple.start)); + System.out.println(TimeStampUtil.longToDatetime(timeTuple.end)); + System.out.println(timeTuple.timeGap); + + } + +} \ No newline at end of file diff --git a/examples/R/command.txt b/examples/R/command.txt new file mode 100644 index 0000000000000000000000000000000000000000..9a549ff200968d96336666c23999e13aa07dbb3f --- /dev/null +++ b/examples/R/command.txt @@ -0,0 +1,55 @@ +# Linux Platform +install.packages('rJDBC', repos='http://cran.us.r-project.org') + +# Loading RJDBC packages +library('RJDBC') +# Set up working path and JDBC driver storage location +setwd('C:/TDengine') + +# Load JDBC Driver for TDengine +drv<-JDBC("com.taosdata.jdbc.TSDBDriver","JDBCDriver-1.0.0-dist.jar", identifier.quote="\"") + +# Connect to the database +conn<-dbConnect(drv,"jdbc:TSDB://192.168.1.114:0/?user=root&password=taosdata","root","taosdata") + +# Get connection information +dbGetInfo(conn) + +# Using database test +dbSendUpdate(conn, "use test") + +# Insert data +dbSendUpdate(conn, "insert into t1 values(now, 99)") + +# View all tables +table1<-dbGetQuery(conn,"show tables") + +# Functional support for RJDBC + +# List all tables +dbListTables(conn) + +# Is there table iris +dbExistsTable(conn,”iris”) + +# Connect summary information +summary(conn) +dbGetInfo(conn) + +# Read all the data from the T1 table +dbReadTable(conn, "t1") + +# Delete table t1 +dbRemoveTable(conn,"t1") + +# Execute any non-query SQL statements +dbSendUpdate(conn, "create table t1(a timestamp, b int, c nchar(12))"); + +# Write data +dbWriteTable(conn, "t1", t_demo_n, overwrite=FALSE, append=TRUE) + +# Extracting data on demand using SQL statements +dbGetQuery(conn, "select k from tu") + +# Close the connection +dbDisconnect(conn) diff --git a/examples/bash/demo.csv b/examples/bash/demo.csv new file mode 100644 index 0000000000000000000000000000000000000000..5b9d6eb8117b20f209d3c94c3608bdedf0d7a469 --- /dev/null +++ b/examples/bash/demo.csv @@ -0,0 +1,10 @@ +1503851026421, 220, 1.10 +1503851026422, 221, 1.20 +1503851026423, 219, 1.09 +1503851026424, 222, 1.11 +1503851026425, 220, 1.08 +'2019-07-22 10:00:01.000', 219, 1.06 +'2019-07-22 10:00:02.000', 218, 1.04 +'2019-07-22 10:01:02.000', 220, 1.12 +'2019-07-22 11:01:02.000', 221, 1.11 +'2019-07-23 11:01:02.000', 220, 1.09 diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..62a82f20156fccd314aab13d0a52f805a1a9a7af --- /dev/null +++ b/examples/c/CMakeLists.txt @@ -0,0 +1,24 @@ +PROJECT(TDengine) + +IF (TD_LINUX) + INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(demo apitest.c) + TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ) + ADD_EXECUTABLE(sml schemaless.c) + TARGET_LINK_LIBRARIES(sml taos_static trpc tutil pthread ) + ADD_EXECUTABLE(sqlperf sqlperf.c) + TARGET_LINK_LIBRARIES(sqlperf taos_static trpc tutil pthread ) + ADD_EXECUTABLE(subscribe subscribe.c) + TARGET_LINK_LIBRARIES(subscribe taos_static trpc tutil pthread ) + ADD_EXECUTABLE(epoll epoll.c) + TARGET_LINK_LIBRARIES(epoll taos_static trpc tutil pthread ${LINK_LUA}) +ENDIF () +IF (TD_DARWIN) + INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(demo demo.c) + TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ${LINK_LUA}) + ADD_EXECUTABLE(epoll epoll.c) + TARGET_LINK_LIBRARIES(epoll taos_static trpc tutil pthread ${LINK_LUA}) +ENDIF () diff --git a/examples/c/apitest.c b/examples/c/apitest.c new file mode 100644 index 0000000000000000000000000000000000000000..2c197887e7d7f1e6397213641a02ee8b37a84190 --- /dev/null +++ b/examples/c/apitest.c @@ -0,0 +1,455 @@ +// sample code to verify all TDengine API +// to compile: gcc -o apitest apitest.c -ltaos + +#include "taoserror.h" + +#include +#include +#include +#include +#include + + +static void prepare_data(TAOS* taos) { + TAOS_RES* result; + result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test precision 'ns';"); + taos_free_result(result); + usleep(100000); + taos_select_db(taos, "test"); + + result = taos_query(taos, "create table meters(ts timestamp, a int) tags(area int);"); + taos_free_result(result); + + result = taos_query(taos, "create table t0 using meters tags(0);"); + taos_free_result(result); + result = taos_query(taos, "create table t1 using meters tags(1);"); + taos_free_result(result); + result = taos_query(taos, "create table t2 using meters tags(2);"); + taos_free_result(result); + result = taos_query(taos, "create table t3 using meters tags(3);"); + taos_free_result(result); + result = taos_query(taos, "create table t4 using meters tags(4);"); + taos_free_result(result); + result = taos_query(taos, "create table t5 using meters tags(5);"); + taos_free_result(result); + result = taos_query(taos, "create table t6 using meters tags(6);"); + taos_free_result(result); + result = taos_query(taos, "create table t7 using meters tags(7);"); + taos_free_result(result); + result = taos_query(taos, "create table t8 using meters tags(8);"); + taos_free_result(result); + result = taos_query(taos, "create table t9 using meters tags(9);"); + taos_free_result(result); + + result = taos_query(taos, + "insert into t0 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " t1 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " ('2020-01-01 00:03:00.000', 0)" + " t2 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:01:01.000', 0)" + " ('2020-01-01 00:01:02.000', 0)" + " t3 values('2020-01-01 00:01:02.000', 0)" + " t4 values('2020-01-01 00:01:02.000', 0)" + " t5 values('2020-01-01 00:01:02.000', 0)" + " t6 values('2020-01-01 00:01:02.000', 0)" + " t7 values('2020-01-01 00:01:02.000', 0)" + " t8 values('2020-01-01 00:01:02.000', 0)" + " t9 values('2020-01-01 00:01:02.000', 0)"); + int affected = taos_affected_rows(result); + if (affected != 18) { + printf("\033[31m%d rows affected by last insert statement, but it should be 18\033[0m\n", affected); + } + taos_free_result(result); + // super tables subscription + usleep(1000000); +} + +static int print_result(TAOS_RES* res, int blockFetch) { + TAOS_ROW row = NULL; + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + int nRows = 0; + + if (blockFetch) { + int rows = 0; + while ((rows = taos_fetch_block(res, &row))) { + // for (int i = 0; i < rows; i++) { + // char temp[256]; + // taos_print_row(temp, row + i, fields, num_fields); + // puts(temp); + //} + nRows += rows; + } + } else { + while ((row = taos_fetch_row(res))) { + char temp[256] = {0}; + taos_print_row(temp, row, fields, num_fields); + puts(temp); + nRows++; + } + } + + printf("%d rows consumed.\n", nRows); + return nRows; +} + +static void check_row_count(int line, TAOS_RES* res, int expected) { + int actual = print_result(res, expected % 2); + if (actual != expected) { + printf("\033[31mline %d: row count mismatch, expected: %d, actual: %d\033[0m\n", line, expected, actual); + } else { + printf("line %d: %d rows consumed as expected\n", line, actual); + } +} + +static void verify_query(TAOS* taos) { + prepare_data(taos); + + int code = taos_load_table_info(taos, "t0,t1,t2,t3,t4,t5,t6,t7,t8,t9"); + if (code != 0) { + printf("\033[31mfailed to load table info: 0x%08x\033[0m\n", code); + } + + code = taos_validate_sql(taos, "select * from nonexisttable"); + if (code == 0) { + printf("\033[31mimpossible, the table does not exists\033[0m\n"); + } + + code = taos_validate_sql(taos, "select * from meters"); + if (code != 0) { + printf("\033[31mimpossible, the table does exists: 0x%08x\033[0m\n", code); + } + + TAOS_RES* res = taos_query(taos, "select * from meters"); + check_row_count(__LINE__, res, 18); + printf("result precision is: %d\n", taos_result_precision(res)); + int c = taos_field_count(res); + printf("field count is: %d\n", c); + int* lengths = taos_fetch_lengths(res); + for (int i = 0; i < c; i++) { + printf("length of column %d is %d\n", i, lengths[i]); + } + taos_free_result(res); + + res = taos_query(taos, "select * from t0"); + check_row_count(__LINE__, res, 3); + taos_free_result(res); + + res = taos_query(taos, "select * from nonexisttable"); + code = taos_errno(res); + printf("code=%d, error msg=%s\n", code, taos_errstr(res)); + taos_free_result(res); + + res = taos_query(taos, "select * from meters"); + taos_stop_query(res); + taos_free_result(res); +} + +void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) { + int rows = print_result(res, *(int*)param); + printf("%d rows consumed in subscribe_callback\n", rows); +} + +static void verify_subscribe(TAOS* taos) { + prepare_data(taos); + + TAOS_SUB* tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + TAOS_RES* res = taos_consume(tsub); + check_row_count(__LINE__, res, 18); + + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + TAOS_RES* result; + result = taos_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);"); + taos_free_result(result); + result = taos_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);"); + taos_free_result(result); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 2); + + result = taos_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);"); + taos_free_result(result); + result = taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);"); + taos_free_result(result); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 2); + + result = taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);"); + taos_free_result(result); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 1); + + // keep progress information and restart subscription + taos_unsubscribe(tsub, 1); + result = taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);"); + taos_free_result(result); + tsub = taos_subscribe(taos, 1, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 24); + + // keep progress information and continue previous subscription + taos_unsubscribe(tsub, 1); + tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + // don't keep progress information and continue previous subscription + taos_unsubscribe(tsub, 0); + tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 24); + + // single meter subscription + + taos_unsubscribe(tsub, 0); + tsub = taos_subscribe(taos, 0, "test", "select * from t0;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 5); + + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + result = taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);"); + taos_free_result(result); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 1); + + taos_unsubscribe(tsub, 0); + + int blockFetch = 0; + tsub = taos_subscribe(taos, 1, "test", "select * from meters;", subscribe_callback, &blockFetch, 1000); + usleep(2000000); + result = taos_query(taos, "insert into t0 values('2020-01-01 00:05:00.001', 0);"); + taos_free_result(result); + usleep(2000000); + taos_unsubscribe(tsub, 0); +} + +void retrieve_callback(void* param, TAOS_RES* tres, int numOfRows) { + if (numOfRows > 0) { + printf("%d rows async retrieved\n", numOfRows); + taos_fetch_rows_a(tres, retrieve_callback, param); + } else { + if (numOfRows < 0) { + printf("\033[31masync retrieve failed, code: %d\033[0m\n", numOfRows); + } else { + printf("async retrieve completed\n"); + } + taos_free_result(tres); + } +} + +void select_callback(void* param, TAOS_RES* tres, int code) { + if (code == 0 && tres) { + taos_fetch_rows_a(tres, retrieve_callback, param); + } else { + printf("\033[31masync select failed, code: %d\033[0m\n", code); + } +} + +void verify_async(TAOS* taos) { + prepare_data(taos); + taos_query_a(taos, "select * from meters", select_callback, NULL); + usleep(1000000); +} + +void stream_callback(void* param, TAOS_RES* res, TAOS_ROW row) { + if (res == NULL || row == NULL) { + return; + } + + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + + printf("got one row from stream_callback\n"); + char temp[256] = {0}; + taos_print_row(temp, row, fields, num_fields); + puts(temp); +} + +void verify_stream(TAOS* taos) { + prepare_data(taos); + TAOS_STREAM* strm = + taos_open_stream(taos, "select count(*) from meters interval(1m)", stream_callback, 0, NULL, NULL); + printf("waiting for stream data\n"); + usleep(100000); + TAOS_RES* result = taos_query(taos, "insert into t0 values(now, 0)(now+5s,1)(now+10s, 2);"); + taos_free_result(result); + usleep(200000000); + taos_close_stream(strm); +} + +void verify_schema_less(TAOS* taos) { + TAOS_RES* result; + result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test precision 'ns' update 1 keep 36500;"); + taos_free_result(result); + usleep(100000); + + taos_select_db(taos, "test"); + result = taos_query(taos, "create stable ste(ts timestamp, f int) tags(t1 bigint)"); + taos_free_result(result); + usleep(100000); + + int code = 0, affected_rows = 0; + + char* lines[] = { + "st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000", + "ste,t2=5f64,t3=L\"ste\" c1=true,c2=4i64,c3=\"iam\" 1626056811823316532", + "st,t1=4i64,t2=5f64,t3=\"t4\" c1=3i64,c3=L\"passitagain\",c2=true,c4=5f64 1626006833642000000", + "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false 1626056811843316532", + "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false,c5=32i8,c6=64i16,c7=32i32,c8=88.88f32 1626056812843316532", + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641000000" + }; + + result = taos_schemaless_insert(taos, lines , sizeof(lines)/sizeof(char*), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + char* lines2[] = { + "stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", + "stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000" + }; + result = taos_schemaless_insert(taos, &lines2[0], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines2_0]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + result = taos_schemaless_insert(taos, &lines2[1], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines2_1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + char* lines3[] = { + "sth,t1=4i64,t2=5f64,t4=5f64,ID=childTable c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641", + "sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654" + }; + result = taos_schemaless_insert(taos, lines3, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines3]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + char* lines4[] = { + "st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", + "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532" + }; + result = taos_schemaless_insert(taos, lines4, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines4]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + + char* lines5[] = { + "zqlbgs,id=zqlbgs_39302_21680,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000", + "zqlbgs,t9=f,id=zqlbgs_39302_21680,t0=f,t1=127i8,t11=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t10=L\"ncharTagValue\" c10=f,c0=f,c1=127i8,c12=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\" 1626006833639000000" + }; + result = taos_schemaless_insert(taos, &lines5[0], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines5_0]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + result = taos_schemaless_insert(taos, &lines5[1], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines5_1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + char* lines6[] = { + "st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", + "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532" + }; + result = taos_schemaless_insert(taos, lines6, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines6]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + + //Test timestamp precision + char* lines7[] = { + "stts,t1=10i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1", + }; + + for (int precision = TSDB_SML_TIMESTAMP_HOURS; precision <= TSDB_SML_TIMESTAMP_NANO_SECONDS; ++precision) { + result = taos_schemaless_insert(taos, lines7, 1, TSDB_SML_LINE_PROTOCOL, precision); + code = taos_errno(result); + if (code != TSDB_CODE_SUCCESS) { + affected_rows = taos_affected_rows(result); + printf("\033[31m [lines7_%d]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", precision, code, taos_errstr(result), affected_rows); + } + taos_free_result(result); + } + +} + +int main(int argc, char* argv[]) { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + TAOS* taos = taos_connect(host, user, passwd, "", 0); + if (taos == NULL) { + printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos)); + exit(1); + } + + char* info = taos_get_server_info(taos); + printf("server info: %s\n", info); + info = taos_get_client_info(taos); + printf("client info: %s\n", info); + + printf("************ verify schema-less *************\n"); + verify_schema_less(taos); + + printf("************ verify query *************\n"); + verify_query(taos); + + printf("********* verify async query **********\n"); + verify_async(taos); + + printf("*********** verify subscribe ************\n"); + verify_subscribe(taos); + + printf("************ verify stream *************\n"); + // verify_stream(taos); + printf("done\n"); + taos_close(taos); + taos_cleanup(); +} diff --git a/examples/c/asyncdemo.c b/examples/c/asyncdemo.c new file mode 100644 index 0000000000000000000000000000000000000000..78e41ddf5cad70ddb430dfdd5832e92d2800d030 --- /dev/null +++ b/examples/c/asyncdemo.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +// TAOS asynchronous API example +// this example opens multiple tables, insert/retrieve multiple tables +// it is used by TAOS internally for one performance testing +// to compiple: gcc -o asyncdemo asyncdemo.c -ltaos + +#include +#include +#include +#include +#include + +#include + +int points = 5; +int numOfTables = 3; +int tablesInsertProcessed = 0; +int tablesSelectProcessed = 0; +int64_t st, et; + +typedef struct { + int id; + TAOS * taos; + char name[16]; + time_t timeStamp; + int value; + int rowsInserted; + int rowsTried; + int rowsRetrieved; +} STable; + +void taos_insert_call_back(void *param, TAOS_RES *tres, int code); +void taos_select_call_back(void *param, TAOS_RES *tres, int code); +void taos_error(TAOS *taos); + +static void queryDB(TAOS *taos, char *command) { + int i; + TAOS_RES *pSql = NULL; + int32_t code = -1; + + for (i = 0; i < 5; i++) { + if (NULL != pSql) { + taos_free_result(pSql); + pSql = NULL; + } + + pSql = taos_query(taos, command); + code = taos_errno(pSql); + if (0 == code) { + break; + } + } + + if (code != 0) { + fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql)); + taos_free_result(pSql); + taos_close(taos); + taos_cleanup(); + exit(EXIT_FAILURE); + } + + taos_free_result(pSql); +} + +int main(int argc, char *argv[]) { + TAOS * taos; + struct timeval systemTime; + int i; + char sql[1024] = {0}; + char prefix[20] = {0}; + char db[128] = {0}; + STable * tableList; + + if (argc != 5) { + printf("usage: %s server-ip dbname rowsPerTable numOfTables\n", argv[0]); + exit(0); + } + + // a simple way to parse input parameters + if (argc >= 3) strcpy(db, argv[2]); + if (argc >= 4) points = atoi(argv[3]); + if (argc >= 5) numOfTables = atoi(argv[4]); + + size_t size = sizeof(STable) * (size_t)numOfTables; + tableList = (STable *)malloc(size); + memset(tableList, 0, size); + + taos = taos_connect(argv[1], "root", "taosdata", NULL, 0); + if (taos == NULL) taos_error(taos); + + printf("success to connect to server\n"); + + sprintf(sql, "drop database if exists %s", db); + queryDB(taos, sql); + + sprintf(sql, "create database %s", db); + queryDB(taos, sql); + + sprintf(sql, "use %s", db); + queryDB(taos, sql); + + strcpy(prefix, "asytbl_"); + for (i = 0; i < numOfTables; ++i) { + tableList[i].id = i; + tableList[i].taos = taos; + sprintf(tableList[i].name, "%s%d", prefix, i); + sprintf(sql, "create table %s%d (ts timestamp, volume bigint)", prefix, i); + queryDB(taos, sql); + } + + gettimeofday(&systemTime, NULL); + for (i = 0; i < numOfTables; ++i) + tableList[i].timeStamp = (time_t)(systemTime.tv_sec) * 1000 + systemTime.tv_usec / 1000; + + printf("success to create tables, press any key to insert\n"); + getchar(); + + printf("start to insert...\n"); + gettimeofday(&systemTime, NULL); + st = systemTime.tv_sec * 1000000 + systemTime.tv_usec; + + tablesInsertProcessed = 0; + tablesSelectProcessed = 0; + + for (i = 0; i < numOfTables; ++i) { + // insert records in asynchronous API + sprintf(sql, "insert into %s values(%ld, 0)", tableList[i].name, 1546300800000 + i); + taos_query_a(taos, sql, taos_insert_call_back, (void *)(tableList + i)); + } + + printf("once insert finished, presse any key to query\n"); + getchar(); + + while (1) { + if (tablesInsertProcessed < numOfTables) { + printf("wait for process finished\n"); + sleep(1); + continue; + } + + break; + } + + printf("start to query...\n"); + gettimeofday(&systemTime, NULL); + st = systemTime.tv_sec * 1000000 + systemTime.tv_usec; + + for (i = 0; i < numOfTables; ++i) { + // select records in asynchronous API + sprintf(sql, "select * from %s", tableList[i].name); + taos_query_a(taos, sql, taos_select_call_back, (void *)(tableList + i)); + } + + printf("\nonce finished, press any key to exit\n"); + getchar(); + + while (1) { + if (tablesSelectProcessed < numOfTables) { + printf("wait for process finished\n"); + sleep(1); + continue; + } + + break; + } + + for (i = 0; i < numOfTables; ++i) { + printf("%s inserted:%d retrieved:%d\n", tableList[i].name, tableList[i].rowsInserted, tableList[i].rowsRetrieved); + } + + taos_close(taos); + free(tableList); + + printf("==== async demo end====\n"); + printf("\n"); + return 0; +} + +void taos_error(TAOS *con) { + fprintf(stderr, "TDengine error: %s\n", taos_errstr(con)); + taos_close(con); + taos_cleanup(); + exit(1); +} + +void taos_insert_call_back(void *param, TAOS_RES *tres, int code) { + STable * pTable = (STable *)param; + struct timeval systemTime; + char sql[128]; + + pTable->rowsTried++; + + if (code < 0) { + printf("%s insert failed, code:%d, rows:%d\n", pTable->name, code, pTable->rowsTried); + } else if (code == 0) { + printf("%s not inserted\n", pTable->name); + } else { + pTable->rowsInserted++; + } + + if (pTable->rowsTried < points) { + // for this demo, insert another record + sprintf(sql, "insert into %s values(%ld, %d)", pTable->name, 1546300800000 + pTable->rowsTried * 1000, + pTable->rowsTried); + taos_query_a(pTable->taos, sql, taos_insert_call_back, (void *)pTable); + } else { + printf("%d rows data are inserted into %s\n", points, pTable->name); + tablesInsertProcessed++; + if (tablesInsertProcessed >= numOfTables) { + gettimeofday(&systemTime, NULL); + et = systemTime.tv_sec * 1000000 + systemTime.tv_usec; + printf("%lld mseconds to insert %d data points\n", (et - st) / 1000, points * numOfTables); + } + } + + taos_free_result(tres); +} + +void taos_retrieve_call_back(void *param, TAOS_RES *tres, int numOfRows) { + STable * pTable = (STable *)param; + struct timeval systemTime; + + if (numOfRows > 0) { + for (int i = 0; i < numOfRows; ++i) { + // synchronous API to retrieve a row from batch of records + /*TAOS_ROW row = */ (void)taos_fetch_row(tres); + // process row + } + + pTable->rowsRetrieved += numOfRows; + + // retrieve next batch of rows + taos_fetch_rows_a(tres, taos_retrieve_call_back, pTable); + + } else { + if (numOfRows < 0) printf("%s retrieve failed, code:%d\n", pTable->name, numOfRows); + + // taos_free_result(tres); + printf("%d rows data retrieved from %s\n", pTable->rowsRetrieved, pTable->name); + + tablesSelectProcessed++; + if (tablesSelectProcessed >= numOfTables) { + gettimeofday(&systemTime, NULL); + et = systemTime.tv_sec * 1000000 + systemTime.tv_usec; + printf("%lld mseconds to query %d data rows\n", (et - st) / 1000, points * numOfTables); + } + + taos_free_result(tres); + } +} + +void taos_select_call_back(void *param, TAOS_RES *tres, int code) { + STable *pTable = (STable *)param; + + if (code == 0 && tres) { + // asynchronous API to fetch a batch of records + taos_fetch_rows_a(tres, taos_retrieve_call_back, pTable); + } else { + printf("%s select failed, code:%d\n", pTable->name, code); + taos_free_result(tres); + taos_cleanup(); + exit(1); + } +} diff --git a/examples/c/clientcfgtest-taosd.c b/examples/c/clientcfgtest-taosd.c new file mode 100644 index 0000000000000000000000000000000000000000..fbfbd8935a34481c23e806bbe461882ed9a10437 --- /dev/null +++ b/examples/c/clientcfgtest-taosd.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + const char config1[128] = "{\"cache\":\"4\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("cache");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config cache to '4'success!\n"); + else + printf("config cache failure!\n"); + return 0 ; + +} diff --git a/examples/c/clientcfgtest-wrongjson.c b/examples/c/clientcfgtest-wrongjson.c new file mode 100644 index 0000000000000000000000000000000000000000..eecb5dae6d27c213731afdea005af3fc265dd47f --- /dev/null +++ b/examples/c/clientcfgtest-wrongjson.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config with wrong JSON + //The result is failure + const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\135\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + cfg1 = taosGetConfigOption("firstEp");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + SGlobalCfg *cfg2 ; + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135'success!\n"); + else + printf("config debugFlag failure!\n"); + + + //case2: + //repair the JSON and try again + //The result is success + const char config2[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg3 ; + + cfg3 = taosGetConfigOption("firstEp");//check the option result + if(cfg3->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + + SGlobalCfg *cfg4 ; + + cfg4 = taosGetConfigOption("debugFlag");//check the option result + if(cfg4->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135'success!\n"); + else + printf("config debugFlag failure!\n"); + return 0 ; + +} diff --git a/examples/c/clientcfgtest-wrongtype.c b/examples/c/clientcfgtest-wrongtype.c new file mode 100644 index 0000000000000000000000000000000000000000..d88cbeebe8e5114ed4836e77b9494de1cc54aba8 --- /dev/null +++ b/examples/c/clientcfgtest-wrongtype.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + //The result is failure + const char config1[128] = "{\"debugFlag\":\"9999999999999999999999999\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("debugFlag");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '9999999999999999999999999\n"); + else + printf("config debugFlag failure!\n"); + + //case2: + //Try again with right parameter + //The result is failure + const char config2[128] = "{\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugflag '135'success!\n"); + else + printf("config debugflag failure!\n"); + return 0 ; + +} diff --git a/examples/c/clientcfgtest-wrongvalue.c b/examples/c/clientcfgtest-wrongvalue.c new file mode 100644 index 0000000000000000000000000000000000000000..f0d44a47f62696d14844ea12276b74da7d0ff408 --- /dev/null +++ b/examples/c/clientcfgtest-wrongvalue.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + const char config1[128] = "{\"rpcTimer\":\"0\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("rpcTimer");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config rpcTimer to '0'success!\n"); + else + printf("config rpcTimer failure!\n"); + + //case2: + //Try again with right parameter + const char config2[128] = "{\"rpcTimer\":\"400\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("rpcTimer");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config rpcTimer '400'success!\n"); + else + printf("config rpcTimer failure!\n"); + return 0 ; + +} diff --git a/examples/c/clientcfgtest.c b/examples/c/clientcfgtest.c new file mode 100644 index 0000000000000000000000000000000000000000..5f8f51cdb1156a25544273fc6419f65b86ea4ecc --- /dev/null +++ b/examples/c/clientcfgtest.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config firstEp success + const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("firstEp");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135' success!\n"); + else + printf("config debugFlag failure!\n"); + //case2: + //Test config only useful at the first time + //The result is failure + const char config2[128] = "{\"fqdn\":\"BCC-3\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg3 ; + + cfg2 = taosGetConfigOption("fqdn");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config fqdn to 'BCC-3'success!\n"); + else + printf("config fqdn failure!\n"); + return 0 ; + +} diff --git a/examples/c/connect_two_cluster.c b/examples/c/connect_two_cluster.c new file mode 100644 index 0000000000000000000000000000000000000000..fa54dd437036f12915d62a60f96b90e6a7adc45f --- /dev/null +++ b/examples/c/connect_two_cluster.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include "taos.h" +int numOfThreads = 1; + +void* connectClusterAndDeal(void *arg) { + int port = *(int *)arg; + const char *host = "127.0.0.1"; + const char *user = "root"; + const char *passwd = "taosdata"; + TAOS* taos1 = taos_connect(host, user, passwd, "", port); + TAOS* taos2 = taos_connect(host, user, passwd, "", port + 1000); + if (NULL == taos1 || NULL == taos2) { + printf("connect to (%d/%d) failed \n", port, port + 1000); + return NULL; + } + TAOS_RES *result = NULL; + result = taos_query(taos1, "drop database if exists db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + + taos_query(taos2, "drop database if exists db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + + taos_free_result(result); + // ========= build database + { + result = taos_query(taos1, "create database db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + + taos_free_result(result); + } + { + result = taos_query(taos2, "create database db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + } + + //======== create table + { + result = taos_query(taos1, "create stable db.stest (ts timestamp, port int) tags(tport int)"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + } + { + result = taos_query(taos2, "create stable db.stest (ts timestamp, port int) tags(tport int)"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + + } + //======== create table + { + result = taos_query(taos1, "use db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + } + { + result = taos_query(taos2, "use db"); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + + } + { + char buf[1024] = {0}; + sprintf(buf, "insert into db.t1 using stest tags(%d) values(now, %d)", port, port); + for (int i = 0; i < 100000; i++) { + //printf("error here\t"); + result = taos_query(taos1, buf); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + //sleep(1); + } + } + + { + char buf[1024] = {0}; + sprintf(buf, "insert into db.t1 using stest tags(%d) values(now, %d)", port + 1000, port + 1000); + for (int i = 0; i < 100000; i++) { + result = taos_query(taos2, buf); + if (0 != taos_errno(result)) { + printf("failed %s\n", taos_errstr(result)); + } + taos_free_result(result); + //sleep(1); + } + } + // query result + { + result = taos_query(taos1, "select * from stest"); + if (result == NULL || taos_errno(result) != 0) { + printf("query failed %s\n", taos_errstr(result)); + taos_free_result(result); + } + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + TAOS_FIELD *fields = taos_fetch_fields(result); + while ((row = taos_fetch_row(result))) { + char temp[1024] = {0}; + rows++; + taos_print_row(temp, row, fields , num_fields); + printf("%s\n", temp); + } + taos_free_result(result); + } + + // query result + { + result = taos_query(taos2, "select * from stest"); + if (result == NULL || taos_errno(result) != 0) { + printf("query failed %s\n", taos_errstr(result)); + taos_free_result(result); + } + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + TAOS_FIELD *fields = taos_fetch_fields(result); + while ((row = taos_fetch_row(result))) { + char temp[1024] = {0}; + rows++; + taos_print_row(temp, row, fields , num_fields); + printf("%s\n", temp); + } + taos_free_result(result); + } + taos_close(taos1); + taos_close(taos2); + return NULL; +} +int main(int argc, char* argv[]) { + pthread_t *pthreads = malloc(sizeof(pthread_t) * numOfThreads); + + int *port = malloc(sizeof(int) * numOfThreads); + port[0] = 6030; + for (int i = 0; i < numOfThreads; i++) { + pthread_create(&pthreads[i], NULL, connectClusterAndDeal, (void *)&port[i]); + } + for (int i = 0; i < numOfThreads; i++) { + pthread_join(pthreads[i], NULL); + } + free(port); +} diff --git a/examples/c/demo.c b/examples/c/demo.c new file mode 100644 index 0000000000000000000000000000000000000000..55d962888871c2ba175daef85f1084a1e28a0da1 --- /dev/null +++ b/examples/c/demo.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +// TAOS standard API example. The same syntax as MySQL, but only a subset +// to compile: gcc -o demo demo.c -ltaos + +#include +#include +#include +#include +#include // TAOS header file + +static void queryDB(TAOS *taos, char *command) { + int i; + TAOS_RES *pSql = NULL; + int32_t code = -1; + + for (i = 0; i < 5; i++) { + if (NULL != pSql) { + taos_free_result(pSql); + pSql = NULL; + } + + pSql = taos_query(taos, command); + code = taos_errno(pSql); + if (0 == code) { + break; + } + } + + if (code != 0) { + fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql)); + taos_free_result(pSql); + taos_close(taos); + exit(EXIT_FAILURE); + } + + taos_free_result(pSql); +} + +void Test(TAOS *taos, char *qstr, int i); + +int main(int argc, char *argv[]) { + char qstr[1024]; + + // connect to server + if (argc < 2) { + printf("please input server-ip \n"); + return 0; + } + + TAOS *taos = taos_connect(argv[1], "root", "taosdata", NULL, 0); + if (taos == NULL) { + printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/); + exit(1); + } + for (int i = 0; i < 100; i++) { + Test(taos, qstr, i); + } + taos_close(taos); + taos_cleanup(); +} +void Test(TAOS *taos, char *qstr, int index) { + printf("==================test at %d\n================================", index); + queryDB(taos, "drop database if exists demo"); + queryDB(taos, "create database demo"); + TAOS_RES *result; + queryDB(taos, "use demo"); + + queryDB(taos, + "create table m1 (ts timestamp, ti tinyint, si smallint, i int, bi bigint, f float, d double, b binary(10))"); + printf("success to create table\n"); + + int i = 0; + for (i = 0; i < 10; ++i) { + sprintf(qstr, "insert into m1 values (%" PRId64 ", %d, %d, %d, %d, %f, %lf, '%s')", + (uint64_t)(1546300800000 + i * 1000), i, i, i, i * 10000000, i * 1.0, i * 2.0, "hello"); + printf("qstr: %s\n", qstr); + + // note: how do you wanna do if taos_query returns non-NULL + // if (taos_query(taos, qstr)) { + // printf("insert row: %i, reason:%s\n", i, taos_errstr(taos)); + // } + TAOS_RES *result1 = taos_query(taos, qstr); + if (result1 == NULL || taos_errno(result1) != 0) { + printf("failed to insert row, reason:%s\n", taos_errstr(result1)); + taos_free_result(result1); + exit(1); + } else { + printf("insert row: %i\n", i); + } + taos_free_result(result1); + } + printf("success to insert rows, total %d rows\n", i); + + // query the records + sprintf(qstr, "SELECT * FROM m1"); + result = taos_query(taos, qstr); + if (result == NULL || taos_errno(result) != 0) { + printf("failed to select, reason:%s\n", taos_errstr(result)); + taos_free_result(result); + exit(1); + } + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + TAOS_FIELD *fields = taos_fetch_fields(result); + + printf("num_fields = %d\n", num_fields); + printf("select * from table, result:\n"); + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[1024] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("%s\n", temp); + } + + taos_free_result(result); + printf("====demo end====\n\n"); +} diff --git a/examples/c/epoll.c b/examples/c/epoll.c new file mode 100644 index 0000000000000000000000000000000000000000..05df33ffe6f0c08dd5608bb3ba30a21623f2ae45 --- /dev/null +++ b/examples/c/epoll.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +// how to use to do a pressure-test upon eok +// tester: cat /dev/urandom | nc -c +// testee: ./debug/build/bin/epoll -l > /dev/null +// compare against: nc -l > /dev/null +// monitor and compare : glances + +#ifdef __APPLE__ +#include "osEok.h" +#else // __APPLE__ +#include +#endif // __APPLE__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define D(fmt, ...) fprintf(stderr, "%s[%d]%s(): " fmt "\n", basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define A(statement, fmt, ...) \ + do { \ + if (statement) break; \ + fprintf(stderr, "%s[%d]%s(): assert [%s] failed: %d[%s]: " fmt "\n", basename(__FILE__), __LINE__, __func__, \ + #statement, errno, strerror(errno), ##__VA_ARGS__); \ + abort(); \ + } while (0) + +#define E(fmt, ...) \ + do { \ + fprintf(stderr, "%s[%d]%s(): %d[%s]: " fmt "\n", basename(__FILE__), __LINE__, __func__, errno, strerror(errno), \ + ##__VA_ARGS__); \ + } while (0) + +#include "os.h" + +typedef struct ep_s ep_t; +struct ep_s { + int ep; + + pthread_mutex_t lock; + int sv[2]; // 0 for read, 1 for write; + pthread_t thread; + + volatile unsigned int stopping : 1; + volatile unsigned int waiting : 1; + volatile unsigned int wakenup : 1; +}; + +static int ep_dummy = 0; + +static ep_t *ep_create(void); +static void ep_destroy(ep_t *ep); +static void *routine(void *arg); +static int open_listen(unsigned short port); + +typedef struct fde_s fde_t; +struct fde_s { + int skt; + void (*on_event)(ep_t *ep, struct epoll_event *events, fde_t *client); +}; + +static void listen_event(ep_t *ep, struct epoll_event *ev, fde_t *client); +static void null_event(ep_t *ep, struct epoll_event *ev, fde_t *client); + +#define usage(arg0, fmt, ...) \ + do { \ + if (fmt[0]) { \ + fprintf(stderr, "" fmt "\n", ##__VA_ARGS__); \ + } \ + fprintf(stderr, "usage:\n"); \ + fprintf(stderr, " %s -l : specify listening port\n", arg0); \ + } while (0) + +int main(int argc, char *argv[]) { + char *prg = basename(argv[0]); + if (argc == 1) { + usage(prg, ""); + return 0; + } + ep_t *ep = ep_create(); + A(ep, "failed"); + for (int i = 1; i < argc; ++i) { + const char *arg = argv[i]; + if (0 == strcmp(arg, "-l")) { + ++i; + if (i >= argc) { + usage(prg, "expecting after -l, but got nothing"); + return 1; // confirmed potential leakage + } + arg = argv[i]; + int port = atoi(arg); + int skt = open_listen(port); + if (skt == -1) continue; + fde_t *client = (fde_t *)calloc(1, sizeof(*client)); + if (!client) { + E("out of memory"); + close(skt); + continue; + } + client->skt = skt; + client->on_event = listen_event; + struct epoll_event ev = {0}; + ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP; + ev.data.ptr = client; + A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, skt, &ev), ""); + continue; + } + usage(prg, "unknown argument: [%s]", arg); + return 1; + } + char * line = NULL; + size_t linecap = 0; + ssize_t linelen; + while ((linelen = getline(&line, &linecap, stdin)) > 0) { + line[strlen(line) - 1] = '\0'; + if (0 == strcmp(line, "exit")) break; + if (0 == strcmp(line, "quit")) break; + if (line == strstr(line, "close")) { + int fd = 0; + sscanf(line, "close %d", &fd); + if (fd <= 2) { + fprintf(stderr, "fd [%d] invalid\n", fd); + continue; + } + A(0 == epoll_ctl(ep->ep, EPOLL_CTL_DEL, fd, NULL), ""); + continue; + } + if (strlen(line) == 0) continue; + fprintf(stderr, "unknown cmd:[%s]\n", line); + } + ep_destroy(ep); + D(""); + return 0; +} + +ep_t *ep_create(void) { + ep_t *ep = (ep_t *)calloc(1, sizeof(*ep)); + A(ep, "out of memory"); + A(-1 != (ep->ep = epoll_create(1)), ""); + ep->sv[0] = -1; + ep->sv[1] = -1; + A(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, ep->sv), ""); + A(0 == pthread_mutex_init(&ep->lock, NULL), ""); + A(0 == pthread_mutex_lock(&ep->lock), ""); + struct epoll_event ev = {0}; + ev.events = EPOLLIN; + ev.data.ptr = &ep_dummy; + A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, ep->sv[0], &ev), ""); + A(0 == pthread_create(&ep->thread, NULL, routine, ep), ""); + A(0 == pthread_mutex_unlock(&ep->lock), ""); + return ep; +} + +static void ep_destroy(ep_t *ep) { + A(ep, "invalid argument"); + ep->stopping = 1; + A(1 == send(ep->sv[1], "1", 1, 0), ""); + A(0 == pthread_join(ep->thread, NULL), ""); + A(0 == pthread_mutex_destroy(&ep->lock), ""); + A(0 == close(ep->sv[0]), ""); + A(0 == close(ep->sv[1]), ""); + A(0 == close(ep->ep), ""); + free(ep); +} + +static void *routine(void *arg) { + A(arg, "invalid argument"); + ep_t *ep = (ep_t *)arg; + + while (!ep->stopping) { + struct epoll_event evs[10]; + memset(evs, 0, sizeof(evs)); + + A(0 == pthread_mutex_lock(&ep->lock), ""); + A(ep->waiting == 0, "internal logic error"); + ep->waiting = 1; + A(0 == pthread_mutex_unlock(&ep->lock), ""); + + int r = epoll_wait(ep->ep, evs, sizeof(evs) / sizeof(evs[0]), -1); + A(r > 0, "indefinite epoll_wait shall not timeout:[%d]", r); + + A(0 == pthread_mutex_lock(&ep->lock), ""); + A(ep->waiting == 1, "internal logic error"); + ep->waiting = 0; + A(0 == pthread_mutex_unlock(&ep->lock), ""); + + for (int i = 0; i < r; ++i) { + struct epoll_event *ev = evs + i; + if (ev->data.ptr == &ep_dummy) { + char c = '\0'; + A(1 == recv(ep->sv[0], &c, 1, 0), "internal logic error"); + A(0 == pthread_mutex_lock(&ep->lock), ""); + ep->wakenup = 0; + A(0 == pthread_mutex_unlock(&ep->lock), ""); + continue; + } + A(ev->data.ptr, "internal logic error"); + fde_t *client = (fde_t *)ev->data.ptr; + client->on_event(ep, ev, client); + continue; + } + } + return NULL; +} + +static int open_listen(unsigned short port) { + int r = 0; + int skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (skt == -1) { + E("socket() failed"); + return -1; + } + do { + struct sockaddr_in si = {0}; + si.sin_family = AF_INET; + si.sin_addr.s_addr = inet_addr("0.0.0.0"); + si.sin_port = htons(port); + r = bind(skt, (struct sockaddr *)&si, sizeof(si)); + if (r) { + E("bind(%u) failed", port); + break; + } + r = listen(skt, 100); + if (r) { + E("listen() failed"); + break; + } + memset(&si, 0, sizeof(si)); + socklen_t len = sizeof(si); + r = getsockname(skt, (struct sockaddr *)&si, &len); + if (r) { + E("getsockname() failed"); + } + A(len == sizeof(si), "internal logic error"); + D("listening at: %d", ntohs(si.sin_port)); + return skt; + } while (0); + close(skt); + return -1; +} + +static void listen_event(ep_t *ep, struct epoll_event *ev, fde_t *client) { + A(ev->events & EPOLLIN, "internal logic error"); + struct sockaddr_in si = {0}; + socklen_t silen = sizeof(si); + int skt = accept(client->skt, (struct sockaddr *)&si, &silen); + A(skt != -1, "internal logic error"); + fde_t *server = (fde_t *)calloc(1, sizeof(*server)); + if (!server) { + close(skt); + return; + } + server->skt = skt; + server->on_event = null_event; + struct epoll_event ee = {0}; + ee.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP; + ee.data.ptr = server; + A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, skt, &ee), ""); +} + +static void null_event(ep_t *ep, struct epoll_event *ev, fde_t *client) { + if (ev->events & EPOLLIN) { + char buf[8192]; + int n = recv(client->skt, buf, sizeof(buf), 0); + A(n >= 0 && n <= sizeof(buf), "internal logic error:[%d]", n); + A(n == fwrite(buf, 1, n, stdout), "internal logic error"); + } + if (ev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { + A(0 == pthread_mutex_lock(&ep->lock), ""); + A(0 == epoll_ctl(ep->ep, EPOLL_CTL_DEL, client->skt, NULL), ""); + A(0 == pthread_mutex_unlock(&ep->lock), ""); + close(client->skt); + client->skt = -1; + client->on_event = NULL; + free(client); + } +} diff --git a/examples/c/makefile b/examples/c/makefile new file mode 100644 index 0000000000000000000000000000000000000000..355d1a2d54c1293e909309dafe986daa716ac293 --- /dev/null +++ b/examples/c/makefile @@ -0,0 +1,30 @@ +# Copyright (c) 2017 by TAOS Technologies, Inc. +# todo: library dependency, header file dependency + +ROOT=./ +TARGET=exe +LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt +CFLAGS = -O3 -g -Wall -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \ + -Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \ + -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \ + -I../../../deps/cJson/inc \ + -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \ + -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment + +all: $(TARGET) + +exe: + gcc $(CFLAGS) ./asyncdemo.c -o $(ROOT)asyncdemo $(LFLAGS) + gcc $(CFLAGS) ./demo.c -o $(ROOT)demo $(LFLAGS) + gcc $(CFLAGS) ./prepare.c -o $(ROOT)prepare $(LFLAGS) + gcc $(CFLAGS) ./stream.c -o $(ROOT)stream $(LFLAGS) + gcc $(CFLAGS) ./subscribe.c -o $(ROOT)subscribe $(LFLAGS) + gcc $(CFLAGS) ./apitest.c -o $(ROOT)apitest $(LFLAGS) + +clean: + rm $(ROOT)asyncdemo + rm $(ROOT)demo + rm $(ROOT)prepare + rm $(ROOT)stream + rm $(ROOT)subscribe + rm $(ROOT)apitest diff --git a/examples/c/prepare.c b/examples/c/prepare.c new file mode 100644 index 0000000000000000000000000000000000000000..14acba3b0d691b4d9bb61db3d8bf95e10e6c20fe --- /dev/null +++ b/examples/c/prepare.c @@ -0,0 +1,1422 @@ +// TAOS standard API example. The same syntax as MySQL, but only a subet +// to compile: gcc -o prepare prepare.c -ltaos + +#include +#include +#include +#include +#include + +void taosMsleep(int mseconds); + +void verify_prepare(TAOS* taos) { + TAOS_RES* result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + + usleep(100000); + result = taos_query(taos, "create database test;"); + + int code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + + taos_free_result(result); + + usleep(100000); + taos_select_db(taos, "test"); + + // create table + const char* sql = + "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned)"; + result = taos_query(taos, sql); + code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + // insert 10 records + struct { + int64_t ts; + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40]; + char blob[80]; + uint8_t u1; + uint16_t u2; + uint32_t u4; + uint64_t u8; + } v = {0}; + + TAOS_STMT* stmt = taos_stmt_init(taos); + TAOS_BIND params[14]; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(v.ts); + params[0].buffer = &v.ts; + params[0].length = ¶ms[0].buffer_length; + params[0].is_null = NULL; + + params[1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[1].buffer_length = sizeof(v.b); + params[1].buffer = &v.b; + params[1].length = ¶ms[1].buffer_length; + params[1].is_null = NULL; + + params[2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[2].buffer_length = sizeof(v.v1); + params[2].buffer = &v.v1; + params[2].length = ¶ms[2].buffer_length; + params[2].is_null = NULL; + + params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[3].buffer_length = sizeof(v.v2); + params[3].buffer = &v.v2; + params[3].length = ¶ms[3].buffer_length; + params[3].is_null = NULL; + + params[4].buffer_type = TSDB_DATA_TYPE_INT; + params[4].buffer_length = sizeof(v.v4); + params[4].buffer = &v.v4; + params[4].length = ¶ms[4].buffer_length; + params[4].is_null = NULL; + + params[5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[5].buffer_length = sizeof(v.v8); + params[5].buffer = &v.v8; + params[5].length = ¶ms[5].buffer_length; + params[5].is_null = NULL; + + params[6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[6].buffer_length = sizeof(v.f4); + params[6].buffer = &v.f4; + params[6].length = ¶ms[6].buffer_length; + params[6].is_null = NULL; + + params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[7].buffer_length = sizeof(v.f8); + params[7].buffer = &v.f8; + params[7].length = ¶ms[7].buffer_length; + params[7].is_null = NULL; + + params[8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[8].buffer_length = sizeof(v.bin); + params[8].buffer = v.bin; + params[8].length = ¶ms[8].buffer_length; + params[8].is_null = NULL; + + strcpy(v.blob, "一二三四五六七八九十"); + params[9].buffer_type = TSDB_DATA_TYPE_NCHAR; + params[9].buffer_length = strlen(v.blob); + params[9].buffer = v.blob; + params[9].length = ¶ms[9].buffer_length; + params[9].is_null = NULL; + + params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT; + params[10].buffer_length = sizeof(v.u1); + params[10].buffer = &v.u1; + params[10].length = ¶ms[10].buffer_length; + params[10].is_null = NULL; + + params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT; + params[11].buffer_length = sizeof(v.u2); + params[11].buffer = &v.u2; + params[11].length = ¶ms[11].buffer_length; + params[11].is_null = NULL; + + params[12].buffer_type = TSDB_DATA_TYPE_UINT; + params[12].buffer_length = sizeof(v.u4); + params[12].buffer = &v.u4; + params[12].length = ¶ms[12].buffer_length; + params[12].is_null = NULL; + + params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT; + params[13].buffer_length = sizeof(v.u8); + params[13].buffer = &v.u8; + params[13].length = ¶ms[13].buffer_length; + params[13].is_null = NULL; + + int is_null = 1; + + sql = "insert into m1 values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + v.ts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts += 1; + for (int j = 1; j < 10; ++j) { + params[j].is_null = ((i == j) ? &is_null : 0); + } + v.b = (int8_t)i % 2; + v.v1 = (int8_t)i; + v.v2 = (int16_t)(i * 2); + v.v4 = (int32_t)(i * 4); + v.v8 = (int64_t)(i * 8); + v.f4 = (float)(i * 40); + v.f8 = (double)(i * 80); + for (int j = 0; j < sizeof(v.bin); ++j) { + v.bin[j] = (char)(i + '0'); + } + v.u1 = (uint8_t)i; + v.u2 = (uint16_t)(i * 2); + v.u4 = (uint32_t)(i * 4); + v.u8 = (uint64_t)(i * 8); + + taos_stmt_bind_param(stmt, params); + taos_stmt_add_batch(stmt); + } + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + int affectedRows = taos_stmt_affected_rows(stmt); + printf("sucessfully inserted %d rows\n", affectedRows); + + taos_stmt_close(stmt); + + // query the records + stmt = taos_stmt_init(taos); + taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0); + v.v1 = 5; + v.v2 = 15; + taos_stmt_bind_param(stmt, params + 2); + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + result = taos_stmt_use_result(stmt); + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_num_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); + + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[256] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("%s\n", temp); + } + + taos_free_result(result); + taos_stmt_close(stmt); +} + +void verify_prepare2(TAOS* taos) { + TAOS_RES* result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test;"); + + int code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + usleep(100000); + taos_select_db(taos, "test"); + + // create table + const char* sql = + "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned)"; + result = taos_query(taos, sql); + code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + // insert 10 records + struct { + int64_t ts; + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40]; + char blob[80]; + uint8_t u1; + uint16_t u2; + uint32_t u4; + uint64_t u8; + } v = {0}; + + TAOS_STMT* stmt = taos_stmt_init(taos); + TAOS_BIND params[14]; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(v.ts); + params[0].buffer = &v.ts; + params[0].length = ¶ms[0].buffer_length; + params[0].is_null = NULL; + + params[1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[1].buffer_length = sizeof(v.b); + params[1].buffer = &v.b; + params[1].length = ¶ms[1].buffer_length; + params[1].is_null = NULL; + + params[2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[2].buffer_length = sizeof(v.v1); + params[2].buffer = &v.v1; + params[2].length = ¶ms[2].buffer_length; + params[2].is_null = NULL; + + params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[3].buffer_length = sizeof(v.v2); + params[3].buffer = &v.v2; + params[3].length = ¶ms[3].buffer_length; + params[3].is_null = NULL; + + params[4].buffer_type = TSDB_DATA_TYPE_INT; + params[4].buffer_length = sizeof(v.v4); + params[4].buffer = &v.v4; + params[4].length = ¶ms[4].buffer_length; + params[4].is_null = NULL; + + params[5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[5].buffer_length = sizeof(v.v8); + params[5].buffer = &v.v8; + params[5].length = ¶ms[5].buffer_length; + params[5].is_null = NULL; + + params[6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[6].buffer_length = sizeof(v.f4); + params[6].buffer = &v.f4; + params[6].length = ¶ms[6].buffer_length; + params[6].is_null = NULL; + + params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[7].buffer_length = sizeof(v.f8); + params[7].buffer = &v.f8; + params[7].length = ¶ms[7].buffer_length; + params[7].is_null = NULL; + + params[8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[8].buffer_length = sizeof(v.bin); + params[8].buffer = v.bin; + params[8].length = ¶ms[8].buffer_length; + params[8].is_null = NULL; + + strcpy(v.blob, "一二三四五六七八九十"); + params[9].buffer_type = TSDB_DATA_TYPE_NCHAR; + params[9].buffer_length = strlen(v.blob); + params[9].buffer = v.blob; + params[9].length = ¶ms[9].buffer_length; + params[9].is_null = NULL; + + params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT; + params[10].buffer_length = sizeof(v.u1); + params[10].buffer = &v.u1; + params[10].length = ¶ms[10].buffer_length; + params[10].is_null = NULL; + + params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT; + params[11].buffer_length = sizeof(v.u2); + params[11].buffer = &v.u2; + params[11].length = ¶ms[11].buffer_length; + params[11].is_null = NULL; + + params[12].buffer_type = TSDB_DATA_TYPE_UINT; + params[12].buffer_length = sizeof(v.u4); + params[12].buffer = &v.u4; + params[12].length = ¶ms[12].buffer_length; + params[12].is_null = NULL; + + params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT; + params[13].buffer_length = sizeof(v.u8); + params[13].buffer = &v.u8; + params[13].length = ¶ms[13].buffer_length; + params[13].is_null = NULL; + + sql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + code = taos_stmt_set_tbname(stmt, "m1"); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + int is_null = 1; + + v.ts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts += 1; + for (int j = 1; j < 10; ++j) { + params[j].is_null = ((i == j) ? &is_null : 0); + } + v.b = (int8_t)i % 2; + v.v1 = (int8_t)i; + v.v2 = (int16_t)(i * 2); + v.v4 = (int32_t)(i * 4); + v.v8 = (int64_t)(i * 8); + v.f4 = (float)(i * 40); + v.f8 = (double)(i * 80); + for (int j = 0; j < sizeof(v.bin); ++j) { + v.bin[j] = (char)(i + '0'); + } + v.u1 = (uint8_t)i; + v.u2 = (uint16_t)(i * 2); + v.u4 = (uint32_t)(i * 4); + v.u8 = (uint64_t)(i * 8); + + taos_stmt_bind_param(stmt, params); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + int affectedRows = taos_stmt_affected_rows(stmt); + printf("sucessfully inserted %d rows\n", affectedRows); + + taos_stmt_close(stmt); + + // query the records + stmt = taos_stmt_init(taos); + taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0); + TAOS_BIND qparams[2]; + + int8_t v1 = 5; + int16_t v2 = 15; + qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT; + qparams[0].buffer_length = sizeof(v1); + qparams[0].buffer = &v1; + qparams[0].length = &qparams[0].buffer_length; + qparams[0].is_null = NULL; + + qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT; + qparams[1].buffer_length = sizeof(v2); + qparams[1].buffer = &v2; + qparams[1].length = &qparams[1].buffer_length; + qparams[1].is_null = NULL; + + taos_stmt_bind_param(stmt, qparams); + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + result = taos_stmt_use_result(stmt); + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_num_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); + + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[256] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("%s\n", temp); + } + + taos_free_result(result); + taos_stmt_close(stmt); +} + +void verify_prepare3(TAOS* taos) { + TAOS_RES* result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test;"); + + int code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + usleep(100000); + taos_select_db(taos, "test"); + + // create table + const char* sql = + "create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned) " + "tags " + "(b_tag bool, v1_tag tinyint, v2_tag smallint, v4_tag int, v8_tag bigint, f4_tag float, f8_tag double, bin_tag " + "binary(40), blob_tag nchar(10), u1_tag tinyint unsigned, u2_tag smallint unsigned, u4_tag int unsigned, u8_tag " + "bigint " + "unsigned)"; + result = taos_query(taos, sql); + code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + TAOS_BIND tags[13]; + + struct { + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40]; + char blob[80]; + uint8_t u1; + uint16_t u2; + uint32_t u4; + uint64_t u8; + } id = {0}; + + id.b = (int8_t)1; + id.v1 = (int8_t)1; + id.v2 = (int16_t)2; + id.v4 = (int32_t)4; + id.v8 = (int64_t)8; + id.f4 = (float)40; + id.f8 = (double)80; + for (int j = 0; j < sizeof(id.bin); ++j) { + id.bin[j] = (char)('1' + '0'); + } + strcpy(id.blob, "一二三四五六七八九十"); + id.u1 = (uint8_t)1; + id.u2 = (uint16_t)2; + id.u4 = (uint32_t)4; + id.u8 = (uint64_t)8; + + tags[0].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[0].buffer_length = sizeof(id.b); + tags[0].buffer = &id.b; + tags[0].length = &tags[0].buffer_length; + tags[0].is_null = NULL; + + tags[1].buffer_type = TSDB_DATA_TYPE_TINYINT; + tags[1].buffer_length = sizeof(id.v1); + tags[1].buffer = &id.v1; + tags[1].length = &tags[1].buffer_length; + tags[1].is_null = NULL; + + tags[2].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[2].buffer_length = sizeof(id.v2); + tags[2].buffer = &id.v2; + tags[2].length = &tags[2].buffer_length; + tags[2].is_null = NULL; + + tags[3].buffer_type = TSDB_DATA_TYPE_INT; + tags[3].buffer_length = sizeof(id.v4); + tags[3].buffer = &id.v4; + tags[3].length = &tags[3].buffer_length; + tags[3].is_null = NULL; + + tags[4].buffer_type = TSDB_DATA_TYPE_BIGINT; + tags[4].buffer_length = sizeof(id.v8); + tags[4].buffer = &id.v8; + tags[4].length = &tags[4].buffer_length; + tags[4].is_null = NULL; + + tags[5].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[5].buffer_length = sizeof(id.f4); + tags[5].buffer = &id.f4; + tags[5].length = &tags[5].buffer_length; + tags[5].is_null = NULL; + + tags[6].buffer_type = TSDB_DATA_TYPE_DOUBLE; + tags[6].buffer_length = sizeof(id.f8); + tags[6].buffer = &id.f8; + tags[6].length = &tags[6].buffer_length; + tags[6].is_null = NULL; + + tags[7].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[7].buffer_length = sizeof(id.bin); + tags[7].buffer = &id.bin; + tags[7].length = &tags[7].buffer_length; + tags[7].is_null = NULL; + + tags[8].buffer_type = TSDB_DATA_TYPE_NCHAR; + tags[8].buffer_length = strlen(id.blob); + tags[8].buffer = &id.blob; + tags[8].length = &tags[8].buffer_length; + tags[8].is_null = NULL; + + tags[9].buffer_type = TSDB_DATA_TYPE_UTINYINT; + tags[9].buffer_length = sizeof(id.u1); + tags[9].buffer = &id.u1; + tags[9].length = &tags[9].buffer_length; + tags[9].is_null = NULL; + + tags[10].buffer_type = TSDB_DATA_TYPE_USMALLINT; + tags[10].buffer_length = sizeof(id.u2); + tags[10].buffer = &id.u2; + tags[10].length = &tags[10].buffer_length; + tags[10].is_null = NULL; + + tags[11].buffer_type = TSDB_DATA_TYPE_UINT; + tags[11].buffer_length = sizeof(id.u4); + tags[11].buffer = &id.u4; + tags[11].length = &tags[11].buffer_length; + tags[11].is_null = NULL; + + tags[12].buffer_type = TSDB_DATA_TYPE_UBIGINT; + tags[12].buffer_length = sizeof(id.u8); + tags[12].buffer = &id.u8; + tags[12].length = &tags[12].buffer_length; + tags[12].is_null = NULL; + // insert 10 records + struct { + int64_t ts[10]; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + char blob[10][80]; + uint8_t u1[10]; + uint16_t u2[10]; + uint32_t u4[10]; + uint64_t u8[10]; + } v; + + int32_t* t8_len = malloc(sizeof(int32_t) * 10); + int32_t* t16_len = malloc(sizeof(int32_t) * 10); + int32_t* t32_len = malloc(sizeof(int32_t) * 10); + int32_t* t64_len = malloc(sizeof(int32_t) * 10); + int32_t* float_len = malloc(sizeof(int32_t) * 10); + int32_t* double_len = malloc(sizeof(int32_t) * 10); + int32_t* bin_len = malloc(sizeof(int32_t) * 10); + int32_t* blob_len = malloc(sizeof(int32_t) * 10); + int32_t* u8_len = malloc(sizeof(int32_t) * 10); + int32_t* u16_len = malloc(sizeof(int32_t) * 10); + int32_t* u32_len = malloc(sizeof(int32_t) * 10); + int32_t* u64_len = malloc(sizeof(int32_t) * 10); + + TAOS_STMT* stmt = taos_stmt_init(taos); + TAOS_MULTI_BIND params[14]; + char is_null[10] = {0}; + + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(v.ts[0]); + params[0].buffer = v.ts; + params[0].length = t64_len; + params[0].is_null = is_null; + params[0].num = 10; + + params[1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[1].buffer_length = sizeof(v.b[0]); + params[1].buffer = v.b; + params[1].length = t8_len; + params[1].is_null = is_null; + params[1].num = 10; + + params[2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[2].buffer_length = sizeof(v.v1[0]); + params[2].buffer = v.v1; + params[2].length = t8_len; + params[2].is_null = is_null; + params[2].num = 10; + + params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[3].buffer_length = sizeof(v.v2[0]); + params[3].buffer = v.v2; + params[3].length = t16_len; + params[3].is_null = is_null; + params[3].num = 10; + + params[4].buffer_type = TSDB_DATA_TYPE_INT; + params[4].buffer_length = sizeof(v.v4[0]); + params[4].buffer = v.v4; + params[4].length = t32_len; + params[4].is_null = is_null; + params[4].num = 10; + + params[5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[5].buffer_length = sizeof(v.v8[0]); + params[5].buffer = v.v8; + params[5].length = t64_len; + params[5].is_null = is_null; + params[5].num = 10; + + params[6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[6].buffer_length = sizeof(v.f4[0]); + params[6].buffer = v.f4; + params[6].length = float_len; + params[6].is_null = is_null; + params[6].num = 10; + + params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[7].buffer_length = sizeof(v.f8[0]); + params[7].buffer = v.f8; + params[7].length = double_len; + params[7].is_null = is_null; + params[7].num = 10; + + params[8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[8].buffer_length = sizeof(v.bin[0]); + params[8].buffer = v.bin; + params[8].length = bin_len; + params[8].is_null = is_null; + params[8].num = 10; + + params[9].buffer_type = TSDB_DATA_TYPE_NCHAR; + params[9].buffer_length = sizeof(v.blob[0]); + params[9].buffer = v.blob; + params[9].length = blob_len; + params[9].is_null = is_null; + params[9].num = 10; + + params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT; + params[10].buffer_length = sizeof(v.u1[0]); + params[10].buffer = v.u1; + params[10].length = u8_len; + params[10].is_null = is_null; + params[10].num = 10; + + params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT; + params[11].buffer_length = sizeof(v.u2[0]); + params[11].buffer = v.u2; + params[11].length = u16_len; + params[11].is_null = is_null; + params[11].num = 10; + + params[12].buffer_type = TSDB_DATA_TYPE_UINT; + params[12].buffer_length = sizeof(v.u4[0]); + params[12].buffer = v.u4; + params[12].length = u32_len; + params[12].is_null = is_null; + params[12].num = 10; + + params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT; + params[13].buffer_length = sizeof(v.u8[0]); + params[13].buffer = v.u8; + params[13].length = u64_len; + params[13].is_null = is_null; + params[13].num = 10; + + sql = "insert into ? using st1 tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + code = taos_stmt_set_tbname_tags(stmt, "m1", tags); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_set_tbname_tags. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + int64_t ts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = ts++; + is_null[i] = 0; + + v.b[i] = (int8_t)i % 2; + v.v1[i] = (int8_t)i; + v.v2[i] = (int16_t)(i * 2); + v.v4[i] = (int32_t)(i * 4); + v.v8[i] = (int64_t)(i * 8); + v.f4[i] = (float)(i * 40); + v.f8[i] = (double)(i * 80); + for (int j = 0; j < sizeof(v.bin[0]); ++j) { + v.bin[i][j] = (char)(i + '0'); + } + strcpy(v.blob[i], "一二三四五六七八九十"); + v.u1[i] = (uint8_t)i; + v.u2[i] = (uint16_t)(i * 2); + v.u4[i] = (uint32_t)(i * 4); + v.u8[i] = (uint64_t)(i * 8); + + t8_len[i] = sizeof(int8_t); + t16_len[i] = sizeof(int16_t); + t32_len[i] = sizeof(int32_t); + t64_len[i] = sizeof(int64_t); + float_len[i] = sizeof(float); + double_len[i] = sizeof(double); + bin_len[i] = sizeof(v.bin[0]); + blob_len[i] = (int32_t)strlen(v.blob[i]); + u8_len[i] = sizeof(uint8_t); + u16_len[i] = sizeof(uint16_t); + u32_len[i] = sizeof(uint32_t); + u64_len[i] = sizeof(uint64_t); + } + + taos_stmt_bind_param_batch(stmt, params); + taos_stmt_add_batch(stmt); + + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + int affectedRows = taos_stmt_affected_rows(stmt); + printf("successfully inserted %d rows\n", affectedRows); + + taos_stmt_close(stmt); + + // query the records + stmt = taos_stmt_init(taos); + taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0); + + TAOS_BIND qparams[2]; + + int8_t v1 = 5; + int16_t v2 = 15; + qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT; + qparams[0].buffer_length = sizeof(v1); + qparams[0].buffer = &v1; + qparams[0].length = &qparams[0].buffer_length; + qparams[0].is_null = NULL; + + qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT; + qparams[1].buffer_length = sizeof(v2); + qparams[1].buffer = &v2; + qparams[1].length = &qparams[1].buffer_length; + qparams[1].is_null = NULL; + + taos_stmt_bind_param(stmt, qparams); + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + result = taos_stmt_use_result(stmt); + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_num_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); + + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[256] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("%s\n", temp); + } + + taos_free_result(result); + taos_stmt_close(stmt); + + free(t8_len); + free(t16_len); + free(t32_len); + free(t64_len); + free(float_len); + free(double_len); + free(bin_len); + free(blob_len); + free(u8_len); + free(u16_len); + free(u32_len); + free(u64_len); + +} + +/** + * @brief Verify the upper/lower case of tableName for create(by setTableName)/query/show/describe/drop. + * https://jira.taosdata.com:18080/browse/TS-904 + * https://jira.taosdata.com:18090/pages/viewpage.action?pageId=129140555 + * @param taos + */ +void verify_prepare4(TAOS* taos) { + printf("Verify the upper/lower case of tableName for create(by setTableName)/query/show/describe/drop etc.\n"); + + TAOS_RES* result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test;"); + + int code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + usleep(100000); + taos_select_db(taos, "test"); + + // create table + const char* sql = + "create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned) " + "tags " + "(b_tag bool, v1_tag tinyint, v2_tag smallint, v4_tag int, v8_tag bigint, f4_tag float, f8_tag double, bin_tag " + "binary(40), blob_tag nchar(10), u1_tag tinyint unsigned, u2_tag smallint unsigned, u4_tag int unsigned, u8_tag " + "bigint " + "unsigned)"; + result = taos_query(taos, sql); + code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); + + TAOS_BIND tags[13]; + + struct { + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40]; + char blob[80]; + uint8_t u1; + uint16_t u2; + uint32_t u4; + uint64_t u8; + } id = {0}; + + id.b = (int8_t)1; + id.v1 = (int8_t)1; + id.v2 = (int16_t)2; + id.v4 = (int32_t)4; + id.v8 = (int64_t)8; + id.f4 = (float)40; + id.f8 = (double)80; + for (int j = 0; j < sizeof(id.bin); ++j) { + id.bin[j] = (char)('1' + '0'); + } + strcpy(id.blob, "一二三四五六七八九十"); + id.u1 = (uint8_t)1; + id.u2 = (uint16_t)2; + id.u4 = (uint32_t)4; + id.u8 = (uint64_t)8; + + tags[0].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[0].buffer_length = sizeof(id.b); + tags[0].buffer = &id.b; + tags[0].length = &tags[0].buffer_length; + tags[0].is_null = NULL; + + tags[1].buffer_type = TSDB_DATA_TYPE_TINYINT; + tags[1].buffer_length = sizeof(id.v1); + tags[1].buffer = &id.v1; + tags[1].length = &tags[1].buffer_length; + tags[1].is_null = NULL; + + tags[2].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[2].buffer_length = sizeof(id.v2); + tags[2].buffer = &id.v2; + tags[2].length = &tags[2].buffer_length; + tags[2].is_null = NULL; + + tags[3].buffer_type = TSDB_DATA_TYPE_INT; + tags[3].buffer_length = sizeof(id.v4); + tags[3].buffer = &id.v4; + tags[3].length = &tags[3].buffer_length; + tags[3].is_null = NULL; + + tags[4].buffer_type = TSDB_DATA_TYPE_BIGINT; + tags[4].buffer_length = sizeof(id.v8); + tags[4].buffer = &id.v8; + tags[4].length = &tags[4].buffer_length; + tags[4].is_null = NULL; + + tags[5].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[5].buffer_length = sizeof(id.f4); + tags[5].buffer = &id.f4; + tags[5].length = &tags[5].buffer_length; + tags[5].is_null = NULL; + + tags[6].buffer_type = TSDB_DATA_TYPE_DOUBLE; + tags[6].buffer_length = sizeof(id.f8); + tags[6].buffer = &id.f8; + tags[6].length = &tags[6].buffer_length; + tags[6].is_null = NULL; + + tags[7].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[7].buffer_length = sizeof(id.bin); + tags[7].buffer = &id.bin; + tags[7].length = &tags[7].buffer_length; + tags[7].is_null = NULL; + + tags[8].buffer_type = TSDB_DATA_TYPE_NCHAR; + tags[8].buffer_length = strlen(id.blob); + tags[8].buffer = &id.blob; + tags[8].length = &tags[8].buffer_length; + tags[8].is_null = NULL; + + tags[9].buffer_type = TSDB_DATA_TYPE_UTINYINT; + tags[9].buffer_length = sizeof(id.u1); + tags[9].buffer = &id.u1; + tags[9].length = &tags[9].buffer_length; + tags[9].is_null = NULL; + + tags[10].buffer_type = TSDB_DATA_TYPE_USMALLINT; + tags[10].buffer_length = sizeof(id.u2); + tags[10].buffer = &id.u2; + tags[10].length = &tags[10].buffer_length; + tags[10].is_null = NULL; + + tags[11].buffer_type = TSDB_DATA_TYPE_UINT; + tags[11].buffer_length = sizeof(id.u4); + tags[11].buffer = &id.u4; + tags[11].length = &tags[11].buffer_length; + tags[11].is_null = NULL; + + tags[12].buffer_type = TSDB_DATA_TYPE_UBIGINT; + tags[12].buffer_length = sizeof(id.u8); + tags[12].buffer = &id.u8; + tags[12].length = &tags[12].buffer_length; + tags[12].is_null = NULL; + // insert 10 records + struct { + int64_t ts[10]; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + char blob[10][80]; + uint8_t u1[10]; + uint16_t u2[10]; + uint32_t u4[10]; + uint64_t u8[10]; + } v; + + int32_t* t8_len = malloc(sizeof(int32_t) * 10); + int32_t* t16_len = malloc(sizeof(int32_t) * 10); + int32_t* t32_len = malloc(sizeof(int32_t) * 10); + int32_t* t64_len = malloc(sizeof(int32_t) * 10); + int32_t* float_len = malloc(sizeof(int32_t) * 10); + int32_t* double_len = malloc(sizeof(int32_t) * 10); + int32_t* bin_len = malloc(sizeof(int32_t) * 10); + int32_t* blob_len = malloc(sizeof(int32_t) * 10); + int32_t* u8_len = malloc(sizeof(int32_t) * 10); + int32_t* u16_len = malloc(sizeof(int32_t) * 10); + int32_t* u32_len = malloc(sizeof(int32_t) * 10); + int32_t* u64_len = malloc(sizeof(int32_t) * 10); + + TAOS_MULTI_BIND params[14]; + char is_null[10] = {0}; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(v.ts[0]); + params[0].buffer = v.ts; + params[0].length = t64_len; + params[0].is_null = is_null; + params[0].num = 10; + + params[1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[1].buffer_length = sizeof(v.b[0]); + params[1].buffer = v.b; + params[1].length = t8_len; + params[1].is_null = is_null; + params[1].num = 10; + + params[2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[2].buffer_length = sizeof(v.v1[0]); + params[2].buffer = v.v1; + params[2].length = t8_len; + params[2].is_null = is_null; + params[2].num = 10; + + params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[3].buffer_length = sizeof(v.v2[0]); + params[3].buffer = v.v2; + params[3].length = t16_len; + params[3].is_null = is_null; + params[3].num = 10; + + params[4].buffer_type = TSDB_DATA_TYPE_INT; + params[4].buffer_length = sizeof(v.v4[0]); + params[4].buffer = v.v4; + params[4].length = t32_len; + params[4].is_null = is_null; + params[4].num = 10; + + params[5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[5].buffer_length = sizeof(v.v8[0]); + params[5].buffer = v.v8; + params[5].length = t64_len; + params[5].is_null = is_null; + params[5].num = 10; + + params[6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[6].buffer_length = sizeof(v.f4[0]); + params[6].buffer = v.f4; + params[6].length = float_len; + params[6].is_null = is_null; + params[6].num = 10; + + params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[7].buffer_length = sizeof(v.f8[0]); + params[7].buffer = v.f8; + params[7].length = double_len; + params[7].is_null = is_null; + params[7].num = 10; + + params[8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[8].buffer_length = sizeof(v.bin[0]); + params[8].buffer = v.bin; + params[8].length = bin_len; + params[8].is_null = is_null; + params[8].num = 10; + + params[9].buffer_type = TSDB_DATA_TYPE_NCHAR; + params[9].buffer_length = sizeof(v.blob[0]); + params[9].buffer = v.blob; + params[9].length = blob_len; + params[9].is_null = is_null; + params[9].num = 10; + + params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT; + params[10].buffer_length = sizeof(v.u1[0]); + params[10].buffer = v.u1; + params[10].length = u8_len; + params[10].is_null = is_null; + params[10].num = 10; + + params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT; + params[11].buffer_length = sizeof(v.u2[0]); + params[11].buffer = v.u2; + params[11].length = u16_len; + params[11].is_null = is_null; + params[11].num = 10; + + params[12].buffer_type = TSDB_DATA_TYPE_UINT; + params[12].buffer_length = sizeof(v.u4[0]); + params[12].buffer = v.u4; + params[12].length = u32_len; + params[12].is_null = is_null; + params[12].num = 10; + + params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT; + params[13].buffer_length = sizeof(v.u8[0]); + params[13].buffer = v.u8; + params[13].length = u64_len; + params[13].is_null = is_null; + params[13].num = 10; + +// verify table names for upper/lower case +#define VERIFY_CNT 5 + + typedef struct { + char setTbName[20]; + char showName[20]; + char describeName[20]; + char queryName[20]; + char dropName[20]; + } STbNames; + + /** + * @brief + * 0 - success expected + * NonZero - fail expected + */ + typedef struct { + int32_t setTbName; + int32_t showName; + int32_t describeName; + int32_t queryName; + int32_t dropName; + } STbNamesResult; + + STbNames tbName[VERIFY_CNT] = {0}; + STbNamesResult tbNameResult[VERIFY_CNT] = {0}; + + STbNames* pTbName = NULL; + STbNamesResult* pTbNameResult = NULL; + + pTbName = &tbName[0]; + pTbNameResult = &tbNameResult[0]; + strcpy(pTbName->setTbName, "Mn1"); + strcpy(pTbName->showName, "mn1"); + strcpy(pTbName->describeName, "mn1"); + strcpy(pTbName->queryName, "mn1"); + strcpy(pTbName->dropName, "mn1"); + + pTbName = &tbName[1]; + pTbNameResult = &tbNameResult[1]; + strcpy(pTbName->setTbName, "'Mn1'"); + strcpy(pTbName->showName, "'mn1'"); + strcpy(pTbName->describeName, "'mn1'"); + strcpy(pTbName->queryName, "'mn1'"); + strcpy(pTbName->dropName, "'mn1'"); + + pTbName = &tbName[2]; + pTbNameResult = &tbNameResult[2]; + strcpy(pTbName->setTbName, "\"Mn1\""); + strcpy(pTbName->showName, "\"mn1\""); + strcpy(pTbName->describeName, "\"mn1\""); + strcpy(pTbName->queryName, "\"mn1\""); + strcpy(pTbName->dropName, "\"mn1\""); + + pTbName = &tbName[3]; + pTbNameResult = &tbNameResult[3]; + strcpy(pTbName->setTbName, "\"Mn1\""); + strcpy(pTbName->showName, "'mn1'"); + strcpy(pTbName->describeName, "'mn1'"); + strcpy(pTbName->queryName, "mn1"); + strcpy(pTbName->dropName, "\"mn1\""); + + pTbName = &tbName[4]; + pTbNameResult = &tbNameResult[4]; + strcpy(pTbName->setTbName, "`Mn1`"); + strcpy(pTbName->showName, "Mn1"); // TODO support uniform of `` + strcpy(pTbName->describeName, "`Mn1`"); + strcpy(pTbName->queryName, "`Mn1`"); + strcpy(pTbName->dropName, "`Mn1`"); + + TAOS_STMT* stmt = NULL; + + for (int n = 0; n < VERIFY_CNT; ++n) { + printf("\033[31m[%d] ===================================\033[0m\n", n); + pTbName = &tbName[n]; + pTbNameResult = &tbNameResult[n]; + char tmpStr[256] = {0}; + + // set table name + stmt = taos_stmt_init(taos); + if (!stmt) { + printf("\033[31m[%d] failed to execute taos_stmt_init. error:%s\033[0m\n", n); + exit(EXIT_FAILURE); + } + + sql = "insert into ? using st1 tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + printf("[%d] taos_stmt_set_tbname_tags, tbname=%s\n", n, pTbName->setTbName); + code = taos_stmt_set_tbname_tags(stmt, pTbName->setTbName, tags); + if ((!pTbNameResult->setTbName && (0 != code)) || (pTbNameResult->setTbName && (0 == code))) { + printf("\033[31m[%d] failed to execute taos_stmt_set_tbname_tags. error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + if (code == 0) { + int64_t ts = 1591060628000 + 1000 * n; + for (int i = 0; i < 10; ++i) { + v.ts[i] = ts++; + is_null[i] = 0; + + v.b[i] = (int8_t)i % 2; + v.v1[i] = (int8_t)i; + v.v2[i] = (int16_t)(i * 2); + v.v4[i] = (int32_t)(i * 4); + v.v8[i] = (int64_t)(i * 8); + v.f4[i] = (float)(i * 40); + v.f8[i] = (double)(i * 80); + for (int j = 0; j < sizeof(v.bin[0]); ++j) { + v.bin[i][j] = (char)(i + '0'); + } + strcpy(v.blob[i], "一二三四五六七八九十"); + v.u1[i] = (uint8_t)i; + v.u2[i] = (uint16_t)(i * 2); + v.u4[i] = (uint32_t)(i * 4); + v.u8[i] = (uint64_t)(i * 8); + + t8_len[i] = sizeof(int8_t); + t16_len[i] = sizeof(int16_t); + t32_len[i] = sizeof(int32_t); + t64_len[i] = sizeof(int64_t); + float_len[i] = sizeof(float); + double_len[i] = sizeof(double); + bin_len[i] = sizeof(v.bin[0]); + blob_len[i] = (int32_t)strlen(v.blob[i]); + u8_len[i] = sizeof(uint8_t); + u16_len[i] = sizeof(uint16_t); + u32_len[i] = sizeof(uint32_t); + u64_len[i] = sizeof(uint64_t); + } + + taos_stmt_bind_param_batch(stmt, params); + taos_stmt_add_batch(stmt); + + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31m[%d] failed to execute insert statement.error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + } + taos_stmt_close(stmt); + + // show the table + printf("[%d] show tables, tbName = %s\n", n, pTbName->showName); + stmt = taos_stmt_init(taos); + sprintf(tmpStr, "show tables like %s", pTbName->showName); + taos_stmt_prepare(stmt, tmpStr, 0); + code = taos_stmt_execute(stmt); + if ((!pTbNameResult->showName && (0 != code)) || (pTbNameResult->showName && (0 == code))) { + printf("\033[31m[%d] failed to execute show tables like. error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + taos_stmt_close(stmt); + + // describe the table + printf("[%d] describe tables, tbName = %s\n", n, pTbName->describeName); + stmt = taos_stmt_init(taos); + sprintf(tmpStr, "describe %s", pTbName->describeName); + taos_stmt_prepare(stmt, tmpStr, 0); + code = taos_stmt_execute(stmt); + if ((!pTbNameResult->describeName && (0 != code)) || (pTbNameResult->describeName && (0 == code))) { + printf("\033[31m[%d] failed to execute describe tables. error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + taos_stmt_close(stmt); + + // query the records + printf("[%d] select statement, tbName = %s\n", n, pTbName->queryName); + stmt = taos_stmt_init(taos); + sprintf(tmpStr, "SELECT * FROM %s", pTbName->queryName); + taos_stmt_prepare(stmt, tmpStr, 0); + + TAOS_BIND qparams[2]; + + int8_t v1 = 5; + int16_t v2 = 15; + qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT; + qparams[0].buffer_length = sizeof(v1); + qparams[0].buffer = &v1; + qparams[0].length = &qparams[0].buffer_length; + qparams[0].is_null = NULL; + + qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT; + qparams[1].buffer_length = sizeof(v2); + qparams[1].buffer = &v2; + qparams[1].length = &qparams[1].buffer_length; + qparams[1].is_null = NULL; + + taos_stmt_bind_param(stmt, qparams); + + code = taos_stmt_execute(stmt); + if ((!pTbNameResult->queryName && (0 != code)) || (pTbNameResult->queryName && (0 == code))) { + printf("\033[31m[%d] failed to execute select statement.error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + + result = taos_stmt_use_result(stmt); + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_num_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); + + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[256] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("[%d] row = %s\n", n, temp); + } + + taos_free_result(result); + taos_stmt_close(stmt); + + // drop table + printf("[%d] drop table, tbName = %s\n", n, pTbName->dropName); + stmt = taos_stmt_init(taos); + sprintf(tmpStr, "drop table %s", pTbName->dropName); + taos_stmt_prepare(stmt, tmpStr, 0); + code = taos_stmt_execute(stmt); + if ((!pTbNameResult->dropName && (0 != code)) || (pTbNameResult->dropName && (0 == code))) { + printf("\033[31m[%d] failed to drop table. error:%s\033[0m\n", n, taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + exit(EXIT_FAILURE); + } + taos_stmt_close(stmt); + } + + free(t8_len); + free(t16_len); + free(t32_len); + free(t64_len); + free(float_len); + free(double_len); + free(bin_len); + free(blob_len); + free(u8_len); + free(u16_len); + free(u32_len); + free(u64_len); +} + +int main(int argc, char* argv[]) { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + TAOS* taos = taos_connect(host, user, passwd, "", 0); + if (taos == NULL) { + printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos)); + exit(1); + } + + char* info = taos_get_server_info(taos); + printf("server info: %s\n", info); + info = taos_get_client_info(taos); + printf("client info: %s\n", info); + printf("************ verify prepare *************\n"); + verify_prepare(taos); + printf("************ verify prepare2 *************\n"); + verify_prepare2(taos); + printf("************ verify prepare3 *************\n"); + verify_prepare3(taos); + printf("************ verify prepare4 *************\n"); + verify_prepare4(taos); + printf("************ verify end *************\n"); + exit(EXIT_SUCCESS); +} diff --git a/examples/c/schemaless.c b/examples/c/schemaless.c new file mode 100644 index 0000000000000000000000000000000000000000..e7f62ffdfe5628689a290730062f429d09170f6f --- /dev/null +++ b/examples/c/schemaless.c @@ -0,0 +1,315 @@ +#include "os.h" +#include "taos.h" +#include "taoserror.h" + +#include +#include +#include +#include +#include + +bool verbose = false; + + +void printThreadId(pthread_t id, char* buf) +{ + size_t i; + for (i = sizeof(i); i; --i) + sprintf(buf + strlen(buf), "%02x", *(((unsigned char*) &id) + i - 1)); +} + +static int64_t getTimeInUs() { + struct timeval systemTime; + gettimeofday(&systemTime, NULL); + return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec; +} + +typedef struct { + char** lines; + int numLines; +} SThreadLinesBatch; + +typedef struct { + TAOS* taos; + int protocol; + int numBatches; + SThreadLinesBatch *batches; + int64_t costTime; +} SThreadInsertArgs; + +static void* insertLines(void* args) { + SThreadInsertArgs* insertArgs = (SThreadInsertArgs*) args; + char tidBuf[32] = {0}; + printThreadId(pthread_self(), tidBuf); + for (int i = 0; i < insertArgs->numBatches; ++i) { + SThreadLinesBatch* batch = insertArgs->batches + i; + if (verbose) printf("%s, thread: 0x%s\n", "begin taos_insert_lines", tidBuf); + int64_t begin = getTimeInUs(); + //int32_t code = taos_insert_lines(insertArgs->taos, batch->lines, batch->numLines); + TAOS_RES * res = taos_schemaless_insert(insertArgs->taos, batch->lines, batch->numLines, insertArgs->protocol, TSDB_SML_TIMESTAMP_MILLI_SECONDS); + int32_t code = taos_errno(res); + int64_t end = getTimeInUs(); + insertArgs->costTime += end - begin; + if (verbose) printf("code: %d, %s. time used:%"PRId64", thread: 0x%s\n", code, tstrerror(code), end - begin, tidBuf); + } + return NULL; +} + +int32_t getTelenetTemplate(char* lineTemplate, int templateLen) { + char* sample = "sta%d %lld 44.3 t0=False t1=127i8 t2=32 t3=%di32 t4=9223372036854775807i64 t5=11.12345f32 t6=22.123456789f64 t7=\"hpxzrdiw\" t8=\"ncharTagValue\" t9=127i8"; + snprintf(lineTemplate, templateLen, "%s", sample); + return 0; +} + +int32_t getLineTemplate(char* lineTemplate, int templateLen, int numFields) { + if (numFields <= 4) { + char* sample = "sta%d,t3=%di32 c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64 %lld"; + snprintf(lineTemplate, templateLen, "%s", sample); + return 0; + } + + if (numFields <= 13) { + char* sample = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=254u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lld"; + snprintf(lineTemplate, templateLen, "%s", sample); + return 0; + } + + char* lineFormatTable = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32 "; + snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "%s", lineFormatTable); + + int offset[] = {numFields*2/5, numFields*4/5, numFields}; + + for (int i = 0; i < offset[0]; ++i) { + snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=%di32,", i, i); + } + + for (int i=offset[0]+1; i < offset[1]; ++i) { + snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=%d.43f64,", i, i); + } + + for (int i = offset[1]+1; i < offset[2]; ++i) { + snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=\"%d\",", i, i); + } + char* lineFormatTs = " %lld"; + snprintf(lineTemplate+strlen(lineTemplate)-1, templateLen-strlen(lineTemplate)+1, "%s", lineFormatTs); + + return 0; +} + +int32_t generateLine(char* line, int lineLen, char* lineTemplate, int protocol, int superTable, int childTable, int64_t ts) { + if (protocol == TSDB_SML_LINE_PROTOCOL) { + snprintf(line, lineLen, lineTemplate, superTable, childTable, ts); + } else if (protocol == TSDB_SML_TELNET_PROTOCOL) { + snprintf(line, lineLen, lineTemplate, superTable, ts, childTable); + } + return TSDB_CODE_SUCCESS; +} + +int32_t setupSuperTables(TAOS* taos, char* lineTemplate, int protocol, + int numSuperTables, int numChildTables, int numRowsPerChildTable, + int maxBatchesPerThread, int64_t ts) { + printf("setup supertables..."); + { + char** linesStb = calloc(numSuperTables, sizeof(char*)); + for (int i = 0; i < numSuperTables; i++) { + char* lineStb = calloc(strlen(lineTemplate)+128, 1); + generateLine(lineStb, strlen(lineTemplate)+128, lineTemplate, protocol, i, + numSuperTables * numChildTables, + ts + numSuperTables * numChildTables * numRowsPerChildTable); + linesStb[i] = lineStb; + } + SThreadInsertArgs args = {0}; + args.protocol = protocol; + args.batches = calloc(maxBatchesPerThread, sizeof(maxBatchesPerThread)); + args.taos = taos; + args.batches[0].lines = linesStb; + args.batches[0].numLines = numSuperTables; + insertLines(&args); + free(args.batches); + for (int i = 0; i < numSuperTables; ++i) { + free(linesStb[i]); + } + free(linesStb); + } + return TSDB_CODE_SUCCESS; +} + +int main(int argc, char* argv[]) { + int numThreads = 8; + int maxBatchesPerThread = 1024; + + int numSuperTables = 1; + int numChildTables = 256; + int numRowsPerChildTable = 8192; + int numFields = 13; + + int maxLinesPerBatch = 16384; + + int protocol = TSDB_SML_TELNET_PROTOCOL; + int assembleSTables = 0; + + int opt; + while ((opt = getopt(argc, argv, "s:c:r:f:t:b:p:w:hv")) != -1) { + switch (opt) { + case 's': + numSuperTables = atoi(optarg); + break; + case 'c': + numChildTables = atoi(optarg); + break; + case 'r': + numRowsPerChildTable = atoi(optarg); + break; + case 'f': + numFields = atoi(optarg); + break; + case 't': + numThreads = atoi(optarg); + break; + case 'b': + maxLinesPerBatch = atoi(optarg); + break; + case 'v': + verbose = true; + break; + case 'a': + assembleSTables = atoi(optarg); + break; + case 'p': + if (optarg[0] == 't') { + protocol = TSDB_SML_TELNET_PROTOCOL; + } else if (optarg[0] == 'l') { + protocol = TSDB_SML_LINE_PROTOCOL; + } else if (optarg[0] == 'j') { + protocol = TSDB_SML_JSON_PROTOCOL; + } + break; + case 'h': + fprintf(stderr, "Usage: %s -s supertable -c childtable -r rows -f fields -t threads -b maxlines_per_batch -p [t|l|j] -a assemble-stables -v\n", + argv[0]); + exit(0); + default: /* '?' */ + fprintf(stderr, "Usage: %s -s supertable -c childtable -r rows -f fields -t threads -b maxlines_per_batch -p [t|l|j] -a assemble-stables -v\n", + argv[0]); + exit(-1); + } + } + + TAOS_RES* result; + //const char* host = "127.0.0.1"; + const char* host = NULL; + const char* user = "root"; + const char* passwd = "taosdata"; + + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + TAOS* taos = taos_connect(host, user, passwd, "", 0); + if (taos == NULL) { + printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos)); + exit(1); + } + + maxBatchesPerThread = (numSuperTables*numChildTables*numRowsPerChildTable)/(numThreads * maxLinesPerBatch) + 1; + + char* info = taos_get_server_info(taos); + printf("server info: %s\n", info); + info = taos_get_client_info(taos); + printf("client info: %s\n", info); + result = taos_query(taos, "drop database if exists db;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database db precision 'us';"); + taos_free_result(result); + usleep(100000); + + (void)taos_select_db(taos, "db"); + + time_t ct = time(0); + int64_t ts = ct * 1000 ; + + char* lineTemplate = calloc(65536, sizeof(char)); + if (protocol == TSDB_SML_LINE_PROTOCOL) { + getLineTemplate(lineTemplate, 65535, numFields); + } else if (protocol == TSDB_SML_TELNET_PROTOCOL ) { + getTelenetTemplate(lineTemplate, 65535); + } + + if (assembleSTables) { + setupSuperTables(taos, lineTemplate, protocol, + numSuperTables, numChildTables, numRowsPerChildTable, maxBatchesPerThread, ts); + } + + printf("generate lines...\n"); + pthread_t* tids = calloc(numThreads, sizeof(pthread_t)); + SThreadInsertArgs* argsThread = calloc(numThreads, sizeof(SThreadInsertArgs)); + for (int i = 0; i < numThreads; ++i) { + argsThread[i].batches = calloc(maxBatchesPerThread, sizeof(SThreadLinesBatch)); + argsThread[i].taos = taos; + argsThread[i].numBatches = 0; + argsThread[i].protocol = protocol; + } + + int64_t totalLines = numSuperTables * numChildTables * numRowsPerChildTable; + int totalBatches = (int) ((totalLines) / maxLinesPerBatch); + if (totalLines % maxLinesPerBatch != 0) { + totalBatches += 1; + } + + char*** allBatches = calloc(totalBatches, sizeof(char**)); + for (int i = 0; i < totalBatches; ++i) { + allBatches[i] = calloc(maxLinesPerBatch, sizeof(char*)); + int threadNo = i % numThreads; + int batchNo = i / numThreads; + argsThread[threadNo].batches[batchNo].lines = allBatches[i]; + argsThread[threadNo].numBatches = batchNo + 1; + } + + int l = 0; + for (int i = 0; i < numSuperTables; ++i) { + for (int j = 0; j < numChildTables; ++j) { + for (int k = 0; k < numRowsPerChildTable; ++k) { + int stIdx = i; + int ctIdx = numSuperTables*numChildTables + j; + char* line = calloc(strlen(lineTemplate)+128, 1); + generateLine(line, strlen(lineTemplate)+128, lineTemplate, protocol, stIdx, ctIdx, ts + l); + int batchNo = l / maxLinesPerBatch; + int lineNo = l % maxLinesPerBatch; + allBatches[batchNo][lineNo] = line; + argsThread[batchNo % numThreads].batches[batchNo/numThreads].numLines = lineNo + 1; + ++l; + } + } + } + + printf("begin multi-thread insertion...\n"); + int64_t begin = taosGetTimestampUs(); + + for (int i=0; i < numThreads; ++i) { + pthread_create(tids+i, NULL, insertLines, argsThread+i); + } + for (int i = 0; i < numThreads; ++i) { + pthread_join(tids[i], NULL); + } + int64_t end = taosGetTimestampUs(); + + size_t linesNum = numSuperTables*numChildTables*numRowsPerChildTable; + printf("TOTAL LINES: %zu\n", linesNum); + printf("THREADS: %d\n", numThreads); + printf("TIME: %d(ms)\n", (int)(end-begin)/1000); + double throughput = (double)(totalLines)/(double)(end-begin) * 1000000; + printf("THROUGHPUT:%d/s\n", (int)throughput); + + for (int i = 0; i < totalBatches; ++i) { + free(allBatches[i]); + } + free(allBatches); + + for (int i = 0; i < numThreads; i++) { + free(argsThread[i].batches); + } + free(argsThread); + free(tids); + + free(lineTemplate); + taos_close(taos); + return 0; +} diff --git a/examples/c/sqlperf.c b/examples/c/sqlperf.c new file mode 100644 index 0000000000000000000000000000000000000000..bde69149651f2b2afffc9c4dffca6f42604f4f2c --- /dev/null +++ b/examples/c/sqlperf.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include "taos.h" // TAOS header file +#include "taoserror.h" +#include "os.h" + +bool verbose = false; +bool describeTableFirst = false; + +typedef struct{ + TAOS* taos; + int numThreads; + int threadId; + int numSTables; +} SThreadArgs; + +static int executeSql(TAOS *taos, char *command) { + if (verbose) { + printf("sql: %s\n", command); + } + TAOS_RES *pSql = NULL; + int32_t code = TSDB_CODE_SUCCESS; + + pSql = taos_query(taos, command); + code = taos_errno(pSql); + + if (code != 0) { + if (verbose) fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql)); + taos_free_result(pSql); + return code; + } + + taos_free_result(pSql); + return 0; +} + +void* threadFunc(void* args) { + char* sqlDescribeSTable = "describe st%d"; + char* sqlCreateSTable = "create table st%d (ts timestamp, value double) " + "tags(t0 nchar(20), t1 nchar(20), t2 nchar(20), t3 nchar(20), t4 nchar(20), " + "t5 nchar(20), t6 nchar(20), t7 nchar(20), t8 nchar(20), t9 nchar(20))"; + + char* sqlInsertData = "insert into t%d using st%d tags('t%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d') values(%lld, %d.%d)"; + + SThreadArgs* param = args; + + int interval = param->numSTables/param->numThreads; + if (param->numSTables % param->numThreads != 0) { + ++interval; + } + int start = param->threadId*interval; + int end = (param->threadId+1)*interval > param->numSTables ? param->numSTables : (param->threadId+1)*interval; + int r = rand(); + + for (int i = start; i < end; ++i) { + int tableId = i; + char sql0[1024] = {0}; + char sql1[1024] = {0}; + char sql2[1024] = {0}; + sprintf(sql0, sqlDescribeSTable, tableId); + sprintf(sql1, sqlCreateSTable, tableId); + time_t ct = time(0); + int64_t ts = ct * 1000; + sprintf(sql2, sqlInsertData, tableId, tableId, r, r, r, r, r, r, r, r, r, r, ts + tableId, r, r); + + if (describeTableFirst) { + executeSql(param->taos, sql0); + } + + executeSql(param->taos, sql1); + + executeSql(param->taos, sql2); + } + return NULL; +} + + +int main(int argc, char *argv[]) { + int numSTables = 20000; + int numThreads = 32; + + int opt; + while ((opt = getopt(argc, argv, "s:t:fvh")) != -1) { + switch (opt) { + case 's': + numSTables = atoi(optarg); + break; + case 't': + numThreads = atoi(optarg); + break; + case 'f': + describeTableFirst = true; + break; + case 'v': + verbose = true; + break; + case 'h': + fprintf(stderr, "Usage: %s -s supertable -t thread -FirstDescribeSTable -Verbose\n", argv[0]); + exit(0); + default: + fprintf(stderr, "Usage: %s -s supertable -t thread -FirstDescribeSTable -Verbose\n", argv[0]); + exit(-1); + } + } + + + // connect to server + TAOS *taos = taos_connect(NULL, "root", "taosdata", NULL, 0); + if (taos == NULL) { + printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/); + exit(1); + } + executeSql(taos, "drop database if exists sqlsml"); + executeSql(taos, "create database sqlsml"); + executeSql(taos, "use sqlsml"); + pthread_t* tids = calloc(numThreads, sizeof(pthread_t)); + SThreadArgs* threadArgs = calloc(numThreads, sizeof(SThreadArgs)); + for (int i = 0; i < numThreads; ++i) { + threadArgs[i].numSTables = numSTables; + threadArgs[i].numThreads = numThreads; + threadArgs[i].threadId = i; + threadArgs[i].taos = taos; + } + + int64_t begin = taosGetTimestampUs(); + for (int i = 0; i < numThreads; ++i) { + pthread_create(tids+i, NULL, threadFunc, threadArgs+i); + } + for (int i = 0; i < numThreads; ++i) { + pthread_join(tids[i], NULL); + } + int64_t end = taosGetTimestampUs(); + printf("TIME: %d(ms)\n", (int)((end-begin)/1000)); + printf("THROUGHPUT: %d\n", (int)((numSTables * 1e6) / (end-begin))); + free(threadArgs); + free(tids); + taos_close(taos); + taos_cleanup(); +} diff --git a/examples/c/stream.c b/examples/c/stream.c new file mode 100644 index 0000000000000000000000000000000000000000..f759da4283bfca69d921f4bbfbb2e78e2123a70c --- /dev/null +++ b/examples/c/stream.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include +#include +#include +#include +#include // include TDengine header file +#include + +typedef struct { + char server_ip[64]; + char db_name[64]; + char tbl_name[64]; +} param; + +int g_thread_exit_flag = 0; +void *insert_rows(void *sarg); + +void streamCallBack(void *param, TAOS_RES *res, TAOS_ROW row) { + // in this simple demo, it just print out the result + char temp[128]; + + TAOS_FIELD *fields = taos_fetch_fields(res); + int numFields = taos_num_fields(res); + + taos_print_row(temp, row, fields, numFields); + + printf("\n%s\n", temp); +} + +int main(int argc, char *argv[]) { + TAOS *taos; + char db_name[64]; + char tbl_name[64]; + char sql[1024] = {0}; + + if (argc != 4) { + printf("usage: %s server-ip dbname tblname\n", argv[0]); + exit(0); + } + + strcpy(db_name, argv[2]); + strcpy(tbl_name, argv[3]); + + // create pthread to insert into row per second for stream calc + param *t_param = (param *)malloc(sizeof(param)); + if (NULL == t_param) { + printf("failed to malloc\n"); + exit(1); + } + memset(t_param, 0, sizeof(param)); + strcpy(t_param->server_ip, argv[1]); + strcpy(t_param->db_name, db_name); + strcpy(t_param->tbl_name, tbl_name); + + pthread_t pid; + pthread_create(&pid, NULL, (void *(*)(void *))insert_rows, t_param); + + sleep(3); // waiting for database is created. + // open connection to database + taos = taos_connect(argv[1], "root", "taosdata", db_name, 0); + if (taos == NULL) { + printf("failed to connet to server:%s\n", argv[1]); + free(t_param); + exit(1); + } + + // starting stream calc, + printf("please input stream SQL:[e.g., select count(*) from tblname interval(5s) sliding(2s);]\n"); + fgets(sql, sizeof(sql), stdin); + if (sql[0] == 0) { + printf("input NULL stream SQL, so exit!\n"); + free(t_param); + exit(1); + } + + // param is set to NULL in this demo, it shall be set to the pointer to app context + TAOS_STREAM *pStream = taos_open_stream(taos, sql, streamCallBack, 0, NULL, NULL); + if (NULL == pStream) { + printf("failed to create stream\n"); + free(t_param); + exit(1); + } + + printf("press any key to exit\n"); + getchar(); + + taos_close_stream(pStream); + + g_thread_exit_flag = 1; + pthread_join(pid, NULL); + + taos_close(taos); + free(t_param); + + return 0; +} + +void *insert_rows(void *sarg) { + TAOS * taos; + char command[1024] = {0}; + param *winfo = (param *)sarg; + + if (NULL == winfo) { + printf("para is null!\n"); + exit(1); + } + + taos = taos_connect(winfo->server_ip, "root", "taosdata", NULL, 0); + if (taos == NULL) { + printf("failed to connet to server:%s\n", winfo->server_ip); + exit(1); + } + + // drop database + sprintf(command, "drop database %s;", winfo->db_name); + if (taos_query(taos, command) != 0) { + printf("failed to drop database, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + // create database + sprintf(command, "create database %s;", winfo->db_name); + if (taos_query(taos, command) != 0) { + printf("failed to create database, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + // use database + sprintf(command, "use %s;", winfo->db_name); + if (taos_query(taos, command) != 0) { + printf("failed to use database, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + // create table + sprintf(command, "create table %s (ts timestamp, speed int);", winfo->tbl_name); + if (taos_query(taos, command) != 0) { + printf("failed to create table, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + // insert data + int64_t begin = (int64_t)time(NULL); + int index = 0; + while (1) { + if (g_thread_exit_flag) break; + + index++; + sprintf(command, "insert into %s values (%ld, %d)", winfo->tbl_name, (begin + index) * 1000, index); + if (taos_query(taos, command)) { + printf("failed to insert row [%s], reason:%s\n", command, taos_errstr(taos)); + } + sleep(1); + } + + taos_close(taos); + return 0; +} diff --git a/examples/c/subscribe.c b/examples/c/subscribe.c new file mode 100644 index 0000000000000000000000000000000000000000..d8b76c008f24a4ff1e7827e5b1cb167f013c81c5 --- /dev/null +++ b/examples/c/subscribe.c @@ -0,0 +1,257 @@ +// sample code for TDengine subscribe/consume API +// to compile: gcc -o subscribe subscribe.c -ltaos + +#include +#include +#include +#include // include TDengine header file +#include + +int nTotalRows; + +void print_result(TAOS_RES* res, int blockFetch) { + TAOS_ROW row = NULL; + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + int nRows = 0; + + if (blockFetch) { + nRows = taos_fetch_block(res, &row); + // for (int i = 0; i < nRows; i++) { + // taos_print_row(buf, row + i, fields, num_fields); + // puts(buf); + //} + } else { + while ((row = taos_fetch_row(res))) { + char buf[4096] = {0}; + taos_print_row(buf, row, fields, num_fields); + puts(buf); + nRows++; + } + } + + nTotalRows += nRows; + printf("%d rows consumed.\n", nRows); +} + +void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) { print_result(res, *(int*)param); } + +void check_row_count(int line, TAOS_RES* res, int expected) { + int actual = 0; + TAOS_ROW row; + while ((row = taos_fetch_row(res))) { + actual++; + } + if (actual != expected) { + printf("line %d: row count mismatch, expected: %d, actual: %d\n", line, expected, actual); + } else { + printf("line %d: %d rows consumed as expected\n", line, actual); + } +} + +void do_query(TAOS* taos, const char* sql) { + TAOS_RES* res = taos_query(taos, sql); + taos_free_result(res); +} + +void run_test(TAOS* taos) { + do_query(taos, "drop database if exists test;"); + + usleep(100000); + do_query(taos, "create database test;"); + usleep(100000); + do_query(taos, "use test;"); + + usleep(100000); + do_query(taos, "create table meters(ts timestamp, a int) tags(area int);"); + + do_query(taos, "create table t0 using meters tags(0);"); + do_query(taos, "create table t1 using meters tags(1);"); + do_query(taos, "create table t2 using meters tags(2);"); + do_query(taos, "create table t3 using meters tags(3);"); + do_query(taos, "create table t4 using meters tags(4);"); + do_query(taos, "create table t5 using meters tags(5);"); + do_query(taos, "create table t6 using meters tags(6);"); + do_query(taos, "create table t7 using meters tags(7);"); + do_query(taos, "create table t8 using meters tags(8);"); + do_query(taos, "create table t9 using meters tags(9);"); + + do_query(taos, "insert into t0 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:02:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:02:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:01.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t3 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t4 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t5 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t6 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t7 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t8 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t9 values('2020-01-01 00:01:02.000', 0);"); + + // super tables subscription + usleep(1000000); + + TAOS_SUB* tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + TAOS_RES* res = taos_consume(tsub); + check_row_count(__LINE__, res, 18); + + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + do_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);"); + do_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);"); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 2); + + do_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);"); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 2); + + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);"); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 1); + + // keep progress information and restart subscription + taos_unsubscribe(tsub, 1); + do_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);"); + tsub = taos_subscribe(taos, 1, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 24); + + // keep progress information and continue previous subscription + taos_unsubscribe(tsub, 1); + tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + // don't keep progress information and continue previous subscription + taos_unsubscribe(tsub, 0); + tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 24); + + // single meter subscription + + taos_unsubscribe(tsub, 0); + tsub = taos_subscribe(taos, 0, "test", "select * from t0;", NULL, NULL, 0); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 5); + + res = taos_consume(tsub); + check_row_count(__LINE__, res, 0); + + do_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);"); + res = taos_consume(tsub); + check_row_count(__LINE__, res, 1); + + taos_unsubscribe(tsub, 0); +} + +int main(int argc, char* argv[]) { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + const char* sql = "select * from meters;"; + const char* topic = "test-multiple"; + int async = 1, restart = 0, keep = 1, test = 0, blockFetch = 0; + + for (int i = 1; i < argc; i++) { + if (strncmp(argv[i], "-h=", 3) == 0) { + host = argv[i] + 3; + continue; + } + if (strncmp(argv[i], "-u=", 3) == 0) { + user = argv[i] + 3; + continue; + } + if (strncmp(argv[i], "-p=", 3) == 0) { + passwd = argv[i] + 3; + continue; + } + if (strcmp(argv[i], "-sync") == 0) { + async = 0; + continue; + } + if (strcmp(argv[i], "-restart") == 0) { + restart = 1; + continue; + } + if (strcmp(argv[i], "-single") == 0) { + sql = "select * from t0;"; + topic = "test-single"; + continue; + } + if (strcmp(argv[i], "-nokeep") == 0) { + keep = 0; + continue; + } + if (strncmp(argv[i], "-sql=", 5) == 0) { + sql = argv[i] + 5; + topic = "test-custom"; + continue; + } + if (strcmp(argv[i], "-test") == 0) { + test = 1; + continue; + } + if (strcmp(argv[i], "-block-fetch") == 0) { + blockFetch = 1; + continue; + } + } + + TAOS* taos = taos_connect(host, user, passwd, "", 0); + if (taos == NULL) { + printf("failed to connect to db, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + if (test) { + run_test(taos); + taos_close(taos); + exit(0); + } + + taos_select_db(taos, "test"); + TAOS_SUB* tsub = NULL; + if (async) { + // create an asynchronized subscription, the callback function will be called every 1s + tsub = taos_subscribe(taos, restart, topic, sql, subscribe_callback, &blockFetch, 1000); + } else { + // create an synchronized subscription, need to call 'taos_consume' manually + tsub = taos_subscribe(taos, restart, topic, sql, NULL, NULL, 0); + } + + if (tsub == NULL) { + printf("failed to create subscription.\n"); + exit(0); + } + + if (async) { + getchar(); + } else + while (1) { + TAOS_RES* res = taos_consume(tsub); + if (res == NULL) { + printf("failed to consume data."); + break; + } else { + print_result(res, blockFetch); + getchar(); + } + } + + printf("total rows consumed: %d\n", nTotalRows); + taos_unsubscribe(tsub, keep); + taos_close(taos); + + return 0; +} diff --git a/examples/go/taosdemo.go b/examples/go/taosdemo.go new file mode 100644 index 0000000000000000000000000000000000000000..543cfcc0f65aad154cc411891a76ae2fdb4e0e02 --- /dev/null +++ b/examples/go/taosdemo.go @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ +package main + +import ( + "database/sql" + "flag" + "fmt" + "log" + "math/rand" + "os" + "runtime" + "strconv" + "sync" + "time" + + _ "github.com/taosdata/driver-go/taosSql" +) + +const ( + maxLocationSize = 32 + //maxSqlBufSize = 65480 +) + +var locations = [maxLocationSize]string{ + "Beijing", "Shanghai", "Guangzhou", "Shenzhen", + "HangZhou", "Tianjin", "Wuhan", "Changsha", + "Nanjing", "Xian"} + +type config struct { + hostName string + serverPort int + user string + password string + dbName string + supTblName string + tablePrefix string + mode string + numOftables int + numOfRecordsPerTable int + numOfRecordsPerReq int + numOfThreads int + startTimestamp string + startTs int64 + + keep int + days int +} + +var configPara config +var taosDriverName = "taosSql" +var url string + +func init() { + flag.StringVar(&configPara.hostName, "h", "127.0.0.1", "The host to connect to TDengine server.") + flag.IntVar(&configPara.serverPort, "p", 6030, "The TCP/IP port number to use for the connection to TDengine server.") + flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.") + flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.") + flag.StringVar(&configPara.dbName, "d", "test", "Destination database.") + flag.StringVar(&configPara.tablePrefix, "m", "d", "Table prefix name.") + flag.StringVar(&configPara.mode, "M", "r", "mode,r:raw,s:stmt") + flag.IntVar(&configPara.numOftables, "t", 2, "The number of tables.") + flag.IntVar(&configPara.numOfRecordsPerTable, "n", 10, "The number of records per table.") + flag.IntVar(&configPara.numOfRecordsPerReq, "r", 3, "The number of records per request.") + flag.IntVar(&configPara.numOfThreads, "T", 1, "The number of threads.") + flag.StringVar(&configPara.startTimestamp, "s", "2020-10-01 08:00:00", "The start timestamp for one table.") + flag.Parse() + + configPara.keep = 365 * 20 + configPara.days = 30 + configPara.supTblName = "meters" + + startTs, err := time.ParseInLocation("2006-01-02 15:04:05", configPara.startTimestamp, time.Local) + if err == nil { + configPara.startTs = startTs.UnixNano() / 1e6 + } +} + +func printAllArgs() { + fmt.Printf("\n============= args parse result: =============\n") + fmt.Printf("hostName: %v\n", configPara.hostName) + fmt.Printf("serverPort: %v\n", configPara.serverPort) + fmt.Printf("usr: %v\n", configPara.user) + fmt.Printf("password: %v\n", configPara.password) + fmt.Printf("dbName: %v\n", configPara.dbName) + fmt.Printf("mode: %v\n", configPara.mode) + fmt.Printf("tablePrefix: %v\n", configPara.tablePrefix) + fmt.Printf("numOftables: %v\n", configPara.numOftables) + fmt.Printf("numOfRecordsPerTable: %v\n", configPara.numOfRecordsPerTable) + fmt.Printf("numOfRecordsPerReq: %v\n", configPara.numOfRecordsPerReq) + fmt.Printf("numOfThreads: %v\n", configPara.numOfThreads) + fmt.Printf("startTimestamp: %v[%v]\n", configPara.startTimestamp, configPara.startTs) + fmt.Printf("================================================\n") +} + +func main() { + printAllArgs() + fmt.Printf("Please press enter key to continue....\n") + _, _ = fmt.Scanln() + + url = "root:taosdata@/tcp(" + configPara.hostName + ":" + strconv.Itoa(configPara.serverPort) + ")/" + //url = fmt.Sprintf("%s:%s@/tcp(%s:%d)/%s?interpolateParams=true", configPara.user, configPara.password, configPara.hostName, configPara.serverPort, configPara.dbName) + // open connect to taos server + //db, err := sql.Open(taosDriverName, url) + //if err != nil { + // fmt.Println("Open database error: %s\n", err) + // os.Exit(1) + //} + //defer db.Close() + rand.Seed(time.Now().Unix()) + + if configPara.mode == "s" { + fmt.Printf("\n======== start stmt mode test ========\n") + db, err := sql.Open("taosSql", url) + if err != nil { + log.Fatalf("Open database error: %s\n", err) + } + defer db.Close() + demodbStmt := configPara.dbName + demotStmt := "demotStmt" + drop_database_stmt(db, demodbStmt) + create_database_stmt(db, demodbStmt) + use_database_stmt(db, demodbStmt) + create_table_stmt(db, demotStmt) + insert_data_stmt(db, demotStmt) + select_data_stmt(db, demotStmt) + return + } + + createDatabase(configPara.dbName, configPara.supTblName) + fmt.Printf("======== create database success! ========\n\n") + + //create_table(db, stblName) + multiThreadCreateTable(configPara.numOfThreads, configPara.numOftables, configPara.dbName, configPara.tablePrefix) + fmt.Printf("======== create super table and child tables success! ========\n\n") + + //insert_data(db, demot) + multiThreadInsertData(configPara.numOfThreads, configPara.numOftables, configPara.dbName, configPara.tablePrefix) + fmt.Printf("======== insert data into child tables success! ========\n\n") + + //select_data(db, demot) + selectTest(configPara.dbName, configPara.tablePrefix, configPara.supTblName) + fmt.Printf("======== select data success! ========\n\n") + + fmt.Printf("======== end demo ========\n") +} + +func createDatabase(dbName string, supTblName string) { + db, err := sql.Open(taosDriverName, url) + if err != nil { + fmt.Printf("Open database error: %s\n", err) + os.Exit(1) + } + defer db.Close() + + // drop database if exists + sqlStr := "drop database if exists " + dbName + _, err = db.Exec(sqlStr) + checkErr(err, sqlStr) + + time.Sleep(time.Second) + + // create database + sqlStr = "create database " + dbName + " keep " + strconv.Itoa(configPara.keep) + " days " + strconv.Itoa(configPara.days) + _, err = db.Exec(sqlStr) + checkErr(err, sqlStr) + + // use database + //sqlStr = "use " + dbName + //_, err = db.Exec(sqlStr) + //checkErr(err, sqlStr) + + sqlStr = "create table if not exists " + dbName + "." + supTblName + " (ts timestamp, current float, voltage int, phase float) tags(location binary(64), groupId int);" + _, err = db.Exec(sqlStr) + checkErr(err, sqlStr) +} + +func multiThreadCreateTable(threads int, nTables int, dbName string, tablePrefix string) { + st := time.Now().UnixNano() + + if threads < 1 { + threads = 1 + } + + a := nTables / threads + if a < 1 { + threads = nTables + a = 1 + } + + b := nTables % threads + + last := 0 + endTblId := 0 + wg := sync.WaitGroup{} + for i := 0; i < threads; i++ { + startTblId := last + if i < b { + endTblId = last + a + } else { + endTblId = last + a - 1 + } + last = endTblId + 1 + wg.Add(1) + go createTable(dbName, tablePrefix, startTblId, endTblId, &wg) + } + wg.Wait() + + et := time.Now().UnixNano() + fmt.Printf("create tables spent duration: %6.6fs\n", (float32(et-st))/1e9) +} + +func createTable(dbName string, childTblPrefix string, startTblId int, endTblId int, wg *sync.WaitGroup) { + //fmt.Printf("subThread[%d]: create table from %d to %d \n", unix.Gettid(), startTblId, endTblId) + // windows.GetCurrentThreadId() + + db, err := sql.Open(taosDriverName, url) + if err != nil { + fmt.Printf("Open database error: %s\n", err) + os.Exit(1) + } + defer db.Close() + + for i := startTblId; i <= endTblId; i++ { + sqlStr := "create table if not exists " + dbName + "." + childTblPrefix + strconv.Itoa(i) + " using " + dbName + ".meters tags('" + locations[i%maxLocationSize] + "', " + strconv.Itoa(i) + ");" + //fmt.Printf("sqlStr: %v\n", sqlStr) + _, err = db.Exec(sqlStr) + checkErr(err, sqlStr) + } + wg.Done() + runtime.Goexit() +} + +func generateRowData(ts int64) string { + voltage := rand.Int() % 1000 + current := 200 + rand.Float32() + phase := rand.Float32() + values := "( " + strconv.FormatInt(ts, 10) + ", " + strconv.FormatFloat(float64(current), 'f', 6, 64) + ", " + strconv.Itoa(voltage) + ", " + strconv.FormatFloat(float64(phase), 'f', 6, 64) + " ) " + return values +} + +func insertData(dbName string, childTblPrefix string, startTblId int, endTblId int, wg *sync.WaitGroup) { + //fmt.Printf("subThread[%d]: insert data to table from %d to %d \n", unix.Gettid(), startTblId, endTblId) + // windows.GetCurrentThreadId() + + db, err := sql.Open(taosDriverName, url) + if err != nil { + fmt.Printf("Open database error: %s\n", err) + os.Exit(1) + } + defer db.Close() + + tmpTs := configPara.startTs + //rand.New(rand.NewSource(time.Now().UnixNano())) + for tID := startTblId; tID <= endTblId; tID++ { + totalNum := 0 + for { + sqlStr := "insert into " + dbName + "." + childTblPrefix + strconv.Itoa(tID) + " values " + currRowNum := 0 + for { + tmpTs += 1000 + valuesOfRow := generateRowData(tmpTs) + currRowNum += 1 + totalNum += 1 + + sqlStr = fmt.Sprintf("%s %s", sqlStr, valuesOfRow) + + if currRowNum >= configPara.numOfRecordsPerReq || totalNum >= configPara.numOfRecordsPerTable { + break + } + } + + res, err := db.Exec(sqlStr) + checkErr(err, sqlStr) + + count, err := res.RowsAffected() + checkErr(err, "rows affected") + + if count != int64(currRowNum) { + fmt.Printf("insert data, expect affected:%d, actual:%d\n", currRowNum, count) + os.Exit(1) + } + + if totalNum >= configPara.numOfRecordsPerTable { + break + } + } + } + + wg.Done() + runtime.Goexit() +} + +func multiThreadInsertData(threads int, nTables int, dbName string, tablePrefix string) { + st := time.Now().UnixNano() + + if threads < 1 { + threads = 1 + } + + a := nTables / threads + if a < 1 { + threads = nTables + a = 1 + } + + b := nTables % threads + + last := 0 + endTblId := 0 + wg := sync.WaitGroup{} + for i := 0; i < threads; i++ { + startTblId := last + if i < b { + endTblId = last + a + } else { + endTblId = last + a - 1 + } + last = endTblId + 1 + wg.Add(1) + go insertData(dbName, tablePrefix, startTblId, endTblId, &wg) + } + wg.Wait() + + et := time.Now().UnixNano() + fmt.Printf("insert data spent duration: %6.6fs\n", (float32(et-st))/1e9) +} + +func selectTest(dbName string, tbPrefix string, supTblName string) { + db, err := sql.Open(taosDriverName, url) + if err != nil { + fmt.Printf("Open database error: %s\n", err) + os.Exit(1) + } + defer db.Close() + + // select sql 1 + limit := 3 + offset := 0 + sqlStr := "select * from " + dbName + "." + supTblName + " limit " + strconv.Itoa(limit) + " offset " + strconv.Itoa(offset) + rows, err := db.Query(sqlStr) + checkErr(err, sqlStr) + + defer rows.Close() + fmt.Printf("query sql: %s\n", sqlStr) + for rows.Next() { + var ( + ts string + current float32 + voltage int + phase float32 + location string + groupid int + ) + err := rows.Scan(&ts, ¤t, &voltage, &phase, &location, &groupid) + if err != nil { + checkErr(err, "rows scan fail") + } + + fmt.Printf("ts:%s\t current:%f\t voltage:%d\t phase:%f\t location:%s\t groupid:%d\n", ts, current, voltage, phase, location, groupid) + } + // check iteration error + if rows.Err() != nil { + checkErr(err, "rows next iteration error") + } + + // select sql 2 + sqlStr = "select avg(voltage), min(voltage), max(voltage) from " + dbName + "." + tbPrefix + strconv.Itoa(rand.Int()%configPara.numOftables) + rows, err = db.Query(sqlStr) + checkErr(err, sqlStr) + + defer rows.Close() + fmt.Printf("\nquery sql: %s\n", sqlStr) + for rows.Next() { + var ( + voltageAvg float32 + voltageMin int + voltageMax int + ) + err := rows.Scan(&voltageAvg, &voltageMin, &voltageMax) + if err != nil { + checkErr(err, "rows scan fail") + } + + fmt.Printf("avg(voltage):%f\t min(voltage):%d\t max(voltage):%d\n", voltageAvg, voltageMin, voltageMax) + } + // check iteration error + if rows.Err() != nil { + checkErr(err, "rows next iteration error") + } + + // select sql 3 + sqlStr = "select last(*) from " + dbName + "." + supTblName + rows, err = db.Query(sqlStr) + checkErr(err, sqlStr) + + defer rows.Close() + fmt.Printf("\nquery sql: %s\n", sqlStr) + for rows.Next() { + var ( + lastTs string + lastCurrent float32 + lastVoltage int + lastPhase float32 + ) + err := rows.Scan(&lastTs, &lastCurrent, &lastVoltage, &lastPhase) + if err != nil { + checkErr(err, "rows scan fail") + } + + fmt.Printf("last(ts):%s\t last(current):%f\t last(voltage):%d\t last(phase):%f\n", lastTs, lastCurrent, lastVoltage, lastPhase) + } + // check iteration error + if rows.Err() != nil { + checkErr(err, "rows next iteration error") + } +} +func drop_database_stmt(db *sql.DB, demodb string) { + st := time.Now().Nanosecond() + // drop test db + res, err := db.Exec("drop database if exists " + demodb) + checkErr(err, "drop database "+demodb) + + affectd, err := res.RowsAffected() + checkErr(err, "drop db, res.RowsAffected") + + et := time.Now().Nanosecond() + fmt.Printf("drop database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} + +func create_database_stmt(db *sql.DB, demodb string) { + st := time.Now().Nanosecond() + // create database + //var stmt interface{} + stmt, err := db.Prepare("create database ?") + checkErr(err, "create db, db.Prepare") + + //var res driver.Result + res, err := stmt.Exec(demodb) + checkErr(err, "create db, stmt.Exec") + + //fmt.Printf("Query OK, %d row(s) affected()", res.RowsAffected()) + affectd, err := res.RowsAffected() + checkErr(err, "create db, res.RowsAffected") + + et := time.Now().Nanosecond() + fmt.Printf("create database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} + +func use_database_stmt(db *sql.DB, demodb string) { + st := time.Now().Nanosecond() + // create database + //var stmt interface{} + stmt, err := db.Prepare("use " + demodb) + checkErr(err, "use db, db.Prepare") + + res, err := stmt.Exec() + checkErr(err, "use db, stmt.Exec") + + affectd, err := res.RowsAffected() + checkErr(err, "use db, res.RowsAffected") + + et := time.Now().Nanosecond() + fmt.Printf("use database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} + +func create_table_stmt(db *sql.DB, demot string) { + st := time.Now().Nanosecond() + // create table + // (ts timestamp, id int, name binary(8), len tinyint, flag bool, notes binary(8), fv float, dv double) + stmt, err := db.Prepare("create table ? (? timestamp, ? int, ? binary(10), ? tinyint, ? bool, ? binary(8), ? float, ? double)") + checkErr(err, "create table db.Prepare") + + res, err := stmt.Exec(demot, "ts", "id", "name", "len", "flag", "notes", "fv", "dv") + checkErr(err, "create table stmt.Exec") + + affectd, err := res.RowsAffected() + checkErr(err, "create table res.RowsAffected") + + et := time.Now().Nanosecond() + fmt.Printf("create table result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} + +func insert_data_stmt(db *sql.DB, demot string) { + st := time.Now().Nanosecond() + // insert data into table + stmt, err := db.Prepare("insert into ? values(?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?)") + checkErr(err, "insert db.Prepare") + + res, err := stmt.Exec(demot, "now", 1000, "'haidian'", 6, true, "'AI world'", 6987.654, 321.987, + "now+1s", 1001, "'changyang'", 7, false, "'DeepMode'", 12356.456, 128634.456, + "now+2s", 1002, "'chuangping'", 8, true, "'database'", 3879.456, 65433478.456) + checkErr(err, "insert data, stmt.Exec") + + affectd, err := res.RowsAffected() + checkErr(err, "res.RowsAffected") + + et := time.Now().Nanosecond() + fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} + +func select_data_stmt(db *sql.DB, demot string) { + st := time.Now().Nanosecond() + + stmt, err := db.Prepare("select ?, ?, ?, ?, ?, ?, ?, ? from ?") // go binary mode + checkErr(err, "db.Prepare") + + rows, err := stmt.Query("ts", "id", "name", "len", "flag", "notes", "fv", "dv", demot) + checkErr(err, "stmt.Query") + + fmt.Printf("%10s%s%8s %5s %8s%s %s %10s%s %7s%s %8s%s %11s%s %14s%s\n", " ", "ts", " ", "id", " ", "name", " ", "len", " ", "flag", " ", "notes", " ", "fv", " ", " ", "dv") + var affectd int + for rows.Next() { + var ts string + var name string + var id int + var len int8 + var flag bool + var notes string + var fv float32 + var dv float64 + + err = rows.Scan(&ts, &id, &name, &len, &flag, ¬es, &fv, &dv) + //fmt.Println("start scan fields from row.rs, &fv:", &fv) + //err = rows.Scan(&fv) + checkErr(err, "rows.Scan") + + fmt.Printf("%s\t", ts) + fmt.Printf("%d\t", id) + fmt.Printf("%10s\t", name) + fmt.Printf("%d\t", len) + fmt.Printf("%t\t", flag) + fmt.Printf("%s\t", notes) + fmt.Printf("%06.3f\t", fv) + fmt.Printf("%09.6f\n", dv) + + affectd++ + + } + + et := time.Now().Nanosecond() + fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9) +} +func checkErr(err error, prompt string) { + if err != nil { + fmt.Printf("%s\n", prompt) + panic(err) + } +} diff --git a/examples/lua/OpenResty/conf/nginx.conf b/examples/lua/OpenResty/conf/nginx.conf new file mode 100644 index 0000000000000000000000000000000000000000..960cac606a49e5964a900f815eb76e7f228078eb --- /dev/null +++ b/examples/lua/OpenResty/conf/nginx.conf @@ -0,0 +1,21 @@ +worker_processes 1; +user root; +error_log logs/error.log; +events { + worker_connections 1024; +} + +http { + lua_package_path '$prefix/lua/?.lua;$prefix/rest/?.lua;$prefix/rest/?/init.lua;;'; + lua_package_cpath "$prefix/so/?.so;;"; + lua_code_cache on; + server { + listen 7000; + server_name restapi; + charset utf-8; + lua_need_request_body on; + location ~ ^/api/([-_a-zA-Z0-9/]+) { + content_by_lua_file rest/$1.lua; + } + } +} diff --git a/examples/lua/OpenResty/logs/.gitignore b/examples/lua/OpenResty/logs/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ad8530e1c3e3c88fcce3b50abf7cc006333f5522 --- /dev/null +++ b/examples/lua/OpenResty/logs/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/examples/lua/OpenResty/rest/config.lua b/examples/lua/OpenResty/rest/config.lua new file mode 100644 index 0000000000000000000000000000000000000000..72a4fd8ec687430e5f3d0a798dc4fb3b2d95a942 --- /dev/null +++ b/examples/lua/OpenResty/rest/config.lua @@ -0,0 +1,10 @@ +local config = { + host = "127.0.0.1", + port = 6030, + database = "", + user = "root", + password = "taosdata", + max_packet_size = 1024 * 1024 , + connection_pool_size = 64 +} +return config diff --git a/examples/lua/OpenResty/rest/tdpool/init.lua b/examples/lua/OpenResty/rest/tdpool/init.lua new file mode 100644 index 0000000000000000000000000000000000000000..ebf8e91756539cc8af5db38232a40bf42aeaa245 --- /dev/null +++ b/examples/lua/OpenResty/rest/tdpool/init.lua @@ -0,0 +1,72 @@ +local _M = {} +local driver = require "luaconnector51" +local water_mark = 0 +local occupied = 0 +local connection_pool = {} + +function _M.new(o,config) + o = o or {} + o.connection_pool = connection_pool + o.water_mark = water_mark + o.occupied = occupied + if #connection_pool == 0 then + + for i = 1, config.connection_pool_size do + local res = driver.connect(config) + if res.code ~= 0 then + ngx.log(ngx.ERR, "connect--- failed:"..res.error) + return nil + else + local object = {obj = res.conn, state = 0} + table.insert(o.connection_pool,i, object) + ngx.log(ngx.INFO, "add connection, now pool size:"..#(o.connection_pool)) + end + end + + end + + return setmetatable(o, { __index = _M }) +end + +function _M:get_connection() + + local connection_obj + + for i = 1, #connection_pool do + connection_obj = connection_pool[i] + if connection_obj.state == 0 then + connection_obj.state = 1 + occupied = occupied +1 + if occupied > water_mark then + water_mark = occupied + end + return connection_obj["obj"] + end + end + + ngx.log(ngx.ERR,"ALERT! NO FREE CONNECTION.") + + return nil +end + +function _M:get_water_mark() + + return water_mark +end + +function _M:release_connection(conn) + + local connection_obj + + for i = 1, #connection_pool do + connection_obj = connection_pool[i] + + if connection_obj["obj"] == conn then + connection_obj["state"] = 0 + occupied = occupied -1 + return + end + end +end + +return _M diff --git a/examples/lua/OpenResty/rest/test.lua b/examples/lua/OpenResty/rest/test.lua new file mode 100644 index 0000000000000000000000000000000000000000..2dc0cf10f22b90c8bcb925700b1d7ebd00ff153a --- /dev/null +++ b/examples/lua/OpenResty/rest/test.lua @@ -0,0 +1,92 @@ +local driver = require "luaconnector51" +local cjson = require "cjson" +local Pool = require "tdpool" +local config = require "config" +ngx.say("start time:"..os.time()) + +local pool = Pool.new(Pool,config) +local conn = pool:get_connection() + +local res = driver.query(conn,"drop database if exists nginx") +if res.code ~=0 then + ngx.say("drop db--- failed: "..res.error) +else + ngx.say("drop db--- pass.") +end +res = driver.query(conn,"create database nginx") +if res.code ~=0 then + ngx.say("create db--- failed: "..res.error) + +else + ngx.say("create db--- pass.") +end + +res = driver.query(conn,"use nginx") +if res.code ~=0 then + ngx.say("select db--- failed: "..res.error) +else + ngx.say("select db--- pass.") +end + +res = driver.query(conn,"create table m1 (ts timestamp, speed int,owner binary(20))") +if res.code ~=0 then + ngx.say("create table---failed: "..res.error) + +else + ngx.say("create table--- pass.") +end + +res = driver.query(conn,"insert into m1 values ('2019-09-01 00:00:00.001', 0, 'robotspace'), ('2019-09-01 00:00:00.002',1,'Hilink'),('2019-09-01 00:00:00.003',2,'Harmony')") +if res.code ~=0 then + ngx.say("insert records failed: "..res.error) + return +else + if(res.affected == 3) then + ngx.say("insert records--- pass") + else + ngx.say("insert records---failed: expect 3 affected records, actually affected "..res.affected) + end +end + +res = driver.query(conn,"select * from m1") + +if res.code ~=0 then + ngx.say("select failed: "..res.error) + return +else + ngx.say(cjson.encode(res)) + if (#(res.item) == 3) then + ngx.say("select--- pass") + else + ngx.say("select--- failed: expect 3 affected records, actually received "..#(res.item)) + end + +end + +--[[ +local flag = false +function query_callback(res) + if res.code ~=0 then + ngx.say("async_query_callback--- failed:"..res.error) + else + if(res.affected == 3) then + ngx.say("async_query_callback, insert records--- pass") + else + ngx.say("async_query_callback, insert records---failed: expect 3 affected records, actually affected "..res.affected) + end + end + flag = true +end + +driver.query_a(conn,"insert into m1 values ('2019-09-01 00:00:00.001', 3, 'robotspace'),('2019-09-01 00:00:00.006', 4, 'Hilink'),('2019-09-01 00:00:00.007', 6, 'Harmony')", query_callback) + +while not flag do + ngx.say("i am here once...") + ngx.sleep(0.001) -- time unit is second +end +--]] + +ngx.say("pool water_mark:"..pool:get_water_mark()) + +pool:release_connection(conn) +ngx.say("end time:"..os.time()) diff --git a/examples/lua/OpenResty/so/luaconnector51.so b/examples/lua/OpenResty/so/luaconnector51.so new file mode 100755 index 0000000000000000000000000000000000000000..442de6e39f909e1aeb869988722b84795c048855 Binary files /dev/null and b/examples/lua/OpenResty/so/luaconnector51.so differ diff --git a/examples/lua/README.md b/examples/lua/README.md new file mode 100644 index 0000000000000000000000000000000000000000..bdc88edbd7b5d6798a8df6530ea82d24eb22915b --- /dev/null +++ b/examples/lua/README.md @@ -0,0 +1,50 @@ +# TDengine driver connector for Lua + +It's a Lua implementation for [TDengine](https://github.com/taosdata/TDengine), an open-sourced big data platform designed and optimized for the Internet of Things (IoT), Connected Cars, Industrial IoT, and IT Infrastructure and Application Monitoring. You may need to install Lua5.3 . +As TDengine is built with lua-enable, the built-in lua module conflicts with external lua. The following commands require TDengine built with lua-disable. +To disable built-in lua: +mkdir debug && cd debug +cmake .. -DBUILD_LUA=false && cmake --build . +## Lua Dependencies +- Lua: +``` +https://www.lua.org/ +``` + +## Run with Lua Sample + +Build driver lib: +``` +./build.sh +``` +Run lua sample: +``` +lua test.lua +``` + +## Run performance test: +``` +time lua benchmark.lua +``` +## OpenResty Dependencies +- OpenResty: +``` +http://openresty.org +``` +## Run with OpenResty Sample +**This section demonstrates how to get binary file for connector. To be convenient for trial, an connector has been put into OpenResty work directory. +Because of difference on C API between Lua5.3 and Lua5.1, the files needed by connector for OpenResty are stored in local source directory and configured in script build.sh.** + +Build driver lib: +``` +cd lua51 +./build.sh +``` +Run OpenResty sample: +``` +cd .. +cd OpenResty +sudo openresty -p . +curl http://127.0.0.1:7000/api/test +``` + diff --git a/examples/lua/benchmark.lua b/examples/lua/benchmark.lua new file mode 100644 index 0000000000000000000000000000000000000000..900e7891d81d5de2d723a9ebd9accf3317b2413a --- /dev/null +++ b/examples/lua/benchmark.lua @@ -0,0 +1,67 @@ +local driver = require "luaconnector" + +local config = { + password = "taosdata", + host = "127.0.0.1", + port = 6030, + database = "", + user = "root", + + max_packet_size = 1024 * 1024 +} + +local conn +local res = driver.connect(config) +if res.code ~=0 then + print("connect--- failed: "..res.error) + return +else + conn = res.conn + print("connect--- pass.") +end + +local res = driver.query(conn,"drop database if exists demo") + +res = driver.query(conn,"create database demo") +if res.code ~=0 then + print("create db--- failed: "..res.error) + return +else + print("create db--- pass.") +end + +res = driver.query(conn,"use demo") +if res.code ~=0 then + print("select db--- failed: "..res.error) + return +else + print("select db--- pass.") +end + +res = driver.query(conn,"create table m1 (ts timestamp, speed int,owner binary(20))") +if res.code ~=0 then + print("create table---failed: "..res.error) + return +else + print("create table--- pass.") +end + +local base = 1617330000000 +local index =0 +local count = 100000 +local t +while( index < count ) +do + t = base + index + local q=string.format([[insert into m1 values (%d,0,'robotspace')]],t) +res = driver.query(conn,q) +if res.code ~=0 then + print("insert records failed: "..res.error) + return +else + +end + index = index+1 +end +print(string.format([["Done. %d records has been stored."]],count)) +driver.close(conn) diff --git a/examples/lua/build.sh b/examples/lua/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..9d00c6842515415034ce0b5dc71d5d6af9ffc881 --- /dev/null +++ b/examples/lua/build.sh @@ -0,0 +1,8 @@ +lua_header_installed=`apt-cache policy liblua5.3-dev|grep Installed|grep none > /dev/null; echo $?` +if [ "$lua_header_installed" = "0" ]; then + echo "If need, please input root password to install liblua5.3-dev for build the connector.." + sudo apt install -y liblua5.3-dev +fi + +gcc -std=c99 lua_connector.c -fPIC -shared -o luaconnector.so -Wall -ltaos -I/usr/include/lua5.3 + diff --git a/examples/lua/lua51/build.sh b/examples/lua/lua51/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..3b52ed14489a636fe7a867ed086199647fa650df --- /dev/null +++ b/examples/lua/lua51/build.sh @@ -0,0 +1,2 @@ +gcc -std=c99 lua_connector51.c -fPIC -shared -o luaconnector51.so -Wall -ltaos + diff --git a/examples/lua/lua51/lauxlib.h b/examples/lua/lua51/lauxlib.h new file mode 100644 index 0000000000000000000000000000000000000000..a44f0272b3ab0745b0ce798d377b40d2cce113cd --- /dev/null +++ b/examples/lua/lua51/lauxlib.h @@ -0,0 +1,161 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + +/* From Lua 5.2. */ +LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname); +LUALIB_API int luaL_execresult(lua_State *L, int stat); +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, + int level); +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* From Lua 5.2. */ +#define luaL_newlibtable(L, l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) +#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0)) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + +#endif diff --git a/examples/lua/lua51/lua.h b/examples/lua/lua51/lua.h new file mode 100644 index 0000000000000000000000000000000000000000..9dcafd690655868115ce53dff26599f5845b12c5 --- /dev/null +++ b/examples/lua/lua51/lua.h @@ -0,0 +1,404 @@ +/* +** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.4" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + +LUA_API void lua_setexdata(lua_State *L, void *exdata); +LUA_API void *lua_getexdata(lua_State *L); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + +/* From Lua 5.2. */ +LUA_API void *lua_upvalueid (lua_State *L, int idx, int n); +LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2); +LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); +LUA_API const lua_Number *lua_version (lua_State *L); +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx); +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum); + +/* From Lua 5.3. */ +LUA_API int lua_isyieldable (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/examples/lua/lua51/lua_connector51.c b/examples/lua/lua51/lua_connector51.c new file mode 100644 index 0000000000000000000000000000000000000000..b6e0b6d1de200b09750ffba6845ae9bf0606f4d8 --- /dev/null +++ b/examples/lua/lua51/lua_connector51.c @@ -0,0 +1,381 @@ +#include +#include +#include +#include +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include + +struct cb_param{ + lua_State* state; + int callback; + void * stream; +}; + +struct async_query_callback_param{ + lua_State* state; + int callback; +}; + +static int l_connect(lua_State *L){ + TAOS * taos=NULL; + const char* host; + const char* database; + const char* user; + const char* password; + int port; + + luaL_checktype(L, 1, LUA_TTABLE); + + lua_getfield(L, 1,"host"); + if (lua_isstring(L,-1)){ + host = lua_tostring(L, -1); + // printf("host = %s\n", host); + } + + lua_getfield(L, 1, "port"); + if (lua_isnumber(L,-1)){ + port = lua_tonumber(L, -1); + //printf("port = %d\n", port); + } + + lua_getfield(L, 1, "database"); + if (lua_isstring(L, -1)){ + database = lua_tostring(L, -1); + //printf("database = %s\n", database); + } + + lua_getfield(L, 1, "user"); + if (lua_isstring(L, -1)){ + user = lua_tostring(L, -1); + //printf("user = %s\n", user); + } + + lua_getfield(L, 1, "password"); + if (lua_isstring(L, -1)){ + password = lua_tostring(L, -1); + //printf("password = %s\n", password); + } + + lua_settop(L,0); + + taos_init(); + + lua_newtable(L); + int table_index = lua_gettop(L); + + taos = taos_connect(host, user,password,database, port); + if (taos == NULL) { + printf("failed to connect server, reason:%s\n", taos_errstr(taos)); + + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,NULL); + lua_setfield(L, table_index, "conn"); + }else{ + // printf("success to connect server\n"); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,taos); + lua_setfield(L, table_index, "conn"); + } + + return 1; +} + +static int l_query(lua_State *L){ + TAOS *taos= (TAOS*)lua_topointer(L,1); + const char* s = lua_tostring(L, 2); + TAOS_RES *result; + lua_newtable(L); + int table_index = lua_gettop(L); + + // printf("receive command:%s\r\n",s); + result = taos_query(taos, s); + int32_t code = taos_errno(result); + if( code != 0){ + printf("failed, reason:%s\n", taos_errstr(result)); + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(result)); + lua_setfield(L, table_index, "error"); + + return 1; + + }else{ + //printf("success to query.\n"); + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + const TAOS_FIELD *fields = taos_fetch_fields(result); + //char temp[256]; + + const int affectRows = taos_affected_rows(result); + // printf(" affect rows:%d\r\n", affectRows); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushinteger(L, affectRows); + lua_setfield(L, table_index, "affected"); + lua_newtable(L); + + while ((row = taos_fetch_row(result))) { + //printf("row index:%d\n",rows); + rows++; + + lua_pushnumber(L,rows); + lua_newtable(L); + + for (int i = 0; i < num_fields; ++i) { + if (row[i] == NULL) { + continue; + } + + lua_pushstring(L,fields[i].name); + + switch (fields[i].type) { + case TSDB_DATA_TYPE_TINYINT: + lua_pushinteger(L,*((char *)row[i])); + break; + case TSDB_DATA_TYPE_SMALLINT: + lua_pushinteger(L,*((short *)row[i])); + break; + case TSDB_DATA_TYPE_INT: + lua_pushinteger(L,*((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_FLOAT: + lua_pushnumber(L,*((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + lua_pushnumber(L,*((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + lua_pushstring(L,(char *)row[i]); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_BOOL: + lua_pushinteger(L,*((char *)row[i])); + break; + default: + lua_pushnil(L); + break; + } + + lua_settable(L,-3); + } + + lua_settable(L,-3); + } + taos_free_result(result); + } + + lua_setfield(L, table_index, "item"); + return 1; +} + +void async_query_callback(void *param, TAOS_RES *result, int code){ + struct async_query_callback_param* p = (struct async_query_callback_param*) param; + + //printf("\nin c,numfields:%d\n", numFields); + //printf("\nin c, code:%d\n", code); + + lua_State *L = p->state; + lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback); + lua_newtable(L); + int table_index = lua_gettop(L); + if( code < 0){ + printf("failed, reason:%s\n", taos_errstr(result)); + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L,"something is wrong");// taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + }else{ + //printf("success to async query.\n"); + const int affectRows = taos_affected_rows(result); + //printf(" affect rows:%d\r\n", affectRows); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushinteger(L, affectRows); + lua_setfield(L, table_index, "affected"); + } + + lua_call(L, 1, 0); +} + +static int l_async_query(lua_State *L){ + int r = luaL_ref(L, LUA_REGISTRYINDEX); + TAOS * taos = (TAOS*)lua_topointer(L,1); + const char * sqlstr = lua_tostring(L,2); + // int stime = luaL_checknumber(L,3); + + lua_newtable(L); + int table_index = lua_gettop(L); + + struct async_query_callback_param *p = malloc(sizeof(struct async_query_callback_param)); + p->state = L; + p->callback=r; + // printf("r:%d, L:%d\n",r,L); + taos_query_a(taos,sqlstr,async_query_callback,p); + + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "ok"); + lua_setfield(L, table_index, "error"); + + return 1; +} + +void stream_cb(void *param, TAOS_RES *result, TAOS_ROW row){ + struct cb_param* p = (struct cb_param*) param; + TAOS_FIELD *fields = taos_fetch_fields(result); + int numFields = taos_num_fields(result); + + // printf("\nnumfields:%d\n", numFields); + //printf("\n\r-----------------------------------------------------------------------------------\n"); + + lua_State *L = p->state; + lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback); + + lua_newtable(L); + + for (int i = 0; i < numFields; ++i) { + if (row[i] == NULL) { + continue; + } + + lua_pushstring(L,fields[i].name); + + switch (fields[i].type) { + case TSDB_DATA_TYPE_TINYINT: + lua_pushinteger(L,*((char *)row[i])); + break; + case TSDB_DATA_TYPE_SMALLINT: + lua_pushinteger(L,*((short *)row[i])); + break; + case TSDB_DATA_TYPE_INT: + lua_pushinteger(L,*((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_FLOAT: + lua_pushnumber(L,*((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + lua_pushnumber(L,*((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + lua_pushstring(L,(char *)row[i]); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_BOOL: + lua_pushinteger(L,*((char *)row[i])); + break; + default: + lua_pushnil(L); + break; + } + + lua_settable(L, -3); + } + + lua_call(L, 1, 0); + + // printf("-----------------------------------------------------------------------------------\n\r"); +} + +static int l_open_stream(lua_State *L){ + int r = luaL_ref(L, LUA_REGISTRYINDEX); + TAOS * taos = (TAOS*)lua_topointer(L,1); + const char * sqlstr = lua_tostring(L,2); + int stime = luaL_checknumber(L,3); + + lua_newtable(L); + int table_index = lua_gettop(L); + + struct cb_param *p = malloc(sizeof(struct cb_param)); + p->state = L; + p->callback=r; + // printf("r:%d, L:%d\n",r,L); + void * s = taos_open_stream(taos,sqlstr,stream_cb,stime,p,NULL); + if (s == NULL) { + printf("failed to open stream, reason:%s\n", taos_errstr(taos)); + free(p); + lua_pushnumber(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,NULL); + lua_setfield(L, table_index, "stream"); + }else{ + // printf("success to open stream\n"); + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + p->stream = s; + lua_pushlightuserdata(L,p); + lua_setfield(L, table_index, "stream");//stream has different content in lua and c. + } + + return 1; +} + +static int l_close_stream(lua_State *L){ + //TODO:get stream and free cb_param + struct cb_param *p = lua_touserdata(L,1); + taos_close_stream(p->stream); + free(p); + return 0; +} + +static int l_close(lua_State *L){ + TAOS *taos= (TAOS*)lua_topointer(L,1); + lua_newtable(L); + int table_index = lua_gettop(L); + + if(taos == NULL){ + lua_pushnumber(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "null pointer."); + lua_setfield(L, table_index, "error"); + }else{ + taos_close(taos); + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "done."); + lua_setfield(L, table_index, "error"); + } + return 1; +} + +static const struct luaL_Reg lib[] = { + {"connect", l_connect}, + {"query", l_query}, + {"query_a",l_async_query}, + {"close", l_close}, + {"open_stream", l_open_stream}, + {"close_stream", l_close_stream}, + {NULL, NULL} +}; + +extern int luaopen_luaconnector51(lua_State* L) +{ + // luaL_register(L, "luaconnector51", lib); + lua_newtable (L); + luaL_setfuncs(L,lib,0); + return 1; +} diff --git a/examples/lua/lua51/luaconf.h b/examples/lua/lua51/luaconf.h new file mode 100644 index 0000000000000000000000000000000000000000..c72893fd152e23c2a413c2da1d31be7b860b2a39 --- /dev/null +++ b/examples/lua/lua51/luaconf.h @@ -0,0 +1,152 @@ +/* +** Configuration header. +** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef luaconf_h +#define luaconf_h + +#ifndef WINVER +#define WINVER 0x0501 +#endif +#include +#include + +/* Default path for loading Lua and C modules with require(). */ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" "!\\lualib\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" "!\\lualib\\?.so;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" +#else +/* +** Note to distribution maintainers: do NOT patch the following lines! +** Please read ../doc/install.html#distro and pass PREFIX=/usr instead. +*/ +#ifndef LUA_MULTILIB +#define LUA_MULTILIB "lib" +#endif +#ifndef LUA_LMULTILIB +#define LUA_LMULTILIB "lib" +#endif +#define LUA_LROOT "/usr/local" +#define LUA_LUADIR "/lua/5.1/" +#define LUA_LJDIR "/luajit-2.1.0-beta3/" + +#ifdef LUA_ROOT +#define LUA_JROOT LUA_ROOT +#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR +#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR +#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua" +#define LUA_RCPATH ";" LUA_RCDIR "?.so" +#else +#define LUA_JROOT LUA_LROOT +#define LUA_RLPATH +#define LUA_RCPATH +#endif + +#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua" +#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR +#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR +#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua" +#define LUA_LCPATH1 ";" LUA_LCDIR "?.so" +#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so" + +#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH +#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2 +#endif + +/* Environment variable names for path overrides and initialization code. */ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + +/* Special file system characters. */ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" +#define LUA_PATH_CONFIG \ + LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \ + LUA_EXECDIR "\n" LUA_IGMARK "\n" + +/* Quoting in error messages. */ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +/* Various tunables. */ +#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */ +#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */ +#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */ +#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */ +#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */ + +/* Configuration for the frontend (the luajit executable). */ +#if defined(luajit_c) +#define LUA_PROGNAME "luajit" /* Fallback frontend name. */ +#define LUA_PROMPT "> " /* Interactive prompt. */ +#define LUA_PROMPT2 ">> " /* Continuation prompt. */ +#define LUA_MAXINPUT 512 /* Max. input line length. */ +#endif + +/* Note: changing the following defines breaks the Lua 5.1 ABI. */ +#define LUA_INTEGER ptrdiff_t +#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */ +/* +** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using +** unreasonable amounts of stack space, but still retain ABI compatibility. +** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it. +*/ +#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ) + +/* The following defines are here only for compatibility with luaconf.h +** from the standard Lua distribution. They must not be changed for LuaJIT. +*/ +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double +#define LUAI_UACNUMBER double +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +/* Linkage of public API functions. */ +#if defined(LUA_BUILD_AS_DLL) +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif +#else +#define LUA_API extern +#endif + +#define LUALIB_API LUA_API + +/* Support for internal assertions. */ +#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK) +#include +#endif +#ifdef LUA_USE_ASSERT +#define lua_assert(x) assert(x) +#endif +#ifdef LUA_USE_APICHECK +#define luai_apicheck(L, o) { (void)L; assert(o); } +#else +#define luai_apicheck(L, o) { (void)L; } +#endif + +#endif diff --git a/examples/lua/lua51/luajit.h b/examples/lua/lua51/luajit.h new file mode 100644 index 0000000000000000000000000000000000000000..ae14c4ffebdff746b22b2274abf33b5c9d601b26 --- /dev/null +++ b/examples/lua/lua51/luajit.h @@ -0,0 +1,81 @@ +/* +** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/ +** +** Copyright (C) 2005-2017 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#ifndef _LUAJIT_H +#define _LUAJIT_H + +#include "lua.h" + +#define OPENRESTY_LUAJIT + +#define LUAJIT_VERSION "LuaJIT 2.1.0-beta3" +#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */ +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_0_beta3 +#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2017 Mike Pall" +#define LUAJIT_URL "http://luajit.org/" + +/* Modes for luaJIT_setmode. */ +#define LUAJIT_MODE_MASK 0x00ff + +enum { + LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */ + LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */ + + LUAJIT_MODE_FUNC, /* Change mode for a function. */ + LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */ + LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */ + + LUAJIT_MODE_TRACE, /* Flush a compiled trace. */ + + LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */ + + LUAJIT_MODE_MAX +}; + +/* Flags or'ed in to the mode. */ +#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */ +#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */ +#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */ + +/* LuaJIT public C API. */ + +/* Control the JIT engine. */ +LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode); + +/* Low-overhead profiling API. */ +typedef void (*luaJIT_profile_callback)(void *data, lua_State *L, + int samples, int vmstate); +LUA_API void luaJIT_profile_start(lua_State *L, const char *mode, + luaJIT_profile_callback cb, void *data); +LUA_API void luaJIT_profile_stop(lua_State *L); +LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt, + int depth, size_t *len); + +/* Enforce (dynamic) linker error for version mismatches. Call from main. */ +LUA_API void LUAJIT_VERSION_SYM(void); + +#endif diff --git a/examples/lua/lua51/lualib.h b/examples/lua/lua51/lualib.h new file mode 100644 index 0000000000000000000000000000000000000000..6aceabe59218d1863e6493bb77b9bed18bc18bdc --- /dev/null +++ b/examples/lua/lua51/lualib.h @@ -0,0 +1,44 @@ +/* +** Standard library header. +** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef _LUALIB_H +#define _LUALIB_H + +#include "lua.h" + +#define LUA_FILEHANDLE "FILE*" + +#define LUA_COLIBNAME "coroutine" +#define LUA_MATHLIBNAME "math" +#define LUA_STRLIBNAME "string" +#define LUA_TABLIBNAME "table" +#define LUA_IOLIBNAME "io" +#define LUA_OSLIBNAME "os" +#define LUA_LOADLIBNAME "package" +#define LUA_DBLIBNAME "debug" +#define LUA_BITLIBNAME "bit" +#define LUA_JITLIBNAME "jit" +#define LUA_FFILIBNAME "ffi" +#define LUA_THRLIBNAME "thread" + +LUALIB_API int luaopen_base(lua_State *L); +LUALIB_API int luaopen_math(lua_State *L); +LUALIB_API int luaopen_string(lua_State *L); +LUALIB_API int luaopen_table(lua_State *L); +LUALIB_API int luaopen_io(lua_State *L); +LUALIB_API int luaopen_os(lua_State *L); +LUALIB_API int luaopen_package(lua_State *L); +LUALIB_API int luaopen_debug(lua_State *L); +LUALIB_API int luaopen_bit(lua_State *L); +LUALIB_API int luaopen_jit(lua_State *L); +LUALIB_API int luaopen_ffi(lua_State *L); + +LUALIB_API void luaL_openlibs(lua_State *L); + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + +#endif diff --git a/examples/lua/lua_connector.c b/examples/lua/lua_connector.c new file mode 100644 index 0000000000000000000000000000000000000000..06568f35d656d5d9af1ae2e88eeaeba92f0ede91 --- /dev/null +++ b/examples/lua/lua_connector.c @@ -0,0 +1,380 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct cb_param{ + lua_State* state; + int callback; + void * stream; +}; + +struct async_query_callback_param{ + lua_State* state; + int callback; +}; + +static int l_connect(lua_State *L){ + TAOS * taos=NULL; + const char* host; + const char* database; + const char* user; + const char* password; + int port; + + luaL_checktype(L, 1, LUA_TTABLE); + + lua_getfield(L,1,"host"); + if (lua_isstring(L,-1)){ + host = lua_tostring(L, -1); + // printf("host = %s\n", host); + } + + lua_getfield(L, 1, "port"); + if (lua_isinteger(L,-1)){ + port = lua_tointeger(L, -1); + //printf("port = %d\n", port); + } + + lua_getfield(L, 1, "database"); + if (lua_isstring(L, -1)){ + database = lua_tostring(L, -1); + //printf("database = %s\n", database); + } + + lua_getfield(L, 1, "user"); + if (lua_isstring(L, -1)){ + user = lua_tostring(L, -1); + //printf("user = %s\n", user); + } + + lua_getfield(L, 1, "password"); + if (lua_isstring(L, -1)){ + password = lua_tostring(L, -1); + //printf("password = %s\n", password); + } + + lua_settop(L,0); + + taos_init(); + + lua_newtable(L); + int table_index = lua_gettop(L); + + taos = taos_connect(host, user,password,database, port); + if (taos == NULL) { + printf("failed to connect server, reason:%s\n", taos_errstr(taos)); + + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,NULL); + lua_setfield(L, table_index, "conn"); + }else{ + // printf("success to connect server\n"); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,taos); + lua_setfield(L, table_index, "conn"); + } + + return 1; +} + +static int l_query(lua_State *L){ + TAOS *taos= (TAOS*)lua_topointer(L,1); + const char* s = lua_tostring(L, 2); + TAOS_RES *result; + lua_newtable(L); + int table_index = lua_gettop(L); + + // printf("receive command:%s\r\n",s); + result = taos_query(taos, s); + int32_t code = taos_errno(result); + if( code != 0){ + printf("failed, reason:%s\n", taos_errstr(result)); + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(result)); + lua_setfield(L, table_index, "error"); + + return 1; + + }else{ + //printf("success to query.\n"); + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + const TAOS_FIELD *fields = taos_fetch_fields(result); + //char temp[256]; + + const int affectRows = taos_affected_rows(result); + // printf(" affect rows:%d\r\n", affectRows); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushinteger(L, affectRows); + lua_setfield(L, table_index, "affected"); + lua_newtable(L); + + while ((row = taos_fetch_row(result))) { + //printf("row index:%d\n",rows); + rows++; + + lua_pushnumber(L,rows); + lua_newtable(L); + + for (int i = 0; i < num_fields; ++i) { + if (row[i] == NULL) { + continue; + } + + lua_pushstring(L,fields[i].name); + + switch (fields[i].type) { + case TSDB_DATA_TYPE_TINYINT: + lua_pushinteger(L,*((char *)row[i])); + break; + case TSDB_DATA_TYPE_SMALLINT: + lua_pushinteger(L,*((short *)row[i])); + break; + case TSDB_DATA_TYPE_INT: + lua_pushinteger(L,*((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_FLOAT: + lua_pushnumber(L,*((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + lua_pushnumber(L,*((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + lua_pushstring(L,(char *)row[i]); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_BOOL: + lua_pushinteger(L,*((char *)row[i])); + break; + default: + lua_pushnil(L); + break; + } + + lua_settable(L,-3); + } + + lua_settable(L,-3); + } + taos_free_result(result); + } + + lua_setfield(L, table_index, "item"); + return 1; +} + +void async_query_callback(void *param, TAOS_RES *result, int code){ + struct async_query_callback_param* p = (struct async_query_callback_param*) param; + + //printf("\nin c,numfields:%d\n", numFields); + //printf("\nin c, code:%d\n", code); + + lua_State *L = p->state; + lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback); + lua_newtable(L); + int table_index = lua_gettop(L); + if( code < 0){ + printf("failed, reason:%s\n", taos_errstr(result)); + lua_pushinteger(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L,"something is wrong");// taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + }else{ + //printf("success to async query.\n"); + const int affectRows = taos_affected_rows(result); + //printf(" affect rows:%d\r\n", affectRows); + lua_pushinteger(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushinteger(L, affectRows); + lua_setfield(L, table_index, "affected"); + } + + lua_call(L, 1, 0); +} + +static int l_async_query(lua_State *L){ + int r = luaL_ref(L, LUA_REGISTRYINDEX); + TAOS * taos = (TAOS*)lua_topointer(L,1); + const char * sqlstr = lua_tostring(L,2); + // int stime = luaL_checknumber(L,3); + + lua_newtable(L); + int table_index = lua_gettop(L); + + struct async_query_callback_param *p = malloc(sizeof(struct async_query_callback_param)); + p->state = L; + p->callback=r; + // printf("r:%d, L:%d\n",r,L); + taos_query_a(taos,sqlstr,async_query_callback,p); + + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "ok"); + lua_setfield(L, table_index, "error"); + + return 1; +} + +void stream_cb(void *param, TAOS_RES *result, TAOS_ROW row){ + struct cb_param* p = (struct cb_param*) param; + TAOS_FIELD *fields = taos_fetch_fields(result); + int numFields = taos_num_fields(result); + + // printf("\nnumfields:%d\n", numFields); + //printf("\n\r-----------------------------------------------------------------------------------\n"); + + lua_State *L = p->state; + lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback); + + lua_newtable(L); + + for (int i = 0; i < numFields; ++i) { + if (row[i] == NULL) { + continue; + } + + lua_pushstring(L,fields[i].name); + + switch (fields[i].type) { + case TSDB_DATA_TYPE_TINYINT: + lua_pushinteger(L,*((char *)row[i])); + break; + case TSDB_DATA_TYPE_SMALLINT: + lua_pushinteger(L,*((short *)row[i])); + break; + case TSDB_DATA_TYPE_INT: + lua_pushinteger(L,*((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_FLOAT: + lua_pushnumber(L,*((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + lua_pushnumber(L,*((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + lua_pushstring(L,(char *)row[i]); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + lua_pushinteger(L,*((int64_t *)row[i])); + break; + case TSDB_DATA_TYPE_BOOL: + lua_pushinteger(L,*((char *)row[i])); + break; + default: + lua_pushnil(L); + break; + } + + lua_settable(L, -3); + } + + lua_call(L, 1, 0); + + // printf("-----------------------------------------------------------------------------------\n\r"); +} + +static int l_open_stream(lua_State *L){ + int r = luaL_ref(L, LUA_REGISTRYINDEX); + TAOS * taos = (TAOS*)lua_topointer(L,1); + const char * sqlstr = lua_tostring(L,2); + int stime = luaL_checknumber(L,3); + + lua_newtable(L); + int table_index = lua_gettop(L); + + struct cb_param *p = malloc(sizeof(struct cb_param)); + p->state = L; + p->callback=r; + // printf("r:%d, L:%d\n",r,L); + void * s = taos_open_stream(taos,sqlstr,stream_cb,stime,p,NULL); + if (s == NULL) { + printf("failed to open stream, reason:%s\n", taos_errstr(taos)); + free(p); + lua_pushnumber(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + lua_pushlightuserdata(L,NULL); + lua_setfield(L, table_index, "stream"); + }else{ + // printf("success to open stream\n"); + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, taos_errstr(taos)); + lua_setfield(L, table_index, "error"); + p->stream = s; + lua_pushlightuserdata(L,p); + lua_setfield(L, table_index, "stream");//stream has different content in lua and c. + } + + return 1; +} + +static int l_close_stream(lua_State *L){ + //TODO:get stream and free cb_param + struct cb_param *p = lua_touserdata(L,1); + taos_close_stream(p->stream); + free(p); + return 0; +} + +static int l_close(lua_State *L){ + TAOS *taos= (TAOS*)lua_topointer(L,1); + lua_newtable(L); + int table_index = lua_gettop(L); + + if(taos == NULL){ + lua_pushnumber(L, -1); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "null pointer."); + lua_setfield(L, table_index, "error"); + }else{ + taos_close(taos); + lua_pushnumber(L, 0); + lua_setfield(L, table_index, "code"); + lua_pushstring(L, "done."); + lua_setfield(L, table_index, "error"); + } + return 1; +} + +static const struct luaL_Reg lib[] = { + {"connect", l_connect}, + {"query", l_query}, + {"query_a",l_async_query}, + {"close", l_close}, + {"open_stream", l_open_stream}, + {"close_stream", l_close_stream}, + {NULL, NULL} +}; + +extern int luaopen_luaconnector(lua_State* L) +{ + luaL_newlib(L, lib); + + return 1; +} diff --git a/examples/lua/test.lua b/examples/lua/test.lua new file mode 100644 index 0000000000000000000000000000000000000000..89c0904c6a04ecec79a95cb1f710136e93a4a00b --- /dev/null +++ b/examples/lua/test.lua @@ -0,0 +1,168 @@ +local driver = require "luaconnector" + +local config = { + host = "127.0.0.1", + port = 6030, + database = "", + user = "root", + password = "taosdata", + max_packet_size = 1024 * 1024 +} + +local conn +local res = driver.connect(config) +if res.code ~=0 then + print("connect--- failed: "..res.error) + return +else + conn = res.conn + print("connect--- pass.") +end + +local res = driver.query(conn,"drop database if exists demo") + +res = driver.query(conn,"create database demo") +if res.code ~=0 then + print("create db--- failed: "..res.error) + return +else + print("create db--- pass.") +end + +res = driver.query(conn,"use demo") +if res.code ~=0 then + print("select db--- failed: "..res.error) + return +else + print("select db--- pass.") +end + +res = driver.query(conn,"create table m1 (ts timestamp, speed int,owner binary(20))") +if res.code ~=0 then + print("create table---failed: "..res.error) + return +else + print("create table--- pass.") +end + +res = driver.query(conn,"insert into m1 values ('2019-09-01 00:00:00.001',0,'robotspace'), ('2019-09-01 00:00:00.002',1,'Hilink'),('2019-09-01 00:00:00.003',2,'Harmony')") +if res.code ~=0 then + print("insert records failed: "..res.error) + return +else + if(res.affected == 3) then + print("insert records--- pass") + else + print("insert records---failed: expect 3 affected records, actually affected "..res.affected) + end +end + +res = driver.query(conn,"select * from m1") + +if res.code ~=0 then + print("select failed: "..res.error) + return +else + if (#(res.item) == 3) then + print("select--- pass") + else + print("select--- failed: expect 3 affected records, actually received "..#(res.item)) + end + +end + +res = driver.query(conn,"CREATE TABLE thermometer (ts timestamp, degree double) TAGS(location binary(20), type int)") +if res.code ~=0 then + print(res.error) + return +else + print("create super table--- pass") +end +res = driver.query(conn,"CREATE TABLE therm1 USING thermometer TAGS ('beijing', 1)") +if res.code ~=0 then + print(res.error) + return +else + print("create table--- pass") +end + +res = driver.query(conn,"INSERT INTO therm1 VALUES ('2019-09-01 00:00:00.001', 20),('2019-09-01 00:00:00.002', 21)") + +if res.code ~=0 then + print(res.error) + return +else + if(res.affected == 2) then + print("insert records--- pass") + else + print("insert records---failed: expect 2 affected records, actually affected "..res.affected) + end +end + +res = driver.query(conn,"SELECT COUNT(*) count, AVG(degree) AS av, MAX(degree), MIN(degree) FROM thermometer WHERE location='beijing' or location='tianjin' GROUP BY location, type") +if res.code ~=0 then + print("select from super table--- failed:"..res.error) + return +else + print("select from super table--- pass") + for i = 1, #(res.item) do + print("res:"..res.item[i].count) + end +end + +function async_query_callback(res) + if res.code ~=0 then + print("async_query_callback--- failed:"..res.error) + return + else + + if(res.affected == 3) then + print("async_query_callback, insert records--- pass") + else + print("async_query_callback, insert records---failed: expect 3 affected records, actually affected "..res.affected) + end + + end +end + +driver.query_a(conn,"INSERT INTO therm1 VALUES ('2019-09-01 00:00:00.005', 100),('2019-09-01 00:00:00.006', 101),('2019-09-01 00:00:00.007', 102)", async_query_callback) + + +function stream_callback(t) + print("------------------------") + print("continuous query result:") + for key, value in pairs(t) do + print("key:"..key..", value:"..value) + end +end + +local stream +res = driver.open_stream(conn,"SELECT COUNT(*) as count, AVG(degree) as avg, MAX(degree) as max, MIN(degree) as min FROM thermometer interval(2s) sliding(2s);)",0, stream_callback) +if res.code ~=0 then + print("open stream--- failed:"..res.error) + return +else + print("open stream--- pass") + stream = res.stream +end + +print("From now on we start continous insert in an definite (infinite if you want) loop.") +local loop_index = 0 +while loop_index < 30 do + local t = os.time()*1000 + local v = loop_index + res = driver.query(conn,string.format("INSERT INTO therm1 VALUES (%d, %d)",t,v)) + + if res.code ~=0 then + print("continous insertion--- failed:" .. res.error) + return + else + --print("insert successfully, affected:"..res.affected) + end + os.execute("sleep " .. 1) + loop_index = loop_index + 1 +end + +driver.close_stream(stream) + +driver.close(conn) diff --git a/examples/matlab/TDengineDemo.m b/examples/matlab/TDengineDemo.m new file mode 100644 index 0000000000000000000000000000000000000000..b44777512bb20d6231d92dd19645d39b77ac80ca --- /dev/null +++ b/examples/matlab/TDengineDemo.m @@ -0,0 +1,128 @@ +%% Connect to TDengine +clear; +fprintf("Connecting to TDengine..."); +dbName = 'tsdb'; +user = 'root'; +password = 'taosdata'; +jdbcDriverName = 'com.taosdata.jdbc.TSDBDriver'; +jdbcUrl = 'jdbc:TSDB://192.168.1.113:0/'; +conn = database(dbName, user, password, jdbcDriverName, jdbcUrl) +if isempty(conn.Message) + fprintf("Connection is successfully established!\n"); +else + fprintf("Failed to connect to server: %s\n", conn.Message); +end + +%% Query a table in TDengine, and store the results in a MATLAB table object 'tb1' +% Please note that the select() function retrieves all rows in a table/supertale into MATLAB +sql = "select ts, distance1 from device1 limit 5"; +fprintf("Execute query: %s\n", sql); +tic +tb1 = select(conn, sql); +timeused = toc; +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(tb1), width(tb1), timeused); + +% To go a bit further, we can convert the MATLAB table object to a MATLAB matrix object +data = table2array(tb1) + +%% Query table names in a TDengine supertable, and store the results in a MATLAB table object 'stbmeta' +sql = "select tbname from devices limit 10"; +fprintf("Execute query: %s\n", sql); +tic; +stbmeta = select(conn, sql); +timeused = toc; +fprintf("\tTables in supertable 'devices': %t", stbmeta); +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(stbmeta), width(stbmeta), timeused); + +%% Query a TDengine supertable, and stores the results in a MATLAB table object 'stb' +sql = "select ts, distance1 from devices"; +fprintf("Execute query: %s\n", sql); +tic; +stb = select(conn, sql); +timeused = toc; +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(stb), width(stb), timeused); + +%% Query TDengine using cursors and specify the number of rows to fetch +sql = 'select * from device1'; +rowLimit = 5; +fprintf("Execute query: %s with row limit set to %d\n", sql, rowLimit); +tic; +% Get cursor +cur = exec(conn, sql); +% Fetch data +cur = fetch(cur, rowLimit); +data = cur.Data +timeused = toc; +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(data, 1), size(data, 2), timeused); + +%% Query specific columns in a TDenigine table 'device1', and stores the results directly in a MATLAB cell array 'data' +sql = 'SELECT * FROM device1 order by ts asc'; +fprintf("Execute query: %s\n", sql); +tic; +data = fetch(conn, sql); +timeused = toc; +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(data, 1), size(data, 2), timeused); +% Let's now convert the cell array 'data' into some matrices, and make a plot of column 'c1' again the timestamp 'ts' +ts = cell2mat(data(:,1)); +c1 = cell2mat(data(:,2)); + +%% Query aggregation results from a table +% TDengine is so powerful at aggregated computations. Let's calculate the max, mean, standard deviation and min values for every 10 minutes in the +% tb1's timeline, and then plot them together with all the data points in tb1 +sql = sprintf('SELECT max(measure1), avg(measure1), stddev(measure1), min(measure1) FROM device1 WHERE ts >= %d and ts <= %d interval(10m)', ts(1), ts(end)); +fprintf("Execute query: %s\n", sql); +tic; +c1_stats = fetch(conn, sql); +timeused = toc; +fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(c1_stats, 1), size(c1_stats, 2), timeused); +% Prepare data for plotting. +tsAsDate = datestr(ts/86400000 + datenum(1970,1,1), 'mm-dd HH:MM'); +c1_stats = cell2mat(c1_stats); +c1_stats_ts = c1_stats(:, 1); +c1_stats_max = c1_stats(:, 2); +c1_stats_mean = c1_stats(:, 3); +c1_stats_stddev = c1_stats(:, 4); +c1_stats_min = c1_stats(:, 5); +c1_stats_tsAsDate = datestr(c1_stats(:,1)/86400000 + datenum(1970,1,1), 'mm-dd HH:MM'); + +%% Now let's plot the data and associated statistical aggregation calculation in a figure. +fh = figure(1); +set(fh,'position',[50 50 1300 700]); +h1 = scatter(ts, c1, 5, 'c'); +hold on; +h2 = plot(c1_stats_ts + 300000, c1_stats_max, '-or', 'linewidth', 1); +hold on; +h3 = plot(c1_stats_ts + 300000, c1_stats_mean, '-xg', 'linewidth', 1); +hold on; +h4 = plot(c1_stats_ts + 300000, c1_stats_stddev, '-*y', 'linewidth', 1); +hold on; +h5 = plot(c1_stats_ts + 300000, c1_stats_min, '-+k', 'linewidth', 1); +xlabel('time'); +ylabel('measurement1'); +set(gca, 'xtick',[ts(1),ts(end/4),ts(2*end/4),ts(3*end/4),ts(end)]); +set(gca, 'xticklabel',{tsAsDate(1,:), tsAsDate(end/4,:),tsAsDate(2*end/4,:),tsAsDate(3*end/4,:),tsAsDate(end,:)}); +xlim([ts(1), ts(end)]); +legend([h1, h2, h3, h4, h5], 'data points', 'max per 10 mins', 'mean per 10 mins', 'stddev per 10 mins', 'min per 10 mins'); +title('Device Measurement Monitoring Demo'); +grid on; + +%% Insert data into TDengine using exec() +sql = 'insert into device1 (ts, distance1) values (now, -1)'; +fprintf("Execute query: %s\n", sql); +cur = exec(conn, sql) +sql = 'select * from device1 limit 1'; +fprintf("Execute query: %s\n", sql); +data = select(conn, sql) +conn.close; + +%% Insert data into TDengine using datainsert() +% this is currently not supported + +% colnames = {'ts','c1','c2','c3'}; +% dat = {'now' 99 99 99}; +% tbname = 'plane1'; +% datainsert(conn, tbname, colnames, dat); +% cur = exec(conn, 'select * from ' + tbname); +% cur = fetch(cur, 5); +% data = cur.Data + diff --git a/examples/nodejs/README-win.md b/examples/nodejs/README-win.md new file mode 100644 index 0000000000000000000000000000000000000000..75fec69413af2bb49498118ec7235c9947e2f89e --- /dev/null +++ b/examples/nodejs/README-win.md @@ -0,0 +1,200 @@ +# 如何在windows上使用nodejs进行TDengine应用开发 + +## 环境准备 + +(1)安装nodejs-10.22.0 + +下载链接:https://nodejs.org/dist/v10.22.0/node-v10.22.0-win-x64.zip +解压安装,把node配置到环境变量里 + +cmd启动命令行,查看node的版本 + +```shell +> node.exe --version +v10.22.0 + +> npm --version +6.14.6 +``` + + + +(2)安装python2.7 + +下载链接:https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi + +查看python版本 + +```shell +>python --version +Python 2.7.18 +``` + + +(3)安装TDengine-client + +下载地址:https://www.taosdata.com/cn/all-downloads/,选择一个合适的windows-client下载(client应该尽量与server端的版本保持一致) + +使用client的taos shell连接server + +```shell +>taos -h node5 + +Welcome to the TDengine shell from Linux, Client Version:2.0.6.0 +Copyright (c) 2017 by TAOS Data, Inc. All rights reserved. + +taos> show dnodes; + id | end_point | vnodes | cores | status | role | create_time | offline reason | +============================================================================================================================================ + 1 | node5:6030 | 7 | 1 | ready | any | 2020-10-26 09:45:26.308 | | +Query OK, 1 row(s) in set (0.036000s) +``` + +注意: +* 检查能否在client的机器上ping通server的fqdn +* 如果你的dns server并没有提供到server的域名解析,可以将server的hostname配置到client的hosts文件中 + + +## 应用开发 + +(1)建立nodejs项目 + +``` +npm init +``` + +(2)安装windows-build-tools +``` +npm install --global --production windows-build-tools +``` + +(3)安装td2.0-connector驱动 + +``` tdshell +npm install td2.0-connector +``` + +(4)nodejs访问tdengine的示例程序 + +```javascript +const taos = require('td2.0-connector'); + +var host = null; +var port = 6030; +for (var i = 2; i < global.process.argv.length; i++) { + var key = global.process.argv[i].split("=")[0]; + var value = global.process.argv[i].split("=")[1]; + + if ("host" == key) { + host = value; + } + if ("port" == key) { + port = value; + } +} + +if (host == null) { + console.log("Usage: node nodejsChecker.js host= port="); + process.exit(0); +} + +// establish connection +var conn = taos.connect({host: host, user: "root", password: "taosdata", port: port}); +var cursor = conn.cursor(); +// create database +executeSql("create database if not exists testnodejs", 0); +// use db +executeSql("use testnodejs", 0); +// drop table +executeSql("drop table if exists testnodejs.weather", 0); +// create table +executeSql("create table if not exists testnodejs.weather(ts timestamp, temperature float, humidity int)", 0); +// insert +executeSql("insert into testnodejs.weather (ts, temperature, humidity) values(now, 20.5, 34)", 1); +// select +executeQuery("select * from testnodejs.weather"); +// close connection +conn.close(); + +function executeQuery(sql) { + var start = new Date().getTime(); + var promise = cursor.query(sql, true); + var end = new Date().getTime(); + promise.then(function (result) { + printSql(sql, result != null, (end - start)); + result.pretty(); + }); +} + +function executeSql(sql, affectRows) { + var start = new Date().getTime(); + var promise = cursor.execute(sql); + var end = new Date().getTime(); + printSql(sql, promise == affectRows, (end - start)); +} + +function printSql(sql, succeed, cost) { + console.log("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); +} +``` + +(5)测试nodejs程序 + +```shell +>node nodejsChecker.js +Usage: node nodejsChecker.js host= port= +# 提示指定host + +>node nodejsChecker.js host=node5 +Successfully connected to TDengine +Query OK, 0 row(s) affected (0.00997610s) +[ OK ] time cost: 14 ms, execute statement ====> create database if not exists testnodejs +Query OK, 0 row(s) affected (0.00235920s) +[ OK ] time cost: 4 ms, execute statement ====> use testnodejs +Query OK, 0 row(s) affected (0.06604280s) +[ OK ] time cost: 67 ms, execute statement ====> drop table if exists testnodejs.weather +Query OK, 0 row(s) affected (0.59403290s) +[ OK ] time cost: 595 ms, execute statement ====> create table if not exists testnodejs.weather(ts timestamp, temperature float, humidity int) +Query OK, 1 row(s) affected (0.01058950s) +[ OK ] time cost: 12 ms, execute statement ====> insert into testnodejs.weather (ts, temperature, humidity) values(now, 20.5, 34) +Query OK, 1 row(s) in set (0.00401490s) +[ OK ] time cost: 10 ms, execute statement ====> select * from testnodejs.weather +Connection is closed + + ts | temperature | humidity | +===================================================================== +2020-10-27 18:49:15.547 | 20.5 | 34 | +``` + +## 指南 + +### 如何设置主机名和hosts + +在server上查看hostname和fqdn +```shell +查看hostname +# hostname +taos-server + +查看fqdn +# hostname -f +taos-server +``` + +windows下hosts文件位于: +C:\\Windows\System32\drivers\etc\hosts +修改hosts文件,添加server的ip和hostname + +``` +192.168.56.101 node5 +``` + +> 什么是FQDN? +> +> FQDN(Full qualified domain name)全限定域名,fqdn由2部分组成:hostname+domainname。 +> +> 例如,一个邮件服务器的fqdn可能是:mymail.somecollege.edu,其中mymail是hostname(主机名),somcollege.edu是domainname(域名)。本例中,.edu是顶级域名,.somecollege是二级域名。 +> +> 当连接服务器时,必须指定fqdn,然后,dns服务器通过查看dns表,将hostname解析为相应的ip地址。如果只指定hostname(不指定domainname),应用程序可能服务解析主机名。因为如果你试图访问不在本地的远程服务器时,本地的dns服务器和可能没有远程服务器的hostname列表。 +> +> 参考:https://kb.iu.edu/d/aiuv diff --git a/examples/nodejs/node-example-raw.js b/examples/nodejs/node-example-raw.js new file mode 100644 index 0000000000000000000000000000000000000000..80d5cd1bdea23370f1ac03756541eaa96937a6d6 --- /dev/null +++ b/examples/nodejs/node-example-raw.js @@ -0,0 +1,123 @@ +/* This example is to show how to use the td-connector through the cursor only and is a bit more raw. + * No promises, object wrappers around data, functions that prettify the data, or anything. + * The cursor will generally use callback functions over promises, and return and store the raw data from the C Interface. + * It is advised to use the td-connector through the cursor and the TaosQuery class amongst other higher level APIs. +*/ + +// Get the td-connector package +const taos = require('td2.0-connector'); + +/* We will connect to TDengine by passing an object comprised of connection options to taos.connect and store the + * connection to the variable conn + */ +/* + * Connection Options + * host: the host to connect to + * user: the use to login as + * password: the password for the above user to login + * config: the location of the taos.cfg file, by default it is in /etc/taos + * port: the port we connect through + */ +var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}); + +// Initialize our TDengineCursor, which we use to interact with TDengine +var c1 = conn.cursor(); + +//execute the sql +function execute(sql){ + try { + c1.execute(sql); + } + catch(err) { + conn.close(); + throw err; + } +} + +// c1.execute(query) will execute the query +// Let's create a database named db +execute('create database if not exists db;') + +// Now we will use database db +execute('use db;') + + +// Let's create a table called weather +// which stores some weather data like humidity, AQI (air quality index), temperature, and some notes as text +execute('create table if not exists weather (ts timestamp, humidity smallint, aqi int, temperature float, notes binary(30));'); + +// Let's get the description of the table weather +execute('describe db.weather'); + +// To get results, we run the function c1.fetchall() +// It only returns the query results as an array of result rows, but also stores the latest results in c1.data +try { + var tableDesc = c1.fetchall(); // The description variable here is equal to c1.data; + console.log(tableDesc); +} +catch (err) { + conn.close(); + throw err; +} + +// Let's try to insert some random generated data to test with + +let stime = new Date(); +let interval = 1000; + +// Timestamps must be in the form of "YYYY-MM-DD HH:MM:SS.MMM" if they are in milliseconds +// "YYYY-MM-DD HH:MM:SS.MMMMMM" if they are in microseconds +// Thus, we create the following function to convert a javascript Date object to the correct formatting +function convertDateToTS(date) { + let tsArr = date.toISOString().split("T") + return "\"" + tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length-1) + "\""; +} + +try { + for (let i = 0; i < 10000; i++) { + stime.setMilliseconds(stime.getMilliseconds() + interval); + let insertData = [convertDateToTS(stime), + parseInt(Math.random()*100), + parseInt(Math.random()*300), + parseFloat(Math.random()*10 + 30), + "\"random note!\""]; + c1.execute('insert into db.weather values(' + insertData.join(',') + ' );'); + } +} +catch (err) { + conn.close(); + throw err; +} + +// Now let's look at our newly inserted data +var retrievedData; +try { + c1.execute('select * from db.weather;') + retrievedData = c1.fetchall(); + + // c1.fields stores the names of each column retrieved + console.log(c1.fields); + console.log(retrievedData); + // timestamps retrieved are always JS Date Objects + // Numbers are numbers, big ints are big ints, and strings are strings +} +catch (err) { + conn.close(); + throw err; +} + +// Let's try running some basic functions +try { + c1.execute('select count(*), avg(temperature), max(temperature), min(temperature), stddev(temperature) from db.weather;') + c1.fetchall(); + console.log(c1.fields); + console.log(c1.data); +} +catch(err) { + conn.close(); + throw err; +} + +conn.close(); + +// Feel free to fork this repository or copy this code and start developing your own apps and backends with NodeJS and TDengine! diff --git a/examples/nodejs/node-example.js b/examples/nodejs/node-example.js new file mode 100644 index 0000000000000000000000000000000000000000..bfdd9e49a08fc1d6c20f3bdafbb84a500986b9fd --- /dev/null +++ b/examples/nodejs/node-example.js @@ -0,0 +1,153 @@ +/* This example is to show the preferred way to use the td-connector */ +/* To run, enter node path/to/node-example.js */ +// Get the td-connector package +const taos = require('td2.0-connector'); + +/* We will connect to TDengine by passing an object comprised of connection options to taos.connect and store the + * connection to the variable conn + */ +/* + * Connection Options + * host: the host to connect to + * user: the use to login as + * password: the password for the above user to login + * config: the location of the taos.cfg file, by default it is in /etc/taos + * port: the port we connect through + */ +var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}); + +// Initialize our TDengineCursor, which we use to interact with TDengine +var c1 = conn.cursor(); + +// c1.query(query) will return a TaosQuery object, of which then we can execute. The execute function then returns a promise +// Let's create a database named db +try { + c1.execute('create database if not exists db;'); + //var query = c1.query('create database if not exists db;'); + //query.execute(); +} +catch(err) { + conn.close(); + throw err; +} + +// Now we will use database db. As this query won't return any results, +// we can simplify the code and directly use the c1.execute() function. No need for a TaosQuery object to wrap around the query +try { + c1.execute('use db;'); +} +catch (err) { + conn.close(); + throw err; +} + +// Let's create a table called weather +// which stores some weather data like humidity, AQI (air quality index), temperature, and some notes as text +// We can also immedietely execute a TaosQuery object by passing true as the secodn argument +// This will then return a promise that we can then attach a callback function to +try { + var promise = c1.query('create table if not exists weather (ts timestamp, humidity smallint, aqi int, temperature float, notes binary(30));', true); + promise.then(function(){ + console.log("Table created!"); + }).catch(function() { + console.log("Table couldn't be created.") + }); +} +catch (err) { + conn.close(); + throw err; +} + +// Let's get the description of the table weather +// When using a TaosQuery object and then executing it, upon success it returns a TaosResult object, which is a wrapper around the +// retrieved data and allows us to easily access data and manipulate or display it. +try { + c1.query('describe db.weather;').execute().then(function(result){ + // Result is an instance of TaosResult and has the function pretty() which instantly logs a prettified version to the console + result.pretty(); + }); +} +catch (err) { + conn.close(); + throw err; +} + + +Date.prototype.Format = function(fmt){ + var o = { + 'M+': this.getMonth() + 1, + 'd+': this.getDate(), + 'H+': this.getHours(), + 'm+': this.getMinutes(), + 's+': this.getSeconds(), + 'S+': this.getMilliseconds() + }; + if (/(y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)); + } + for (var k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(String(o[k]).length))); + } + } + return fmt; +} + + +// Let's try to insert some random generated data to test with +// We will use the bind function of the TaosQuery object to easily bind values to question marks in the query +// For Timestamps, a normal Datetime object or TaosTimestamp or milliseconds can be passed in through the bind function +let stime = new Date(); +let interval = 1000; +try { + for (let i = 0; i < 1000; i++) { + stime.setMilliseconds(stime.getMilliseconds() + interval); + + //console.log(stime.Format('yyyy-MM-dd HH:mm:ss.SSS')); + + let insertData = [stime, + parseInt(Math.random()*100), + parseInt(Math.random()*300), + parseFloat(Math.random()*10 + 30), + "Note"]; + //c1.execute('insert into db.weather values(' + insertData.join(',') + ' );'); + + //var query = c1.query('insert into db.weather values(?, ?, ?, ?, ?);').bind(insertData); + //query.execute(); + c1.execute('insert into db.weather values(\"'+stime.Format('yyyy-MM-dd HH:mm:ss.SSS')+'\",'+parseInt(Math.random() * 100)+','+parseInt(Math.random() * 300)+','+parseFloat(Math.random()*10 + 30)+',"Note");'); + } +}catch (err) { + conn.close(); + throw err; +} + +// Now let's look at our newly inserted data +var retrievedData; +try { + c1.query('select * from db.weather limit 5 offset 100;', true).then(function(result){ + //result.pretty(); + console.log('=========>'+JSON.stringify(result)); + // Neat! + }); + +} +catch (err) { + conn.close(); + throw err; +} + +// Let's try running some basic functions +try { + c1.query('select count(*), avg(temperature), max(temperature), min(temperature), stddev(temperature) from db.weather;', true) + .then(function(result) { + result.pretty(); + }) +} +catch(err) { + conn.close(); + throw err; +} + +conn.close(); + +// Feel free to fork this repository or copy this code and start developing your own apps and backends with NodeJS and TDengine! diff --git a/examples/nodejs/nodejsChecker.js b/examples/nodejs/nodejsChecker.js new file mode 100644 index 0000000000000000000000000000000000000000..e634a54ea1c56310bae7d38188590a0d7862f953 --- /dev/null +++ b/examples/nodejs/nodejsChecker.js @@ -0,0 +1,61 @@ +const taos = require('td2.0-connector'); +//const taos = require('../../../src/connector/nodejs/'); + + +var host = null; +var port = 6030; +for(var i = 2; i < global.process.argv.length; i++){ + var key = global.process.argv[i].split("=")[0]; + var value = global.process.argv[i].split("=")[1]; + + if("host" == key){ + host = value; + } + if("port" == key){ + port = value; + } +} + +if(host == null){ + console.log("Usage: node nodejsChecker.js host= port="); + process.exit(0); +} + +// establish connection +var conn = taos.connect({host:host, user:"root", password:"taosdata",port:port}); +var cursor = conn.cursor(); +// create database +executeSql("create database if not exists test", 0); +// use db +executeSql("use test", 0); +// drop table +executeSql("drop table if exists test.weather", 0); +// create table +executeSql("create table if not exists test.weather(ts timestamp, temperature float, humidity int)", 0); +// insert +executeSql("insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)", 1); +// select +executeQuery("select * from test.weather"); +// close connection +conn.close(); + +function executeQuery(sql){ + var start = new Date().getTime(); + var promise = cursor.query(sql, true); + var end = new Date().getTime(); + promise.then(function(result){ + printSql(sql, result != null,(end - start)); + result.pretty(); + }); +} + +function executeSql(sql, affectRows){ + var start = new Date().getTime(); + var promise = cursor.execute(sql); + var end = new Date().getTime(); + printSql(sql, promise == affectRows, (end - start)); +} + +function printSql(sql, succeed, cost){ + console.log("[ "+(succeed ? "OK" : "ERROR!")+" ] time cost: " + cost + " ms, execute statement ====> " + sql); +} diff --git a/examples/nodejs/test1970.js b/examples/nodejs/test1970.js new file mode 100644 index 0000000000000000000000000000000000000000..5177a7371e9a07fa7b548936ff038c1f2a29bc1f --- /dev/null +++ b/examples/nodejs/test1970.js @@ -0,0 +1,125 @@ +const taos = require('td2.0-connector'); +var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}) +var c1 = conn.cursor(); // Initializing a new cursor + +let stime = new Date(); +let interval = 1000; + +function convertDateToTS(date) { + let tsArr = date.toISOString().split("T") + return "\"" + tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length - 1) + "\""; +} + +function R(l, r) { + return Math.random() * (r - l) - r; +} + +function randomBool() { + if (Math.random() < 0.5) { + return true; + } + return false; +} + +// Initialize +const dbname = "nodejs_1970_db"; +const tbname = "t1"; + +let dropDB = "drop database if exists " + dbname +console.log(dropDB);//asdasdasd +c1.execute(dropDB);///asdasd + +let createDB = "create database " + dbname + " keep 36500" +console.log(createDB); +c1.execute(createDB); + +let useTbl = "use " + dbname +console.log(useTbl) +c1.execute(useTbl); + +let createTbl = "create table if not exists " + tbname + "(ts timestamp,id int)" +console.log(createTbl); +c1.execute(createTbl); + +//1969-12-31 23:59:59.999 +//1970-01-01 00:00:00.000 +//1970-01-01 07:59:59.999 +//1970-01-01 08:00:00.000a +//1628928479484 2021-08-14 08:07:59.484 +let sql1 = "insert into " + dbname + "." + tbname + " values('1969-12-31 23:59:59.999',1)" +console.log(sql1); +c1.execute(sql1); + +let sql2 = "insert into " + dbname + "." + tbname + " values('1970-01-01 00:00:00.000',2)" +console.log(sql2); +c1.execute(sql2); + +let sql3 = "insert into " + dbname + "." + tbname + " values('1970-01-01 07:59:59.999',3)" +console.log(sql3); +c1.execute(sql3); + +let sql4 = "insert into " + dbname + "." + tbname + " values('1970-01-01 08:00:00.000',4)" +console.log(sql4); +c1.execute(sql4); + +let sql5 = "insert into " + dbname + "." + tbname + " values('2021-08-14 08:07:59.484',5)" +console.log(sql5); +c1.execute(sql5); + +// Select +let query1 = "select * from " + dbname + "." + tbname +console.log(query1); +c1.execute(query1); + +var d = c1.fetchall(); +console.log(c1.fields); +for (let i = 0; i < d.length; i++) + console.log(d[i][0].valueOf()); + +//initialize +let initSql1 = "drop table if exists " + tbname +console.log(initSql1); +c1.execute(initSql1); + +console.log(createTbl); +c1.execute(createTbl); +c1.execute(useTbl) + +//-28800001 1969-12-31 23:59:59.999 +//-28800000 1970-01-01 00:00:00.000 +//-1 1970-01-01 07:59:59.999 +//0 1970-01-01 08:00:00.00 +//1628928479484 2021-08-14 08:07:59.484 +let sql11 = "insert into " + dbname + "." + tbname + " values(-28800001,11)"; +console.log(sql11); +c1.execute(sql11); + +let sql12 = "insert into " + dbname + "." + tbname + " values(-28800000,12)" +console.log(sql12); +c1.execute(sql12); + +let sql13 = "insert into " + dbname + "." + tbname + " values(-1,13)" +console.log(sql13); +c1.execute(sql13); + +let sql14 = "insert into " + dbname + "." + tbname + " values(0,14)" +console.log(sql14); +c1.execute(sql14); + +let sql15 = "insert into " + dbname + "." + tbname + " values(1628928479484,15)" +console.log(sql15); +c1.execute(sql15); + +// Select +console.log(query1); +c1.execute(query1); + +var d = c1.fetchall(); +console.log(c1.fields); +for (let i = 0; i < d.length; i++) + console.log(d[i][0].valueOf()); + +setTimeout(function () { + conn.close(); +}, 2000); + diff --git a/examples/python/PYTHONConnectorChecker/PythonChecker.py b/examples/python/PYTHONConnectorChecker/PythonChecker.py new file mode 100644 index 0000000000000000000000000000000000000000..d74f021ffcf3aa33c551cc265243b5139c23b757 --- /dev/null +++ b/examples/python/PYTHONConnectorChecker/PythonChecker.py @@ -0,0 +1,114 @@ +import taos +import time +import sys +import getopt +class ConnectorChecker: + def init(self): + self.host = "127.0.0.1" + self.dbName = "test" + self.tbName = "weather" + self.user = "root" + self.password = "taosdata" + + + def sethdt(self,FQDN,dbname,tbname): + if(FQDN): + self.host=FQDN + if(dbname): + self.dbname=dbname + if(tbname): + self.tbName + def printSql(self,sql,elapsed): + print("[ "+"OK"+" ]"+" time cost: %s ms, execute statement ====> %s" + %(elapsed,sql)) + def executeQuery(self,sql): + try: + start=time.time() + execute = self.cl.execute(sql) + elapsed = (time.time()-start)*1000 + self.printSql(sql,elapsed) + data = self.cl.fetchall() + numOfRows = self.cl.rowcount + numOfCols = len(self.cl.description) + for irow in range(numOfRows): + print("Row%d: ts=%s, temperature=%d, humidity=%f" %(irow, data[irow][0], data[irow][1],data[irow][2])) + except Exception as e: + print("Failure sql: %s,exception: %s" %sql,str(e)) + def execute(self,sql): + try: + start=time.time() + execute = self.cl.execute(sql) + elapsed = (time.time()-start)*1000 + self.printSql(sql,elapsed) + + except Exception as e: + print("Failure sql: %s,exception: %s" % + sql,str(e)) + def close(self): + print("connetion closed.") + self.cl.close() + self.conn.close() + def createDatabase(self): + sql="create database if not exists %s" % self.dbName + self.execute(sql) + def useDatabase(self): + sql="use %s" % self.dbName + self.execute(sql) + def createTable(self): + sql="create table if not exists %s.%s (ts timestamp, temperature float, humidity int)"%(self.dbName,self.tbName) + self.execute(sql) + def checkDropTable(self): + sql="drop table if exists " + self.dbName + "." + self.tbName + "" + self.execute(sql) + def checkInsert(self): + sql="insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)" + self.execute(sql) + def checkSelect(self): + sql = "select * from test.weather" + self.executeQuery(sql) + def srun(self): + try: + self.conn = taos.connect(host=self.host,user=self.user,password=self.password) + #self.conn = taos.connect(self.host,self.user,self.password) + except Exception as e: + print("connection failed: %s"%self.host) + exit(1) + print("[ OK ] Connection established.") + self.cl = self.conn.cursor() + +def main(argv): + FQDN='' + dbname='' + tbname='' + try: + opts, args = getopt.getopt(argv,"h:d:t:",["FQDN=","ifile=","ofile="]) + except getopt.GetoptError: + print ('PYTHONConnectorChecker.py -h ') + sys.exit(2) + for opt, arg in opts: + if opt in ("-h", "--FQDN"): + FQDN=arg + elif opt in ("-d", "--dbname"): + dbname = arg + elif opt in ("-t", "--tbname"): + tbname = arg + + checker = ConnectorChecker() + checker.init() + checker.sethdt(FQDN,dbname,tbname) + checker.srun() + checker.createDatabase() + checker.useDatabase() + checker.checkDropTable() + checker.createTable() + checker.checkInsert() + checker.checkSelect() + checker.checkDropTable() + checker.close() + + + +if __name__ == "__main__": + main(sys.argv[1:]) + + diff --git a/examples/python/read_example.py b/examples/python/read_example.py new file mode 100644 index 0000000000000000000000000000000000000000..73052ab2df54fcee8fb01573e23eb7b29ed11712 --- /dev/null +++ b/examples/python/read_example.py @@ -0,0 +1,93 @@ +""" +This is the sample code for TDengine python2 client. +""" +import taos +import sys +import datetime +import random + +def exitProgram(conn): + conn.close() + sys.exit() + +if __name__ == '__main__': + start_time = datetime.datetime(2019, 7, 1) + time_interval = datetime.timedelta(seconds=60) + + # Connect to TDengine server. + # + # parameters: + # @host : TDengine server IP address + # @user : Username used to connect to TDengine server + # @password : Password + # @database : Database to use when connecting to TDengine server + # @config : Configuration directory + if len(sys.argv)>1: + hostname=sys.argv[1] + conn = taos.connect(host=hostname, user="root", password="taosdata", config="/etc/taos") + else: + conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/etc/taos") + + # Generate a cursor object to run SQL commands + c1 = conn.cursor() + # Create a database named db + try: + c1.execute('create database if not exists db ') + except Exception as err: + conn.close() + raise(err) + + # use database + try: + c1.execute('use db') + except Exception as err: + conn.close() + raise(err) + + + # create table + try: + c1.execute('create table if not exists t (ts timestamp, a int, b float, c binary(20))') + except Exception as err: + conn.close() + raise(err) + + # insert data + for i in range(10): + try: + value = c1.execute("insert into t values ('%s', %d, %f, '%s')" % (start_time, random.randint(1,10), random.randint(1,10)/10.0, 'hello')) + #if insert, value is the affected rows + print(value) + except Exception as err: + conn.close() + raise(err) + start_time += time_interval + + # query data and return data in the form of list + try: + c1.execute('select * from db.t') + except Exception as err: + conn.close() + raise(err) + + # Column names are in c1.description list + cols = c1.description + # Use fetchall to fetch data in a list + data = c1.fetchall() + + for col in data: + print(col) + + print('Another query method ') + + try: + c1.execute('select * from db.t') + except Exception as err: + conn.close() + raise(err) + + # Use iterator to go through the retreived data + for col in c1: + print(col) + + conn.close() diff --git a/examples/python/taosdemo/README.md b/examples/python/taosdemo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d48fffe8ff44fb68a1a147a2c97ca057fb360092 --- /dev/null +++ b/examples/python/taosdemo/README.md @@ -0,0 +1,38 @@ +install build environment +=== +/usr/bin/python3 -m pip install -r requirements.txt + +run python version taosdemo +=== +Usage: ./taosdemo.py [OPTION...] + +Author: Shuduo Sang + + -H, --help Show usage. + + -N, --native flag, Use native interface if set. Default is using RESTful interface. + -h, --host host, The host to connect to TDengine. Default is localhost. + -p, --port port, The TCP/IP port number to use for the connection. Default is 0. + -u, --user user, The user name to use when connecting to the server. Default is 'root'. + -P, --password password, The password to use when connecting to the server. Default is 'taosdata'. + -l, --colsPerRec num_of_columns_per_record, The number of columns per record. Default is 3. + -d, --dbname database, Destination database. Default is 'test'. + -a, --replica replica, Set the replica parameters of the database, Default 1, min: 1, max: 5. + -m, --tbname
table_prefix, Table prefix name. Default is 't'. + -M, --stable flag, Use super table. Default is no + -s, --stbname stable_prefix, STable prefix name. Default is 'st' + -Q, --query query, Execute query command. set 'DEFAULT' means select * from each table + -T, --threads num_of_threads, The number of threads. Default is 1. + -C, --processes num_of_processes, The number of threads. Default is 1. + -r, --batch num_of_records_per_req, The number of records per request. Default is 1000. + -t, --numOfTb num_of_tables, The number of tables. Default is 1. + -n, --numOfRec num_of_records_per_table, The number of records per table. Default is 1. + -c, --config config_directory, Configuration directory. Default is '/etc/taos/'. + -x, --inserOnly flag, Insert only flag. + -O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order. + -R, --rateOOOO rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50. + -D, --deleteMethod Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database. + -v, --verbose Print verbose output + -g, --debug Print debug output + -y, --skipPrompt Skip read key for continous test, default is not skip + diff --git a/examples/python/taosdemo/requirements.txt b/examples/python/taosdemo/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..977e8e3726a446e85635764fe9243a3c5416ea0f --- /dev/null +++ b/examples/python/taosdemo/requirements.txt @@ -0,0 +1,28 @@ +## +######## example-requirements.txt ####### +## +####### Requirements without Version Specifiers ###### +requests +multipledispatch +#beautifulsoup4 +## +####### Requirements with Version Specifiers ###### +## See https://www.python.org/dev/peps/pep-0440/#version-specifiers +#docopt == 0.6.1 # Version Matching. Must be version 0.6.1 +#keyring >= 4.1.1 # Minimum version 4.1.1 +#coverage != 3.5 # Version Exclusion. Anything except version 3.5 +#Mopidy-Dirble ~= 1.1 # Compatible release. Same as >= 1.1, == 1.* +## +####### Refer to other requirements files ###### +#-r other-requirements.txt +## +## +####### A particular file ###### +#./downloads/numpy-1.9.2-cp34-none-win32.whl +#http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl +## +####### Additional Requirements without Version Specifiers ###### +## Same as 1st section, just here to show that you can put things in any order. +#rejected +#green +## diff --git a/examples/python/taosdemo/taosdemo.py b/examples/python/taosdemo/taosdemo.py new file mode 100755 index 0000000000000000000000000000000000000000..4aaf00157c5fe5bbeec27b001f663a94c1d89439 --- /dev/null +++ b/examples/python/taosdemo/taosdemo.py @@ -0,0 +1,817 @@ +#!/usr/bin/python3 +# * Copyright (c) 2019 TAOS Data, Inc. +# * +# * 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 . + +# -*- coding: utf-8 -*- + +import sys +import getopt +import requests +import json +import random +import time +import datetime +import multiprocessing +from multiprocessing import Manager, Pool, Lock +from multipledispatch import dispatch +from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED + + +@dispatch(str, str) +def v_print(msg, arg): + # type: (str, str) -> None + if verbose: + print(msg % arg) + + +@dispatch(str, str, str) +def v_print(msg, arg1, arg2): + # type: (str, str, str) -> None + if verbose: + print(msg % (arg1, arg2)) + + +@dispatch(str, str, str, str) +def v_print(msg, arg1, arg2, arg3): + # type: (str, str, str, str) -> None + if verbose: + print(msg % (arg1, arg2, arg3)) + + +@dispatch(str, str, str, str, str) +def v_print(msg, arg1, arg2, arg3, arg4): + # type: (str, str, str, str, str) -> None + if verbose: + print(msg % (arg1, arg2, arg3, arg4)) + + +@dispatch(str, int) +def v_print(msg, arg): + # type: (str, int) -> None + if verbose: + print(msg % int(arg)) + + +@dispatch(str, int, str) +def v_print(msg, arg1, arg2): + # type: (str, int, str) -> None + if verbose: + print(msg % (int(arg1), str(arg2))) + + +@dispatch(str, str, int) +def v_print(msg, arg1, arg2): + # type: (str, str, int) -> None + if verbose: + print(msg % (arg1, int(arg2))) + + +@dispatch(str, int, int) +def v_print(msg, arg1, arg2): + # type: (str, int, int) -> None + if verbose: + print(msg % (int(arg1), int(arg2))) + + +@dispatch(str, int, int, str) +def v_print(msg, arg1, arg2, arg3): + # type: (str, int, int, str) -> None + if verbose: + print(msg % (int(arg1), int(arg2), str(arg3))) + + +@dispatch(str, int, int, int) +def v_print(msg, arg1, arg2, arg3): + # type: (str, int, int, int) -> None + if verbose: + print(msg % (int(arg1), int(arg2), int(arg3))) + + +@dispatch(str, int, int, int, int) +def v_print(msg, arg1, arg2, arg3, arg4): + # type: (str, int, int, int, int) -> None + if verbose: + print(msg % (int(arg1), int(arg2), int(arg3), int(arg4))) + + +def restful_execute(host, port, user, password, cmd): + # type: (str, int, str, str, str) -> None + url = "http://%s:%d/rest/sql" % (host, restPort) + + v_print("restful_execute - cmd: %s", cmd) + + resp = requests.post(url, cmd, auth=(user, password)) + + v_print("resp status: %d", resp.status_code) + + if debug: + v_print( + "resp text: %s", + json.dumps( + resp.json(), + sort_keys=True, + indent=2)) + else: + print("resp: %s" % json.dumps(resp.json())) + + +def query_func(process, thread, cmd): + # type: (int, int, str) -> None + v_print("%d process %d thread cmd: %s", process, thread, cmd) + + if oneMoreHost != "NotSupported" and random.randint( + 0, 1) == 1: + v_print("%s", "Send to second host") + if native: + cursor2.execute(cmd) + else: + restful_execute( + oneMoreHost, port, user, password, cmd) + else: + v_print("%s%s%s", "Send ", cmd, " to the host") + if native: + pass +# cursor.execute(cmd) + else: + restful_execute( + host, port, user, password, cmd) + + +def query_data_process(cmd): + # type: (str) -> None + # establish connection if native + if native: + v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir) + try: + conn = taos.connect( + host=host, + user=user, + password=password, + config=configDir) + v_print("conn: %s", str(conn.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + sys.exit(1) + + try: + cursor = conn.cursor() + v_print("cursor:%d %s", id(cursor), str(cursor.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + conn.close() + sys.exit(1) + + if native: + try: + cursor.execute(cmd) + cols = cursor.description + data = cursor.fetchall() + + for col in data: + print(col) + except Exception as e: + conn.close() + print("Error: %s" % e.args[0]) + sys.exit(1) + + else: + restful_execute( + host, + port, + user, + password, + cmd) + + if native: + cursor.close() + conn.close() + + +def create_stb(): + for i in range(0, numOfStb): + if native: + cursor.execute( + "CREATE TABLE IF NOT EXISTS %s%d (ts timestamp, value float) TAGS (uuid binary(50))" % + (stbName, i)) + else: + restful_execute( + host, + port, + user, + password, + "CREATE TABLE IF NOT EXISTS %s%d (ts timestamp, value float) TAGS (uuid binary(50))" % + (stbName, i) + ) + + +def use_database(): + + if native: + cursor.execute("USE %s" % current_db) + else: + restful_execute(host, port, user, password, "USE %s" % current_db) + + +def create_databases(): + for i in range(0, numOfDb): + v_print("will create database db%d", int(i)) + + if native: + cursor.execute( + "CREATE DATABASE IF NOT EXISTS %s%d" % (dbName, i)) + else: + restful_execute( + host, + port, + user, + password, + "CREATE DATABASE IF NOT EXISTS %s%d" % (dbName, i)) + + +def drop_tables(): + # TODO + v_print("TODO: drop tables total %d", numOfTb) + pass + + +def drop_stable(): + # TODO + v_print("TODO: drop stables total %d", numOfStb) + pass + + +def drop_databases(): + v_print("drop databases total %d", numOfDb) + + # drop exist databases first + for i in range(0, numOfDb): + v_print("will drop database db%d", int(i)) + + if native: + cursor.execute( + "DROP DATABASE IF EXISTS %s%d" % + (dbName, i)) + else: + restful_execute( + host, + port, + user, + password, + "DROP DATABASE IF EXISTS %s%d" % + (dbName, i)) + + +def insert_func(process, thread): + # type: (int, int) -> None + v_print("%d process %d thread, insert_func ", process, thread) + + # generate uuid + uuid_int = random.randint(0, numOfTb + 1) + uuid = "%s" % uuid_int + v_print("uuid is: %s", uuid) + + # establish connection if native + if native: + v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir) + try: + conn = taos.connect( + host=host, + user=user, + password=password, + config=configDir) + v_print("conn: %s", str(conn.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + sys.exit(1) + + try: + cursor = conn.cursor() + v_print("cursor:%d %s", id(cursor), str(cursor.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + conn.close() + sys.exit(1) + + v_print("numOfRec %d:", numOfRec) + + row = 0 + while row < numOfRec: + v_print("row: %d", row) + sqlCmd = ['INSERT INTO '] + try: + sqlCmd.append( + "%s.%s%d " % (current_db, tbName, thread)) + + if (numOfStb > 0 and autosubtable): + sqlCmd.append("USING %s.%s%d TAGS('%s') " % + (current_db, stbName, numOfStb - 1, uuid)) + + start_time = datetime.datetime( + 2021, 1, 25) + datetime.timedelta(seconds=row) + + sqlCmd.append("VALUES ") + for batchIter in range(0, batch): + sqlCmd.append("('%s', %f) " % + ( + start_time + + datetime.timedelta( + milliseconds=batchIter), + random.random())) + row = row + 1 + if row >= numOfRec: + v_print("BREAK, row: %d numOfRec:%d", row, numOfRec) + break + + except Exception as e: + print("Error: %s" % e.args[0]) + + cmd = ' '.join(sqlCmd) + + if measure: + exec_start_time = datetime.datetime.now() + + if native: + affectedRows = cursor.execute(cmd) + else: + restful_execute( + host, port, user, password, cmd) + + if measure: + exec_end_time = datetime.datetime.now() + exec_delta = exec_end_time - exec_start_time + v_print( + "consume %d microseconds", + exec_delta.microseconds) + + v_print("cmd: %s, length:%d", cmd, len(cmd)) + + if native: + cursor.close() + conn.close() + + +def create_tb_using_stb(): + # TODO: + pass + + +def create_tb(): + v_print("create_tb() numOfTb: %d", numOfTb) + for i in range(0, numOfDb): + if native: + cursor.execute("USE %s%d" % (dbName, i)) + else: + restful_execute( + host, port, user, password, "USE %s%d" % + (dbName, i)) + + for j in range(0, numOfTb): + if native: + cursor.execute( + "CREATE TABLE %s%d (ts timestamp, value float)" % + (tbName, j)) + else: + restful_execute( + host, + port, + user, + password, + "CREATE TABLE %s%d (ts timestamp, value float)" % + (tbName, j)) + + +def insert_data_process(lock, i, begin, end): + # type: (multiprocessing._LockType, int, int, int) -> None + lock.acquire() + tasks = end - begin + v_print("insert_data_process:%d table from %d to %d, tasks %d", i, begin, end, tasks) + + if (threads < (end - begin)): + for j in range(begin, end, threads): + with ThreadPoolExecutor(max_workers=threads) as executor: + k = end if ((j + threads) > end) else (j + threads) + workers = [ + executor.submit( + insert_func, + i, + n) for n in range( + j, + k)] + wait(workers, return_when=ALL_COMPLETED) + else: + with ThreadPoolExecutor(max_workers=threads) as executor: + workers = [ + executor.submit( + insert_func, + i, + j) for j in range( + begin, + end)] + wait(workers, return_when=ALL_COMPLETED) + + lock.release() + + +def query_db(i): + if native: + cursor.execute("USE %s%d" % (dbName, i)) + else: + restful_execute( + host, port, user, password, "USE %s%d" % + (dbName, i)) + + for j in range(0, numOfTb): + if native: + cursor.execute( + "SELECT COUNT(*) FROM %s%d" % (tbName, j)) + else: + restful_execute( + host, port, user, password, "SELECT COUNT(*) FROM %s%d" % + (tbName, j)) + + +def printConfig(): + + print("###################################################################") + print("# Use native interface: %s" % native) + print("# Server IP: %s" % host) + if native: + print("# Server port: %s" % port) + else: + print("# Server port: %s" % restPort) + + print("# Configuration Dir: %s" % configDir) + print("# User: %s" % user) + print("# Password: %s" % password) + print("# Number of Columns per record: %s" % colsPerRecord) + print("# Number of Threads: %s" % threads) + print("# Number of Processes: %s" % processes) + print("# Number of Tables: %s" % numOfTb) + print("# Number of records per Table: %s" % numOfRec) + print("# Records/Request: %s" % batch) + print("# Database name: %s" % dbName) + print("# Replica: %s" % replica) + print("# Use STable: %s" % useStable) + print("# Table prefix: %s" % tbName) + if useStable: + print("# STable prefix: %s" % stbName) + + print("# Data order: %s" % outOfOrder) + print("# Data out of order rate: %s" % rateOOOO) + print("# Delete method: %s" % deleteMethod) + print("# Query command: %s" % queryCmd) + print("# Insert Only: %s" % insertOnly) + print("# Verbose output %s" % verbose) + print("# Test time: %s" % + datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")) + print("###################################################################") + + +if __name__ == "__main__": + + native = False + verbose = False + debug = False + measure = True + dropDbOnly = False + colsPerRecord = 3 + numOfDb = 1 + dbName = "test" + replica = 1 + batch = 1 + numOfTb = 1 + tbName = "tb" + useStable = False + numOfStb = 0 + stbName = "stb" + numOfRec = 10 + ieration = 1 + host = "127.0.0.1" + configDir = "/etc/taos" + oneMoreHost = "NotSupported" + port = 6030 + restPort = 6041 + user = "root" + defaultPass = "taosdata" + processes = 1 + threads = 1 + insertOnly = False + autosubtable = False + queryCmd = "NO" + outOfOrder = 0 + rateOOOO = 0 + deleteMethod = 0 + skipPrompt = False + + try: + opts, args = getopt.gnu_getopt(sys.argv[1:], + 'Nh:p:u:P:d:a:m:Ms:Q:T:C:r:l:t:n:c:xOR:D:vgyH', + [ + 'native', 'host', 'port', 'user', 'password', 'dbname', 'replica', 'tbname', + 'stable', 'stbname', 'query', 'threads', 'processes', + 'recPerReq', 'colsPerRecord', 'numOfTb', 'numOfRec', 'config', + 'insertOnly', 'outOfOrder', 'rateOOOO', 'deleteMethod', + 'verbose', 'debug', 'skipPrompt', 'help' + ]) + except getopt.GetoptError as err: + print('ERROR:', err) + print('Try `taosdemo.py --help` for more options.') + sys.exit(1) + + if bool(opts) is False: + print('Try `taosdemo.py --help` for more options.') + sys.exit(1) + + for key, value in opts: + if key in ['-H', '--help']: + print('') + print( + 'taosdemo.py for TDengine') + print('') + print('Author: Shuduo Sang ') + print('') + + print('\t-H, --help Show usage.') + print('') + + print('\t-N, --native flag, Use native interface if set. Default is using RESTful interface.') + print('\t-h, --host host, The host to connect to TDengine. Default is localhost.') + print('\t-p, --port port, The TCP/IP port number to use for the connection. Default is 0.') + print('\t-u, --user user, The user name to use when connecting to the server. Default is \'root\'.') + print('\t-P, --password password, The password to use when connecting to the server. Default is \'taosdata\'.') + print('\t-l, --colsPerRec num_of_columns_per_record, The number of columns per record. Default is 3.') + print( + '\t-d, --dbname database, Destination database. Default is \'test\'.') + print('\t-a, --replica replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.') + print( + '\t-m, --tbname
table_prefix, Table prefix name. Default is \'t\'.') + print( + '\t-M, --stable flag, Use super table. Default is no') + print( + '\t-s, --stbname stable_prefix, STable prefix name. Default is \'st\'') + print('\t-Q, --query [NO|EACHTB|command] query, Execute query command. set \'EACHTB\' means select * from each table') + print( + '\t-T, --threads num_of_threads, The number of threads. Default is 1.') + print( + '\t-C, --processes num_of_processes, The number of threads. Default is 1.') + print('\t-r, --batch num_of_records_per_req, The number of records per request. Default is 1000.') + print( + '\t-t, --numOfTb num_of_tables, The number of tables. Default is 1.') + print('\t-n, --numOfRec num_of_records_per_table, The number of records per table. Default is 1.') + print('\t-c, --config config_directory, Configuration directory. Default is \'/etc/taos/\'.') + print('\t-x, --inserOnly flag, Insert only flag.') + print('\t-O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order.') + print('\t-R, --rateOOOO rate, Out of order data\'s rate--if order=1 Default 10, min: 0, max: 50.') + print('\t-D, --deleteMethod Delete data methods 0: don\'t delete, 1: delete by table, 2: delete by stable, 3: delete by database.') + print('\t-v, --verbose Print verbose output') + print('\t-g, --debug Print debug output') + print( + '\t-y, --skipPrompt Skip read key for continous test, default is not skip') + print('') + sys.exit(0) + + if key in ['-N', '--native']: + try: + import taos + except Exception as e: + print("Error: %s" % e.args[0]) + sys.exit(1) + native = True + + if key in ['-h', '--host']: + host = value + + if key in ['-p', '--port']: + port = int(value) + + if key in ['-u', '--user']: + user = value + + if key in ['-P', '--password']: + password = value + else: + password = defaultPass + + if key in ['-d', '--dbname']: + dbName = value + + if key in ['-a', '--replica']: + replica = int(value) + if replica < 1: + print("FATAL: number of replica need > 0") + sys.exit(1) + + if key in ['-m', '--tbname']: + tbName = value + + if key in ['-M', '--stable']: + useStable = True + numOfStb = 1 + + if key in ['-s', '--stbname']: + stbName = value + + if key in ['-Q', '--query']: + queryCmd = str(value) + + if key in ['-T', '--threads']: + threads = int(value) + if threads < 1: + print("FATAL: number of threads must be larger than 0") + sys.exit(1) + + if key in ['-C', '--processes']: + processes = int(value) + if processes < 1: + print("FATAL: number of processes must be larger than 0") + sys.exit(1) + + if key in ['-r', '--batch']: + batch = int(value) + + if key in ['-l', '--colsPerRec']: + colsPerRec = int(value) + + if key in ['-t', '--numOfTb']: + numOfTb = int(value) + v_print("numOfTb is %d", numOfTb) + + if key in ['-n', '--numOfRec']: + numOfRec = int(value) + v_print("numOfRec is %d", numOfRec) + if numOfRec < 1: + print("FATAL: number of records must be larger than 0") + sys.exit(1) + + + if key in ['-c', '--config']: + configDir = value + v_print("config dir: %s", configDir) + + if key in ['-x', '--insertOnly']: + insertOnly = True + v_print("insert only: %d", insertOnly) + + if key in ['-O', '--outOfOrder']: + outOfOrder = int(value) + v_print("out of order is %d", outOfOrder) + + if key in ['-R', '--rateOOOO']: + rateOOOO = int(value) + v_print("the rate of out of order is %d", rateOOOO) + + if key in ['-D', '--deleteMethod']: + deleteMethod = int(value) + if (deleteMethod < 0) or (deleteMethod > 3): + print( + "inputed delete method is %d, valid value is 0~3, set to default 0" % + deleteMethod) + deleteMethod = 0 + v_print("the delete method is %d", deleteMethod) + + if key in ['-v', '--verbose']: + verbose = True + + if key in ['-g', '--debug']: + debug = True + + if key in ['-y', '--skipPrompt']: + skipPrompt = True + + if verbose: + printConfig() + + if not skipPrompt: + try: + input("Press any key to continue..") + except SyntaxError: + pass + + # establish connection first if native + if native: + v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir) + try: + conn = taos.connect( + host=host, + user=user, + password=password, + config=configDir) + v_print("conn: %s", str(conn.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + sys.exit(1) + + try: + cursor = conn.cursor() + v_print("cursor:%d %s", id(cursor), str(cursor.__class__)) + except Exception as e: + print("Error: %s" % e.args[0]) + conn.close() + sys.exit(1) + + # drop data only if delete method be set + if deleteMethod > 0: + if deleteMethod == 1: + drop_tables() + print("Drop tables done.") + elif deleteMethod == 2: + drop_stables() + print("Drop super tables done.") + elif deleteMethod == 3: + drop_databases() + print("Drop Database done.") + sys.exit(0) + + # create databases + drop_databases() + create_databases() + + # use last database + current_db = "%s%d" % (dbName, (numOfDb - 1)) + use_database() + + if measure: + start_time_begin = time.time() + + if numOfStb > 0: + create_stb() + if (autosubtable == False): + create_tb_using_stb() + else: + create_tb() + + if measure: + end_time = time.time() + print( + "Total time consumed {} seconds for create table.".format( + (end_time - start_time_begin))) + + if native: + cursor.close() + conn.close() + + # start insert data + if measure: + start_time = time.time() + + manager = Manager() + lock = manager.Lock() + pool = Pool(processes) + + begin = 0 + end = 0 + + quotient = numOfTb // processes + if quotient < 1: + processes = numOfTb + quotient = 1 + + remainder = numOfTb % processes + v_print( + "num of tables: %d, quotient: %d, remainder: %d", + numOfTb, + quotient, + remainder) + + for i in range(processes): + begin = end + + if i < remainder: + end = begin + quotient + 1 + else: + end = begin + quotient + pool.apply_async(insert_data_process, args=(lock, i, begin, end,)) + + pool.close() + pool.join() + time.sleep(1) + + if measure: + end_time = time.time() + print( + "Total time consumed {} seconds for insert data.".format( + (end_time - start_time))) + + + # query data + if queryCmd != "NO": + print("queryCmd: %s" % queryCmd) + query_data_process(queryCmd) + + if measure: + end_time = time.time() + print( + "Total time consumed {} seconds.".format( + (end_time - start_time_begin))) + + print("done") diff --git a/packaging/deb/makedeb.sh b/packaging/deb/makedeb.sh index 83907ff5753871059ffa0fb64a089e29d2de79ee..9e15c06612b50a04a59a3226f3bf7e6789431333 100755 --- a/packaging/deb/makedeb.sh +++ b/packaging/deb/makedeb.sh @@ -69,7 +69,7 @@ cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_pat cp ${compile_dir}/../src/inc/taos.h ${pkg_dir}${install_home_path}/include cp ${compile_dir}/../src/inc/taosdef.h ${pkg_dir}${install_home_path}/include cp ${compile_dir}/../src/inc/taoserror.h ${pkg_dir}${install_home_path}/include -cp -r ${top_dir}/tests/examples/* ${pkg_dir}${install_home_path}/examples +cp -r ${top_dir}/examples/* ${pkg_dir}${install_home_path}/examples #cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector #cp -r ${top_dir}/src/connector/go ${pkg_dir}${install_home_path}/connector #cp -r ${top_dir}/src/connector/nodejs ${pkg_dir}${install_home_path}/connector diff --git a/packaging/rpm/tdengine.spec b/packaging/rpm/tdengine.spec index 3fcc422a5fdf0d28fd3b9187ef7d2699401a846f..3992f7b6a867b7aacc9b479820c20dd7745dd54f 100644 --- a/packaging/rpm/tdengine.spec +++ b/packaging/rpm/tdengine.spec @@ -79,7 +79,7 @@ cp %{_compiledir}/../src/inc/taoserror.h %{buildroot}%{homepath}/incl #cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector #cp -r %{_compiledir}/../src/connector/nodejs %{buildroot}%{homepath}/connector #cp %{_compiledir}/build/lib/taos-jdbcdriver*.* %{buildroot}%{homepath}/connector ||: -cp -r %{_compiledir}/../tests/examples/* %{buildroot}%{homepath}/examples +cp -r %{_compiledir}/../examples/* %{buildroot}%{homepath}/examples if [ -f %{_compiledir}/build/bin/jemalloc-config ]; then mkdir -p %{buildroot}%{userlocalpath}/bin diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh index 42c7cbc80862e960c8a2a48ea7c291ae1cca82ee..91c0c4389ab76fb1e7b33f59ddd217bd6cbf7044 100755 --- a/packaging/tools/make_install.sh +++ b/packaging/tools/make_install.sh @@ -430,9 +430,9 @@ function install_connector() { function install_examples() { if [ "$osType" != "Darwin" ]; then - ${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_dir}/examples + ${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples else - ${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_dir}/examples || ${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_2_dir}/examples + ${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples || ${csudo}cp -rf ${source_dir}/examples/* ${install_main_2_dir}/examples fi } diff --git a/packaging/tools/makeclient.sh b/packaging/tools/makeclient.sh index 7346960763f09b2a828495ecf1d73e904167d694..f1a9d30c917e3b358eaa26d259ef2fffd1bc5126 100755 --- a/packaging/tools/makeclient.sh +++ b/packaging/tools/makeclient.sh @@ -134,7 +134,7 @@ chmod a+x ${install_dir}/install_client.sh # Copy example code mkdir -p ${install_dir}/examples -examples_dir="${top_dir}/tests/examples" +examples_dir="${top_dir}/examples" cp -r ${examples_dir}/c ${install_dir}/examples if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then cp -r ${examples_dir}/JDBC ${install_dir}/examples diff --git a/packaging/tools/makepkg.sh b/packaging/tools/makepkg.sh index 8a8748a5a92feda427a92b369a330733ebcbba60..13ab6f13543dd991a1891bde3df95e58378c8a3f 100755 --- a/packaging/tools/makepkg.sh +++ b/packaging/tools/makepkg.sh @@ -242,7 +242,7 @@ chmod a+x ${install_dir}/install.sh # Copy example code mkdir -p ${install_dir}/examples -examples_dir="${top_dir}/tests/examples" +examples_dir="${top_dir}/examples" cp -r ${examples_dir}/c ${install_dir}/examples if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then if [ -d ${examples_dir}/JDBC/connectionPools/target ]; then