diff --git a/postgres-testing.sh b/postgres-testing.sh new file mode 100644 index 0000000..cdaf65b --- /dev/null +++ b/postgres-testing.sh @@ -0,0 +1,173 @@ +#! /bin/sh + +# Do some "integration" testing against running PostgreSQL server. + +# This file is to be sourced. + +: ${PGTESTS_DATADIR=`pwd`/datadir} +: ${PGTESTS_ADMIN=`id -u -n`} +: ${PGTESTS_ADMINDB=$PGTESTS_ADMIN} +: ${PGTESTS_ADMINPASS=$PGTESTS_ADMIN} +: ${PGTESTS_PORT=54321} +: ${PGTESTS_SOCKETDIR=/tmp} +: ${PGTESTS_USERS=test:test} +: ${PGTESTS_DATABASES=test:test} + +# Stop the old cluster and/or remove it's data. +: ${PGTESTS_STARTCLEANUP=:} + +# Cleanup once we exit the script. +: ${PGTESTS_CLEANUP=:} + +# Cleanup once we exit the script. +: ${PGTESTS_CLEANUP=:} + +export PGPORT=$PGTESTS_PORT +export PGHOST=$PGTESTS_SOCKETDIR + +warning () +{ + echo >&2 " ! $*" +} + + +__trap_cb () +{ + IFS=' ' + for __func in $__TRAP_ACTIONS + do + $__func + done +} +trap __trap_cb EXIT + + +__pgtests_initdb () +{ + initdb "$PGTESTS_DATADIR" -U "$PGTESTS_ADMIN" \ + --auth-local=peer --auth-host=md5 \ + ${PGTESTS_LOCALE+--locale="$PGTESTS_LOCALE"} +} + + +__pgtests_start () +{ + pg_ctl -D "$PGTESTS_DATADIR" -l "$PGTESTS_DATADIR"/start.log start -o "-k $PGTESTS_SOCKETDIR -p $PGTESTS_PORT" -w +} + + +__pgtests_create_admins_db () +{ + createdb -h "$PGTESTS_SOCKETDIR" "$PGTESTS_ADMINDB" --owner "$PGTESTS_ADMIN" -p "$PGTESTS_PORT" +} + + +__pgtests_passwd() +{ + psql -d postgres --set=user="$1" --set=pass="$2" -tA \ + <<<"ALTER USER :\"user\" WITH ENCRYPTED PASSWORD :'pass';" +} + +pgtests_start () +{ + unset __TRAP_ACTIONS + + if $PGTESTS_STARTCLEANUP; then + # We don't plan to be serious here. This pgtests_* effort is just to + # ease _testing_ against running postgresql server without too much + # writing. + if test -f "$PGTESTS_DATADIR"/postmaster.pid; then + # Give it a try. + warning "Seems like server works, trying to stop." + pg_ctl stop -D "$PGTESTS_DATADIR" -w + fi + + # Cleanup testing directory + if test -e "$PGTESTS_DATADIR"; then + warning "Removing old data directory." + rm -r "$PGTESTS_DATADIR" + fi + fi + + __pgtests_initdb && __TRAP_ACTIONS="pgtests_cleanup $__TRAP_ACTIONS" + __pgtests_start && __TRAP_ACTIONS="pgtests_stop $__TRAP_ACTIONS" + __pgtests_create_admins_db + + __pgtests_passwd "$PGTESTS_ADMIN" "$PGTESTS_ADMINPASS" + + + for _pgt_user in $PGTESTS_USERS + do + save_IFS=$IFS + IFS=: + _user= + _pass= + for _part in $_pgt_user + do + if test -z "$_user"; then + _user=$_part + else + _pass=$_part + fi + done + + createuser "$_user" + __pgtests_passwd "$_user" "$_pass" + IFS=$save_IFS + done + + + for _pgt_db in $PGTESTS_DATABASES + do + save_IFS=$IFS + IFS=: + _db= + _user= + for _part in $_pgt_db + do + if test -z "$_user"; then + _user=$_part + else + _db=$_part + fi + done + + createdb "$_db" --owner "$_part" + + IFS=$save_IFS + done +} + + +__clean_trap_action () +{ + __new_actions= + for __action in $__TRAP_ACTIONS + do + if test "$__action" = "$1"; then + : + else + __new_actions="$__action $__new_actions" + fi + done + + __TRAP_ACTIONS=$__new_actions +} + + +pgtests_cleanup () +{ + if $PGTESTS_CLEANUP && $PGTESTS_AUTOSTOP; then + rm -r "$PGTESTS_DATADIR" + fi + __clean_trap_action pgtests_cleanup +} + + +pgtests_stop () +{ + if $PGTESTS_AUTOSTOP; then + pg_ctl stop -D "$PGTESTS_DATADIR" -w + fi + __clean_trap_action pgtests_stop +} diff --git a/postgresql-odbc-09.05.0200-add-missing-test.patch b/postgresql-odbc-09.05.0200-add-missing-test.patch new file mode 100644 index 0000000..4ac889c --- /dev/null +++ b/postgresql-odbc-09.05.0200-add-missing-test.patch @@ -0,0 +1,166 @@ +From c15f7cfea5c2974d4d66ebb8c63594283eca6c30 Mon Sep 17 00:00:00 2001 +From: Hiroshi Inoue +Date: Sat, 26 Mar 2016 22:20:38 +0900 +Subject: [PATCH] Add test declare-block-test. It contains 3 cases which + correspond to bugs introduced in 9.05.0100. They are all in declare/fetch + mode. 1. Using block cursors. 2. Scroll BOF -> EOF -> BOF ... 3. When + fetching a row "behind" the rowset by "fetch absolute", how many rows can be + fetched? + +--- + test/expected/declare-fetch-block.out | 10 +++ + test/src/declare-fetch-block-test.c | 125 ++++++++++++++++++++++++++++++++++ + 2 files changed, 135 insertions(+) + create mode 100644 test/expected/declare-fetch-block.out + create mode 100644 test/src/declare-fetch-block-test.c + +diff --git a/test/expected/declare-fetch-block.out b/test/expected/declare-fetch-block.out +new file mode 100644 +index 0000000..2368b59 +--- /dev/null ++++ b/test/expected/declare-fetch-block.out +@@ -0,0 +1,10 @@ ++connected ++fetchIdx=1, fetched rows=84, total rows=84 ++fetchIdx=2, fetched rows=36, total rows=120 ++next total rows=120 ++prior total rows=120 ++next total rows=120 ++prior total rows=120 ++FetchScroll beyond the end failed 100 ++encountered EOF at 120 ++disconnecting +diff --git a/test/src/declare-fetch-block-test.c b/test/src/declare-fetch-block-test.c +new file mode 100644 +index 0000000..2ecd0c2 +--- /dev/null ++++ b/test/src/declare-fetch-block-test.c +@@ -0,0 +1,125 @@ ++/* ++ * Test what happens when using block cursors, scrolling next and prior, or ++ * fetching a row "behind" the rowset by "fetch absolute". ++ */ ++ ++#include ++#include ++#include ++ ++#include "common.h" ++ ++#define TOTAL 120 ++#define BLOCK 84 ++int main(int argc, char **argv) ++{ ++ int rc; ++ HSTMT hstmt = SQL_NULL_HSTMT; ++ int i; ++ int count = TOTAL; ++ char query[100]; ++ int totalRows = 0; ++ int fetchIdx = 0; ++ SQLLEN rowArraySize = BLOCK; ++ SQLULEN rowsFetched; ++ SQLINTEGER id[BLOCK]; ++ SQLLEN cbLen[BLOCK]; ++ ++ /**** ++ * Run this test with UseDeclareFetch = 1 and Fetch=100(default). ++ */ ++ test_connect_ext("UseDeclareFetch=1"); ++ ++ rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); ++ if (!SQL_SUCCEEDED(rc)) ++ { ++ print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn); ++ exit(1); ++ } ++ ++ rc = SQLExecDirect(hstmt, (SQLCHAR *) "create temporary table tmptable(id int4 primary key)", SQL_NTS); ++ CHECK_STMT_RESULT(rc, "SQLExecDirect create table failed", hstmt); ++ ++ /* insert into a table */ ++ for (i = 0; i < count; i++) ++ { ++ snprintf(query, sizeof(query), "insert into tmptable values (%d)", i); ++ rc = SQLExecDirect(hstmt, (SQLCHAR *) query, SQL_NTS); ++ CHECK_STMT_RESULT(rc, "insert into table failed", hstmt); ++ } ++ rc = SQLFreeStmt(hstmt, SQL_CLOSE); ++ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); ++ ++ /* ++ * Block cursor ++ */ ++ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) rowArraySize, 0); ++ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROW_ARRAY_SIZE failed", hstmt); ++ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, (SQLPOINTER) &rowsFetched, 0); ++ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROWS_FETCHED_PTR failed", hstmt); ++ rc = SQLBindCol(hstmt, 1, SQL_C_SLONG, &id, 0, cbLen); ++ CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); ++ rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); ++ CHECK_STMT_RESULT(rc, "select failed", hstmt); ++ while (rc = SQLFetch(hstmt), SQL_SUCCEEDED(rc)) ++ { ++ fetchIdx++; ++ totalRows += (int) rowsFetched; ++ printf("fetchIdx=%d, fetched rows=%d, total rows=%d\n", fetchIdx, (int) rowsFetched, totalRows); ++ } ++ rc = SQLFreeStmt(hstmt, SQL_CLOSE); ++ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); ++ /* ++ * Scroll next -> EOF -> prior -> BOF -> next -> EOF -> prior -> BOF ++ */ ++ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) 1, SQL_IS_UINTEGER); ++ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROW_ARRAY_SIZE failed", hstmt); ++ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_STATIC, 0); ++ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CURSOR_TYPE failed", hstmt); ++ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0); ++ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CONCURRENCY failed", hstmt); ++ rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); ++ CHECK_STMT_RESULT(rc, "select failed", hstmt); ++ for (i = 0; i < 2; i++) ++ { ++ totalRows = 0; ++ while (rc = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0), SQL_SUCCEEDED(rc)) ++ totalRows += (int) rowsFetched; ++ if (SQL_NO_DATA != rc) ++ CHECK_STMT_RESULT(rc, "fetch failed", hstmt); ++ printf("next total rows=%d\n", totalRows); ++ totalRows = 0; ++ while (rc = SQLFetchScroll(hstmt, SQL_FETCH_PRIOR, 0), SQL_SUCCEEDED(rc)) ++ totalRows += (int) rowsFetched; ++ if (SQL_NO_DATA != rc) ++ CHECK_STMT_RESULT(rc, "fetch failed", hstmt); ++ printf("prior total rows=%d\n", totalRows); ++ } ++ rc = SQLFreeStmt(hstmt, SQL_CLOSE); ++ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); ++ /* ++ * When fetching a row "behind" the rowset by "fetch absolute" only the first ones of the result set can be fetched? ++ */ ++ rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); ++ CHECK_STMT_RESULT(rc, "select failed", hstmt); ++ if (rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, count + 1), !SQL_SUCCEEDED(rc)) ++ { ++ printf("FetchScroll beyond the end failed %d\n", rc); ++ } ++ rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, 1); ++ CHECK_STMT_RESULT(rc, "FetchScroll the 1st row failed", hstmt); ++ for (i = 1; i < count; i++) ++ { ++ if (!SQL_SUCCEEDED(rc = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0))) ++ break; ++ } ++ printf("encountered EOF at %d\n", i); ++ ++ rc = SQLFreeStmt(hstmt, SQL_CLOSE); ++ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); ++ ++ /* Clean up */ ++ test_disconnect(); ++ ++ return 0; ++} +-- +2.5.5 + diff --git a/postgresql-odbc.spec b/postgresql-odbc.spec index f30657e..d35b2cf 100644 --- a/postgresql-odbc.spec +++ b/postgresql-odbc.spec @@ -8,7 +8,12 @@ URL: http://psqlodbc.projects.postgresql.org/ Source0: http://ftp.postgresql.org/pub/odbc/versions/src/psqlodbc-%{version}.tar.gz +Source1: postgres-testing.sh + +Patch0: postgresql-odbc-09.05.0200-add-missing-test.patch + BuildRequires: unixODBC-devel postgresql-devel +BuildRequires: postgresql-server # This spec file and ancillary files are licensed in accordance with # the psqlodbc license. @@ -19,7 +24,7 @@ PostgreSQL system via ODBC (Open Database Connectivity). %prep -%setup -q -n psqlodbc-%{version} +%autosetup -p1 -n psqlodbc-%{version} cat <README.rpmdist The upstream psqlodbc testsuite is distributed in '%{name}-tests' (sub)package. @@ -46,6 +51,21 @@ pushd ${RPM_BUILD_ROOT}%{_libdir} popd +%check +. %{SOURCE1} + +pgtests_start + +cd test && make installcheck || { + echo "=== trying to find all regression.diffs files in build directory ===" + find -name 'regression.diffs' | while read line; do + cat "$line" + done + false +} + + + %post -p /sbin/ldconfig %postun -p /sbin/ldconfig