refactor and c test case
This commit is contained in:
parent
f8c905211a
commit
5c81c19808
|
@ -42,12 +42,18 @@ do {
|
|||
obj->err.err_no = eno; \
|
||||
const char* estr = tstrerror(eno); \
|
||||
if (!estr) estr = "Unknown error"; \
|
||||
int n = snprintf(NULL, 0, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \
|
||||
int n = snprintf(NULL, 0, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \
|
||||
eno, estr, \
|
||||
basename((char*)__FILE__), __LINE__, \
|
||||
##__VA_ARGS__); \
|
||||
if (n<0) break; \
|
||||
char *err_str = (char*)realloc(obj->err.err_str, n+1); \
|
||||
if (!err_str) break; \
|
||||
obj->err.err_str = err_str; \
|
||||
snprintf(obj->err.err_str, n+1, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \
|
||||
snprintf(obj->err.err_str, n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \
|
||||
eno, estr, \
|
||||
basename((char*)__FILE__), __LINE__, \
|
||||
##__VA_ARGS__); \
|
||||
snprintf((char*)obj->err.sql_state, sizeof(obj->err.sql_state), "%s", sqlstate); \
|
||||
} while (0)
|
||||
|
||||
|
@ -410,6 +416,19 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
|
|||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
NameLength1 = (NameLength1==SQL_NTS) ? strlen((const char*)ServerName) : NameLength1;
|
||||
NameLength2 = (NameLength2==SQL_NTS) ? strlen((const char*)UserName) : NameLength2;
|
||||
NameLength3 = (NameLength3==SQL_NTS) ? strlen((const char*)Authentication) : NameLength3;
|
||||
|
||||
if (NameLength1 < 0 || NameLength2 < 0 || NameLength3 < 0) {
|
||||
SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, "");
|
||||
return SQL_ERROR;
|
||||
}
|
||||
if (NameLength1>SQL_MAX_DSN_LENGTH) {
|
||||
SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, "");
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
const char *serverName = SDUP(ServerName, NameLength1);
|
||||
const char *userName = SDUP(UserName, NameLength2);
|
||||
const char *auth = SDUP(Authentication, NameLength3);
|
||||
|
|
|
@ -52,6 +52,20 @@ static void buf_clean(buf_t *buf) {
|
|||
}
|
||||
}
|
||||
|
||||
const char* tsdb_conv_code_str(TSDB_CONV_CODE code) {
|
||||
switch (code) {
|
||||
case TSDB_CONV_OK: return "TSDB_CONV_OK";
|
||||
case TSDB_CONV_OOM: return "TSDB_CONV_OOM";
|
||||
case TSDB_CONV_OOR: return "TSDB_CONV_OOR";
|
||||
case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION";
|
||||
case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC";
|
||||
case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM";
|
||||
case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL";
|
||||
case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR";
|
||||
default: return "UNKNOWN";
|
||||
};
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) {
|
||||
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ typedef enum {
|
|||
TSDB_CONV_BAD_CHAR,
|
||||
} TSDB_CONV_CODE;
|
||||
|
||||
const char* tsdb_conv_code_str(TSDB_CONV_CODE code);
|
||||
|
||||
TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen);
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _todbc_log_h_
|
||||
#define _todbc_log_h_
|
||||
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define D(fmt, ...) \
|
||||
fprintf(stderr, \
|
||||
"%s[%d]:%s() " fmt "\n", \
|
||||
basename((char*)__FILE__), __LINE__, __func__, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define DASSERT(statement) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s", #statement); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#define DASSERTX(statement, fmt, ...) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#endif // _todbc_log_h_
|
||||
|
|
@ -16,32 +16,11 @@
|
|||
#ifndef _TODBC_UTIL_H_
|
||||
#define _TODBC_UTIL_H_
|
||||
|
||||
#include <libgen.h>
|
||||
#include "todbc_log.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sql.h>
|
||||
|
||||
#define D(fmt, ...) \
|
||||
fprintf(stderr, \
|
||||
"%s[%d]:%s() " fmt "\n", \
|
||||
basename((char*)__FILE__), __LINE__, __func__, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define DASSERT(statement) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s", #statement); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#define DASSERTX(statement, fmt, ...) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
const char* sql_sql_type(int type);
|
||||
const char* sql_c_type(int type);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <libgen.h>
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
|
||||
|
@ -5,11 +6,20 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "../src/todbc_log.h"
|
||||
|
||||
// static const char *dsn = "TAOS_DSN";
|
||||
// static const char *uid = "root";
|
||||
// static const char *pwd = "taosdata";
|
||||
|
||||
#define CHK_TEST(statement) \
|
||||
do { \
|
||||
D("testing: %s", #statement); \
|
||||
int r = (statement); \
|
||||
if (r) return 1; \
|
||||
} while (0);
|
||||
|
||||
|
||||
typedef struct data_s data_t;
|
||||
struct data_s {
|
||||
int64_t ts;
|
||||
|
@ -37,7 +47,7 @@ static const char *pro_stmts[] = {
|
|||
// "drop database db"
|
||||
};
|
||||
|
||||
#define CHK_RESULT(r, ht, h) \
|
||||
#define CHK_RESULT(r, ht, h, fmt, ...) \
|
||||
do { \
|
||||
if (r==0) break; \
|
||||
SQLCHAR ss[10]; \
|
||||
|
@ -48,23 +58,124 @@ do {
|
|||
es[0] = '\0'; \
|
||||
SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \
|
||||
if (ret) break; \
|
||||
fprintf(stderr, "%s%s\n", ss, es); \
|
||||
D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) {
|
||||
SQLRETURN r;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
r = SQLAllocEnv(&env);
|
||||
if (r!=SQL_SUCCESS) return 1;
|
||||
do {
|
||||
r = SQLAllocConnect(env, &conn);
|
||||
CHK_RESULT(r, SQL_HANDLE_ENV, env, "");
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn),
|
||||
(SQLCHAR*)uid, strlen(uid),
|
||||
(SQLCHAR*)pwd, strlen(pwd));
|
||||
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
|
||||
if (r==SQL_SUCCESS) {
|
||||
*pEnv = env;
|
||||
*pConn = conn;
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
SQLFreeConnect(conn);
|
||||
} while (0);
|
||||
SQLFreeEnv(env);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) {
|
||||
SQLRETURN r;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
r = SQLAllocEnv(&env);
|
||||
if (r!=SQL_SUCCESS) return 1;
|
||||
do {
|
||||
r = SQLAllocConnect(env, &conn);
|
||||
CHK_RESULT(r, SQL_HANDLE_ENV, env, "");
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
SQLCHAR buf[4096];
|
||||
SQLSMALLINT blen = 0;
|
||||
SQLHDBC ConnectionHandle = conn;
|
||||
SQLHWND WindowHandle = NULL;
|
||||
SQLCHAR * InConnectionString = (SQLCHAR*)connstr;
|
||||
SQLSMALLINT StringLength1 = strlen(connstr);
|
||||
SQLCHAR * OutConnectionString = buf;
|
||||
SQLSMALLINT BufferLength = sizeof(buf);
|
||||
SQLSMALLINT * StringLength2Ptr = &blen;
|
||||
SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT;
|
||||
r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString,
|
||||
StringLength1, OutConnectionString, BufferLength,
|
||||
StringLength2Ptr, DriverCompletion);
|
||||
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
|
||||
if (r==SQL_SUCCESS) {
|
||||
*pEnv = env;
|
||||
*pConn = conn;
|
||||
return 0;
|
||||
}
|
||||
} while (0);
|
||||
SQLFreeConnect(conn);
|
||||
} while (0);
|
||||
SQLFreeEnv(env);
|
||||
|
||||
return 1;
|
||||
}
|
||||
static int do_statement(SQLHSTMT stmt, const char *statement) {
|
||||
SQLRETURN r = 0;
|
||||
do {
|
||||
fprintf(stderr, "prepare [%s]\n", statement);
|
||||
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
r = SQLExecDirect(stmt, (SQLCHAR*)statement, SQL_NTS);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: [%s]", statement);
|
||||
if (r) break;
|
||||
fprintf(stderr, "execute [%s]\n", statement);
|
||||
r = SQLExecute(stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
SQLSMALLINT cols = 0;
|
||||
r = SQLNumResultCols(stmt, &cols);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
|
||||
if (r) break;
|
||||
fprintf(stderr, "done\n");
|
||||
if (cols <= 0) break;
|
||||
char buf[4096];
|
||||
while (1) {
|
||||
SQLRETURN r = SQLFetch(stmt);
|
||||
if (r==SQL_NO_DATA) break;
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
|
||||
for (size_t i=0; i<cols; ++i) {
|
||||
SQLLEN soi = 0;
|
||||
r = SQLGetData(stmt, i+1, SQL_C_CHAR, buf, sizeof(buf), &soi);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
|
||||
if (r) {
|
||||
if (r!=SQL_SUCCESS_WITH_INFO) {
|
||||
if (i>0) fprintf(stdout, "\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if (soi==SQL_NULL_DATA) {
|
||||
fprintf(stdout, "%snull", i==0?"":",");
|
||||
} else {
|
||||
fprintf(stdout, "%s\"%s\"", i==0?"":",", buf);
|
||||
}
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
// r = SQLFetch(stmt);
|
||||
// if (r==SQL_NO_DATA) {
|
||||
// D("..........");
|
||||
// r = SQL_SUCCESS;
|
||||
// break;
|
||||
// }
|
||||
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
|
||||
// if (r) break;
|
||||
// r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
|
||||
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
|
||||
// if (r) break;
|
||||
// r = SQLExecute(stmt);
|
||||
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
// if (r) break;
|
||||
} while (0);
|
||||
fprintf(stderr, "r: [%x][%d]\n", r, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -77,155 +188,344 @@ static int do_insert(SQLHSTMT stmt, data_t data) {
|
|||
int ignored = 0;
|
||||
|
||||
do {
|
||||
fprintf(stderr, "prepare [%s]\n", statement);
|
||||
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 1 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 2 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 3 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 4 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 5 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 6 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 7 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 8 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 9 [%s]\n", statement);
|
||||
lbin = SQL_NTS;
|
||||
r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 10 [%s]\n", statement);
|
||||
lblob = SQL_NTS;
|
||||
r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "execute [%s]\n", statement);
|
||||
r = SQLExecute(stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
|
||||
if (r) break;
|
||||
|
||||
// ts += 1;
|
||||
// v = 2;
|
||||
// fprintf(stderr, "execute [%s]\n", statement);
|
||||
// r = SQLExecute(stmt);
|
||||
// if (r) break;
|
||||
|
||||
fprintf(stderr, "done\n");
|
||||
} while (0);
|
||||
fprintf(stderr, "r: [%x][%d]\n", r, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 4) return 1;
|
||||
const char *dsn = argv[1];
|
||||
const char *uid = argv[2];
|
||||
const char *pwd = argv[3];
|
||||
SQLRETURN r;
|
||||
static int test1(const char *dsn, const char *uid, const char *pwd) {
|
||||
SQLRETURN r = SQL_SUCCESS;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
r = SQLAllocEnv(&env);
|
||||
if (r!=SQL_SUCCESS) return 1;
|
||||
int n = open_connect(dsn, uid, pwd, &env, &conn);
|
||||
if (n) return 1;
|
||||
|
||||
do {
|
||||
r = SQLAllocConnect(env, &conn);
|
||||
CHK_RESULT(r, SQL_HANDLE_ENV, env);
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn),
|
||||
(SQLCHAR*)uid, strlen(uid),
|
||||
(SQLCHAR*)pwd, strlen(pwd));
|
||||
CHK_RESULT(r, SQL_HANDLE_DBC, conn);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
if (do_statement(stmt, "drop database if exists db")) {
|
||||
r = SQL_ERROR;
|
||||
break;
|
||||
}
|
||||
for (size_t i=0; i<sizeof(pre_stmts)/sizeof(pre_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pre_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
do {
|
||||
data_t data = {0};
|
||||
data.ts = 1591060628001;
|
||||
data.b = 1;
|
||||
data.v1 = 127;
|
||||
data.v2 = 32767;
|
||||
data.v4 = 2147483647;
|
||||
data.v8 = 9223372036854775807;
|
||||
data.f4 = 123.456;
|
||||
data.f8 = 9999999.999999;
|
||||
memset(data.bin, 0, sizeof(data.bin));
|
||||
memset(data.blob, 0, sizeof(data.blob));
|
||||
snprintf(data.bin, sizeof(data.bin), "hel我lo");
|
||||
snprintf(data.blob, sizeof(data.blob), "world");
|
||||
snprintf(data.blob, sizeof(data.blob), "wo人rld");
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
do_statement(stmt, "drop database db");
|
||||
for (size_t i=0; i<sizeof(pre_stmts)/sizeof(pre_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pre_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
do {
|
||||
data_t data = {0};
|
||||
data.ts = 1591060628001;
|
||||
data.b = 1;
|
||||
data.v1 = 127;
|
||||
data.v2 = 32767;
|
||||
data.v4 = 2147483647;
|
||||
data.v8 = 9223372036854775807;
|
||||
data.f4 = 123.456;
|
||||
data.f8 = 9999999.999999;
|
||||
memset(data.bin, 0, sizeof(data.bin));
|
||||
memset(data.blob, 0, sizeof(data.blob));
|
||||
snprintf(data.bin, sizeof(data.bin), "hel我lo");
|
||||
snprintf(data.blob, sizeof(data.blob), "world");
|
||||
snprintf(data.blob, sizeof(data.blob), "wo人rld");
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
r = do_insert(stmt, data);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
} while (0);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
|
||||
// r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// do {
|
||||
// r = do_insert(stmt, ts++, v++);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// } while (0);
|
||||
// SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
r = do_insert(stmt, data);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
for (size_t i=0; i<sizeof(pro_stmts)/sizeof(pro_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pro_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
} while (0);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
|
||||
// r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// do {
|
||||
// r = do_insert(stmt, ts++, v++);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// } while (0);
|
||||
// SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
SQLDisconnect(conn);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
for (size_t i=0; i<sizeof(pro_stmts)/sizeof(pro_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pro_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
} while (0);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
SQLDisconnect(conn);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeEnv(env);
|
||||
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int test_statements(const char *dsn, const char *uid, const char *pwd, const char **statements) {
|
||||
SQLRETURN r = SQL_SUCCESS;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
int n = open_connect(dsn, uid, pwd, &env, &conn);
|
||||
if (n) return 1;
|
||||
do {
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
const char **p = statements;
|
||||
while (*p) {
|
||||
if (do_statement(stmt, *p)) {
|
||||
r = SQL_ERROR;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
SQLDisconnect(conn);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeEnv(env);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int test_driver_connect(const char *connstr) {
|
||||
SQLRETURN r = SQL_SUCCESS;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
int n = open_driver_connect(connstr, &env, &conn);
|
||||
if (n) return 1;
|
||||
SQLDisconnect(conn);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeEnv(env);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int create_statement(SQLHENV env, SQLHDBC conn, SQLHSTMT *pStmt) {
|
||||
SQLHSTMT stmt = {0};
|
||||
SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
|
||||
if (r==SQL_SUCCESS) {
|
||||
*pStmt = stmt;
|
||||
return 0;
|
||||
}
|
||||
if (r==SQL_SUCCESS_WITH_INFO) {
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int do_statements(SQLHSTMT stmt, const char **statements) {
|
||||
const char **p = statements;
|
||||
while (p && *p) {
|
||||
CHK_TEST(do_statement(stmt, *p));
|
||||
++p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tests_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt) {
|
||||
const char *statements[] = {
|
||||
"drop database if exists m",
|
||||
"create database m",
|
||||
"use m",
|
||||
// "create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1))",
|
||||
"create table t (ts timestamp, b bool)",
|
||||
"insert into t values('2020-10-10 00:00:00', 0)",
|
||||
"insert into t values('2020-10-10 00:00:00.001', 1)",
|
||||
NULL
|
||||
};
|
||||
CHK_TEST(do_statements(stmt, statements));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tests(SQLHENV env, SQLHDBC conn) {
|
||||
SQLHSTMT stmt = {0};
|
||||
CHK_TEST(create_statement(env, conn, &stmt));
|
||||
int r = tests_stmt(env, conn, stmt);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int test_env(void) {
|
||||
SQLRETURN r;
|
||||
SQLHENV env = {0};
|
||||
r = SQLAllocEnv(&env);
|
||||
if (r!=SQL_SUCCESS) return 1;
|
||||
SQLFreeEnv(env);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls) {
|
||||
FILE *f = fopen(sqls, "rb");
|
||||
if (!f) {
|
||||
D("failed to open file [%s]", sqls);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int r = 0;
|
||||
while (!feof(f)) {
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
ssize_t n = getline(&line, &len, f);
|
||||
if (n==-1) break;
|
||||
|
||||
const char *p = NULL;
|
||||
do {
|
||||
if (line[0] == '#') break;
|
||||
if (line[n-1] == '\n') line[n-1]='\0';
|
||||
p = line;
|
||||
while (isspace(*p)) ++p;
|
||||
|
||||
if (*p==0) break;
|
||||
|
||||
int positive = 1;
|
||||
if (strncmp(p, "N:", 2)==0) {
|
||||
positive = 0;
|
||||
p += 2;
|
||||
} else if (strncmp(p, "P:", 2)==0) {
|
||||
p += 2;
|
||||
}
|
||||
|
||||
D("statement: [%s]", p);
|
||||
r = do_statement(stmt, p);
|
||||
|
||||
if (positive && r==0) break;
|
||||
if (!positive && r) { r = 0; break; }
|
||||
if (positive) return r;
|
||||
D("expecting negative result, but got positive");
|
||||
return -1;
|
||||
} while (0);
|
||||
|
||||
free(line);
|
||||
|
||||
if (r) break;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int test_sqls_in_conn(SQLHENV env, SQLHDBC conn, const char *sqls) {
|
||||
SQLHSTMT stmt = {0};
|
||||
CHK_TEST(create_statement(env, conn, &stmt));
|
||||
int r = test_sqls_in_stmt(env, conn, stmt, sqls);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *connstr, const char *sqls) {
|
||||
int r = 0;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
if (dsn) {
|
||||
CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn));
|
||||
} else {
|
||||
CHK_TEST(open_driver_connect(connstr, &env, &conn));
|
||||
}
|
||||
r = test_sqls_in_conn(env, conn, sqls);
|
||||
SQLDisconnect(conn);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeEnv(env);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc==1) {
|
||||
CHK_TEST(test_env());
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *dsn = (argc>1) ? argv[1] : NULL;
|
||||
const char *uid = (argc>2) ? argv[2] : NULL;
|
||||
const char *pwd = (argc>3) ? argv[3] : NULL;
|
||||
const char *connstr = (argc>4) ? argv[4] : NULL;
|
||||
const char *sqls = (argc>5) ? argv[5] : NULL;
|
||||
|
||||
if (0) {
|
||||
CHK_TEST(test_env());
|
||||
|
||||
CHK_TEST(test1(dsn, uid, pwd));
|
||||
|
||||
const char *statements[] = {
|
||||
"drop database if exists m",
|
||||
"create database m",
|
||||
"use m",
|
||||
"drop database m",
|
||||
NULL
|
||||
};
|
||||
CHK_TEST(test_statements(dsn, uid, pwd, statements));
|
||||
|
||||
if (connstr)
|
||||
CHK_TEST(test_driver_connect(connstr));
|
||||
|
||||
if (connstr) {
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
CHK_TEST(open_driver_connect(connstr, &env, &conn));
|
||||
int r = tests(env, conn);
|
||||
SQLDisconnect(conn);
|
||||
SQLFreeConnect(conn);
|
||||
SQLFreeEnv(env);
|
||||
if (r) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((dsn || connstr) && 1) {
|
||||
CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue