From ed28a3c16aec7f7b4e9d86a4a6fd77eee1a9ece5 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 20 Sep 2023 12:33:22 -0400 Subject: [PATCH 1/7] Boolean support Like the PR for ibm_db2. Binding and returning both work. It considers bools to be int-like, although it returns a "TRUE"/"FALSE" string. Changing PDO_IBM to return non-strings is out of scope. It at least works. --- ibm_statement.c | 15 +++++++++-- php_pdo_ibm_int.h | 8 ++++++ tests/fvt_boolean.phpt | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/fvt_boolean.phpt diff --git a/ibm_statement.c b/ibm_statement.c index 796486e..21dbf40 100644 --- a/ibm_statement.c +++ b/ibm_statement.c @@ -353,6 +353,8 @@ static int stmt_get_parameter_info(pdo_stmt_t * stmt, struct pdo_bound_param_dat * Numeric forms we can map directly to a long * int value */ + case SQL_BOOLEAN: + case SQL_BIT: case SQL_SMALLINT: case SQL_INTEGER: param_res->ctype = SQL_C_LONG; @@ -371,6 +373,8 @@ static int stmt_get_parameter_info(pdo_stmt_t * stmt, struct pdo_bound_param_dat static int db2_inout_parm_numeric(param_node *param_res) { /* need character to number padding */ switch ( param_res->data_type ) { + case SQL_BOOLEAN: + case SQL_BIT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_REAL: @@ -446,6 +450,8 @@ static void db2_inout_parm_pad_data(param_node *param_res, struct pdo_bound_para * '2' becomes '000000000000000000002' */ switch ( param_res->data_type ) { + case SQL_BOOLEAN: + case SQL_BIT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_REAL: @@ -591,6 +597,7 @@ int stmt_bind_parameter(pdo_stmt_t *stmt, struct pdo_bound_param_data *curr) return FALSE; /* this is a long value for PHP (or user forced) */ + case PDO_PARAM_BOOL: case PDO_PARAM_INT: /* * If the parameter type is a numeric type, @@ -634,7 +641,6 @@ int stmt_bind_parameter(pdo_stmt_t *stmt, struct pdo_bound_param_data *curr) */ /* a string value (very common) */ - case PDO_PARAM_BOOL: case PDO_PARAM_STR: /* * SQL_PARAM_INPUT -- null remain untouched (read) @@ -1481,6 +1487,8 @@ static int ibm_stmt_describer( #ifdef PASE /* i5/OS size changes for "common" converts to string */ switch (col_res->data_type) { /* BIGINT 9223372036854775807 (2^63-1) string convert */ + case SQL_BOOLEAN: + case SQL_BIT: case SQL_BIGINT: case SQL_SMALLINT: case SQL_INTEGER: @@ -1780,6 +1788,10 @@ static int ibm_stmt_get_column_meta( * XXX: Also safe for pre-8.1? */ switch (col_res->data_type) { + /* Booleans */ + case SQL_BOOLEAN: + case SQL_BIT: + add_assoc_long(return_value, "pdo_type", PDO_PARAM_BOOL); /* LOBs */ #ifndef PASE /* i5/OS - not LOBs */ case SQL_LONGVARBINARY: @@ -1815,7 +1827,6 @@ static int ibm_stmt_get_column_meta( default: add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR); break; - /* XXX: PARAM_(INT|BOOL)? */ } #endif return SUCCESS; diff --git a/php_pdo_ibm_int.h b/php_pdo_ibm_int.h index 0c1fd14..0988760 100644 --- a/php_pdo_ibm_int.h +++ b/php_pdo_ibm_int.h @@ -41,6 +41,14 @@ #define MAX_ERR_MSG_LEN (SQL_MAX_MESSAGE_LENGTH + SQL_SQLSTATE_SIZE + 1) #define CDTIMETYPE 112 +/* + * Added in IBM i 7.5, also in LUW 11.1 MP1/FP1 + * see: https://www.ibm.com/docs/en/db2/11.1?topic=database-mod-pack-fix-pack-updates#c0061179__FP1 + */ +#ifndef SQL_BOOLEAN +#define SQL_BOOLEAN 16 +#endif + #ifndef SQL_XML #define SQL_XML -370 #endif diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt new file mode 100644 index 0000000..33d04c6 --- /dev/null +++ b/tests/fvt_boolean.phpt @@ -0,0 +1,56 @@ +--TEST-- +pdo_ibm: Boolean data type +--SKIPIF-- + +--FILE-- +connect(); + + // Tests insert and select + try { + $c->exec("drop table booltest"); + } catch (Exception $e) {} + $c->exec("create or replace table booltest (id integer not null, enabled boolean, primary key(id))"); + + $s = $c->prepare("insert into booltest (id, enabled) values (1, ?)"); + $x = true; + $s->bindParam(1, $x, PDO::PARAM_BOOL); + $r = $s->execute();; + echo " ! Inserted\n"; + + $s = $c->prepare("insert into booltest (id, enabled) values (2, ?)"); + $x = false; + $s->bindParam(1, $x, PDO::PARAM_BOOL); + $r = $s->execute(); + echo " ! Inserted\n"; + + $s = $c->prepare("select * from calvinb.booltest"); + $s->execute(); + while ($r = $s->fetch(PDO::FETCH_ASSOC)) { + var_dump($r); + } + } + } + + $testcase = new Test(); + $testcase->runTest(); +?> +--EXPECT-- +array(2) { + ["ID"]=> + string(1) "1" + ["ENABLED"]=> + string(4) "TRUE" +} +array(2) { + ["ID"]=> + string(1) "2" + ["ENABLED"]=> + string(5) "FALSE" +} From 24f665bd9b33076dc95ca041c456645186ea2dcc Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 20 Sep 2023 13:46:57 -0400 Subject: [PATCH 2/7] fix my badly pasted example code --- tests/fvt_boolean.phpt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index 33d04c6..c0aa2a5 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -14,23 +14,23 @@ pdo_ibm: Boolean data type // Tests insert and select try { - $c->exec("drop table booltest"); + $this->db->exec("drop table booltest"); } catch (Exception $e) {} - $c->exec("create or replace table booltest (id integer not null, enabled boolean, primary key(id))"); + $this->db->exec("create or replace table booltest (id integer not null, enabled boolean, primary key(id))"); - $s = $c->prepare("insert into booltest (id, enabled) values (1, ?)"); + $s = $this->db->prepare("insert into booltest (id, enabled) values (1, ?)"); $x = true; $s->bindParam(1, $x, PDO::PARAM_BOOL); $r = $s->execute();; echo " ! Inserted\n"; - $s = $c->prepare("insert into booltest (id, enabled) values (2, ?)"); + $s = $this->db->prepare("insert into booltest (id, enabled) values (2, ?)"); $x = false; $s->bindParam(1, $x, PDO::PARAM_BOOL); $r = $s->execute(); echo " ! Inserted\n"; - $s = $c->prepare("select * from calvinb.booltest"); + $s = $this->db->prepare("select * from calvinb.booltest"); $s->execute(); while ($r = $s->fetch(PDO::FETCH_ASSOC)) { var_dump($r); From 1cac85c06030aaecaf5f4a4f262724da87efaa40 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 20 Sep 2023 13:55:41 -0400 Subject: [PATCH 3/7] TIL that LUW doesn't support CREATE OR REPLACE TABLE (just view) --- tests/fvt_boolean.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index c0aa2a5..9baead6 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -16,7 +16,7 @@ pdo_ibm: Boolean data type try { $this->db->exec("drop table booltest"); } catch (Exception $e) {} - $this->db->exec("create or replace table booltest (id integer not null, enabled boolean, primary key(id))"); + $this->db->exec("create table booltest (id integer not null, enabled boolean, primary key(id))"); $s = $this->db->prepare("insert into booltest (id, enabled) values (1, ?)"); $x = true; From 1686f33a6e15fbae61821e95b6655d5b83cff726 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 20 Sep 2023 14:04:39 -0400 Subject: [PATCH 4/7] fix hardcoded schema --- tests/fvt_boolean.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index 9baead6..041d676 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -30,7 +30,7 @@ pdo_ibm: Boolean data type $r = $s->execute(); echo " ! Inserted\n"; - $s = $this->db->prepare("select * from calvinb.booltest"); + $s = $this->db->prepare("select * from booltest"); $s->execute(); while ($r = $s->fetch(PDO::FETCH_ASSOC)) { var_dump($r); From 7156e84519876bd4ebc8bea1ce4b541f80109472 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 27 Sep 2023 13:56:08 -0400 Subject: [PATCH 5/7] clean up debug echos --- tests/fvt_boolean.phpt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index 041d676..4f6259d 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -22,13 +22,11 @@ pdo_ibm: Boolean data type $x = true; $s->bindParam(1, $x, PDO::PARAM_BOOL); $r = $s->execute();; - echo " ! Inserted\n"; $s = $this->db->prepare("insert into booltest (id, enabled) values (2, ?)"); $x = false; $s->bindParam(1, $x, PDO::PARAM_BOOL); $r = $s->execute(); - echo " ! Inserted\n"; $s = $this->db->prepare("select * from booltest"); $s->execute(); From 38e863ffe9e70b10443cb207a908c16a9838b5b7 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 18 Oct 2023 16:30:22 -0400 Subject: [PATCH 6/7] For now, accept the difference between luw/i This returns TRUE/FALSE on i and 1/0 on LUW. For now, make consumers deal with it. If it turns out to be a problem, we can decide on one without breaking compatibility for users that have to support both. --- tests/fvt_boolean.phpt | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index 4f6259d..23b86b8 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -31,7 +31,8 @@ pdo_ibm: Boolean data type $s = $this->db->prepare("select * from booltest"); $s->execute(); while ($r = $s->fetch(PDO::FETCH_ASSOC)) { - var_dump($r); + // This can return 0/1 on LUW or TRUE/FALSE on i + echo $r["ID"] . ": " . $r["ENABLED"] . "\n"; } } } @@ -39,16 +40,6 @@ pdo_ibm: Boolean data type $testcase = new Test(); $testcase->runTest(); ?> ---EXPECT-- -array(2) { - ["ID"]=> - string(1) "1" - ["ENABLED"]=> - string(4) "TRUE" -} -array(2) { - ["ID"]=> - string(1) "2" - ["ENABLED"]=> - string(5) "FALSE" -} +--EXPECTREGEX-- +1: (1|TRUE) +0: (0|FALSE) From b196160176d26f334ebfbe5790f043ec3bb3e8b1 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 18 Oct 2023 16:37:35 -0400 Subject: [PATCH 7/7] typo in id --- tests/fvt_boolean.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fvt_boolean.phpt b/tests/fvt_boolean.phpt index 23b86b8..16647a4 100644 --- a/tests/fvt_boolean.phpt +++ b/tests/fvt_boolean.phpt @@ -42,4 +42,4 @@ pdo_ibm: Boolean data type ?> --EXPECTREGEX-- 1: (1|TRUE) -0: (0|FALSE) +2: (0|FALSE)