From 1393e7c2280ec25736c9cc83a79aeb84462ff6df Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Tue, 19 May 2020 21:22:17 +0900 Subject: [PATCH] Add regression test for batch execution. --- test/expected/params-batch-exec.out | 54 ++++++++++++ test/src/params-batch-exec-test.c | 129 ++++++++++++++++++++++++++++ test/tests | 3 +- 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 test/expected/params-batch-exec.out create mode 100644 test/src/params-batch-exec-test.c diff --git a/test/expected/params-batch-exec.out b/test/expected/params-batch-exec.out new file mode 100644 index 0000000..d00d9dd --- /dev/null +++ b/test/expected/params-batch-exec.out @@ -0,0 +1,54 @@ +connected +one by one execution +insert into test_batch returns 1 +row 0 status=success +row 1 status=success_with_info +row 2 status=success +row 3 status=success +row 4 status=success_with_info +row 5 status=success +row 6 status=success +row 7 status=success_with_info +row 8 status=success +row 9 status=success +insert into test_batch returns -1 + +22001=ERROR: value too long for type character varying(4); +Error while executing the query +row 0 status=success_with_info +row 1 status=success_with_info +row 2 status=success_with_info +row 3 status=success_with_info +row 4 status=success_with_info +row 5 status=success_with_info +row 6 status=success_with_info +row 7 status=error +row 8 status=unused +row 9 status=unused +batch execution +insert into test_batch returns 1 +row 0 status=success_with_info +row 1 status=success_with_info +row 2 status=success +row 3 status=success +row 4 status=success_with_info +row 5 status=success_with_info +row 6 status=success_with_info +row 7 status=success_with_info +row 8 status=success +row 9 status=success +insert into test_batch returns -1 + +22001=ERROR: value too long for type character varying(4); +Error while executing the query +row 0 status=success_with_info +row 1 status=success_with_info +row 2 status=success_with_info +row 3 status=success_with_info +row 4 status=success_with_info +row 5 status=success_with_info +row 6 status=error +row 7 status=error +row 8 status=unused +row 9 status=unused +disconnecting diff --git a/test/src/params-batch-exec-test.c b/test/src/params-batch-exec-test.c new file mode 100644 index 0000000..e0d9ab2 --- /dev/null +++ b/test/src/params-batch-exec-test.c @@ -0,0 +1,129 @@ +#include +#include + +#include "common.h" +#ifdef ODBCVER // supress warning +#undef ODBCVER +#endif +#include "../../pgapifunc.h" + +static void b_result(SQLRETURN rc, HSTMT stmt, int repcnt, SQLUSMALLINT status[]) +{ + printf("insert into test_batch returns %d\n", rc); + if (!SQL_SUCCEEDED(rc)) + print_diag("", SQL_HANDLE_STMT, stmt); + /* + if (SQL_SUCCESS != rc) + disp_stmt_error(stmt); + */ + for (int i = 0; i < repcnt; i++) + { + printf("row %d status=%s\n", i, + (status[i] == SQL_PARAM_SUCCESS ? "success" : + (status[i] == SQL_PARAM_UNUSED ? "unused" : + (status[i] == SQL_PARAM_ERROR ? "error" : + (status[i] == SQL_PARAM_SUCCESS_WITH_INFO ? "success_with_info" : "????") + )))); + } +} + +#define BATCHCNT 10 +static SQLRETURN BatchExecute(HDBC conn, int batch_size) +{ + SQLRETURN rc; + HSTMT hstmt; + int vals[BATCHCNT] = { 0, 0, 1, 2, 2, 3, 4, 4, 5, 6}; + SQLCHAR strs[BATCHCNT][10] = { "0", "0-2", "1", "2", "2-2", "3", "4", "4-2", "5", "6" }; + SQLUSMALLINT status[BATCHCNT]; + + rc = SQLSetConnectAttr(conn, SQL_ATTR_PGOPT_BATCHSIZE, (SQLPOINTER)(SQLLEN)batch_size, 0); + if (!SQL_SUCCEEDED(rc)) + { + print_diag("SQLSetConnectAttr SQL_ATTR_PGOPT_BATCHSIZE failed", SQL_HANDLE_DBC, conn); + exit(1); + } + + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); + + SQLSetStmtAttr(hstmt , SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)BATCHCNT, 0); + SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, status, 0); + rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, vals, 0, NULL); + CHECK_STMT_RESULT(rc, "SQLBindParameter 1 failed", hstmt); + rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(strs[0]), 0, strs, sizeof(strs[0]), NULL); + CHECK_STMT_RESULT(rc, "SQLBindParameter 2 failed", hstmt); + rc = SQLExecDirect(hstmt, "INSERT INTO test_batch VALUES (?, ?)" + " ON CONFLICT (id) DO UPDATE SET dt=EXCLUDED.dt" + , SQL_NTS); + b_result(rc, hstmt, BATCHCNT, status); + /** + rc = SQLExecDirect(hstmt, "SELECT * FROM test_batch where id=?" + , SQL_NTS); + b_result(rc, hstmt, BATCHCNT, status); + SQLCloseCursor(hstmt); + **/ + strncpy((LPTSTR) &strs[BATCHCNT - 3], "4-long", sizeof(strs[0])); + rc = SQLExecDirect(hstmt, "INSERT INTO test_batch VALUES (?, ?)" + " ON CONFLICT (id) DO UPDATE SET dt=EXCLUDED.dt" + , SQL_NTS); + b_result(rc, hstmt, BATCHCNT, status); + + rc = SQLFreeStmt(hstmt, SQL_DROP); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + + return rc; +} + +int main(int argc, char **argv) +{ + SQLRETURN rc; + HSTMT hstmt = SQL_NULL_HSTMT; + + test_connect(); + + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); + if (!SQL_SUCCEEDED(rc)) + { + print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn); + exit(1); + } + + /* Drop the existent tables */ + rc = SQLExecDirect(hstmt, "drop table if exists test_batch", SQL_NTS); + CHECK_STMT_RESULT(rc, "drop table failed", hstmt); + /* Create temp table */ + rc = SQLExecDirect(hstmt, "create temporary table test_batch(id int4 primary key, dt varchar(4))", SQL_NTS); + CHECK_STMT_RESULT(rc, "create table failed", hstmt); + /* Create function */ + rc = SQLExecDirect(hstmt, + "CREATE OR REPLACE FUNCTION batch_update_notice() RETURNS TRIGGER" + " AS $$" + " BEGIN" + " RAISE NOTICE 'id=% updated', NEW.id;" + " RETURN NULL;" + " END;" + " $$ LANGUAGE plpgsql" + , SQL_NTS); + CHECK_STMT_RESULT(rc, "create function failed", hstmt); + /* Create trigger */ + rc = SQLExecDirect(hstmt, + "CREATE TRIGGER batch_update_notice" + " BEFORE update on test_batch" + " FOR EACH ROW EXECUTE PROCEDURE batch_update_notice()" + , SQL_NTS); + CHECK_STMT_RESULT(rc, "create trigger failed", hstmt); + + /* 1 by 1 executiton */ + printf("one by one execution\n"); + BatchExecute(conn, 1); + /* Truncate table */ + rc = SQLExecDirect(hstmt, "truncate table test_batch", SQL_NTS); + CHECK_STMT_RESULT(rc, "truncate table failed", hstmt); + /* batch executiton batch_size=2*/ + printf("batch execution\n"); + BatchExecute(conn, 2); + + /* Clean up */ + test_disconnect(); + + return 0; +} diff --git a/test/tests b/test/tests index e6e195c..8d96039 100644 --- a/test/tests +++ b/test/tests @@ -52,4 +52,5 @@ TESTBINS = exe/connect-test \ exe/large-object-test \ exe/large-object-data-at-exec-test \ exe/odbc-escapes-test \ - exe/wchar-char-test + exe/wchar-char-test \ + exe/params-batch-exec-test -- 2.39.5