--- /dev/null
+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\r
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#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;
+}