Skip to content

Commit 44a5070

Browse files
committed
Fix sqltype overwrite
1 parent b8761c3 commit 44a5070

3 files changed

Lines changed: 159 additions & 13 deletions

File tree

ibase_query.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@
5151
#define FETCH_ROW 1
5252
#define FETCH_ARRAY 2
5353

54-
typedef struct {
55-
unsigned short vary_length;
56-
char vary_string[1];
57-
} IBVARY;
58-
5954
static int le_query;
6055

6156
static void _php_ibase_alloc_xsqlda_vars(XSQLDA *sqlda, ISC_SHORT *nullinds);
@@ -96,6 +91,7 @@ static void _php_ibase_free_query(ibase_query *ib_query) /* {{{ */
9691
if(ib_query->query)efree(ib_query->query);
9792
if(ib_query->ht_aliases)zend_array_destroy(ib_query->ht_aliases);
9893
if(ib_query->ht_ind)zend_array_destroy(ib_query->ht_ind);
94+
if(ib_query->sql_types)efree(ib_query->sql_types);
9995

10096
efree(ib_query);
10197
}
@@ -314,12 +310,18 @@ static int _php_ibase_prepare(ibase_query **new_query, ibase_db_link *link, /* {
314310
ib_query->in_sqlda->sqln = ib_query->in_fields_count;
315311
ib_query->in_sqlda->version = SQLDA_CURRENT_VERSION;
316312

313+
ib_query->sql_types = emalloc(sizeof(*ib_query->sql_types) * ib_query->in_fields_count);
314+
317315
if (isc_dsql_describe_bind(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->in_sqlda)) {
318316
IBDEBUG("isc_dsql_describe_bind() failed\n");
319317
_php_ibase_error();
320318
goto _php_ibase_alloc_query_error;
321319
}
322320

321+
for (int i = 0; i < ib_query->in_fields_count; i++) {
322+
ib_query->sql_types[i] = ib_query->in_sqlda->sqlvar[i].sqltype;
323+
}
324+
323325
assert(ib_query->in_sqlda->sqln == ib_query->in_sqlda->sqld);
324326
assert(ib_query->in_sqlda->sqld == ib_query->in_fields_count);
325327

@@ -567,10 +569,12 @@ static int _php_ibase_bind(ibase_query *ib_query, zval *b_vars) /* {{{ */
567569
int i, array_cnt = 0, rv = SUCCESS;
568570

569571
for (i = 0; i < sqlda->sqld; ++i) { /* bound vars */
570-
571572
zval *b_var = &b_vars[i];
572573
XSQLVAR *var = &sqlda->sqlvar[i];
573574

575+
// We need keep track of original type because XSQLVAR type could get modified
576+
var->sqltype = ib_query->sql_types[i];
577+
574578
var->sqlind = &buf[i].nullind;
575579
var->sqldata = (void*)&buf[i].val;
576580

@@ -742,7 +746,7 @@ static int _php_ibase_bind(ibase_query *ib_query, zval *b_vars) /* {{{ */
742746
rv = FAILURE;
743747
continue;
744748
}
745-
var->sqltype = SQL_BOOLEAN;
749+
// var->sqltype = SQL_BOOLEAN;
746750
continue;
747751
#endif
748752
case SQL_ARRAY:
@@ -781,13 +785,13 @@ static int _php_ibase_bind(ibase_query *ib_query, zval *b_vars) /* {{{ */
781785
}
782786
++array_cnt;
783787
continue;
784-
} /* switch */
788+
} /* switch */
785789

786-
/* we end up here if none of the switch cases handled the field */
787-
convert_to_string(b_var);
788-
var->sqldata = Z_STRVAL_P(b_var);
789-
var->sqllen = (ISC_SHORT)Z_STRLEN_P(b_var);
790-
var->sqltype = SQL_TEXT;
790+
/* we end up here if none of the switch cases handled the field */
791+
convert_to_string(b_var);
792+
var->sqldata = Z_STRVAL_P(b_var);
793+
var->sqllen = (ISC_SHORT)Z_STRLEN_P(b_var);
794+
var->sqltype = SQL_TEXT; // Here: sqltype is modfied, can't rely on it for next calls
791795
} /* for */
792796
return rv;
793797
}

php_ibase_includes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ typedef struct event {
127127
enum event_state { NEW, ACTIVE, DEAD } state;
128128
} ibase_event;
129129

130+
typedef struct {
131+
unsigned short vary_length;
132+
char vary_string[1];
133+
} IBVARY;
134+
130135
/* sql variables union
131136
* used for convert and binding input variables
132137
*/
@@ -167,6 +172,7 @@ typedef struct _ib_query {
167172
ISC_UCHAR statement_type;
168173
BIND_BUF *bind_buf;
169174
ISC_SHORT *in_nullind, *out_nullind;
175+
ISC_SHORT *sql_types;
170176
ISC_USHORT in_fields_count, out_fields_count;
171177
HashTable *ht_aliases, *ht_ind; // Precomputed for ibase_fetch_*()
172178
int was_result_once;

tests/nulls_001.phpt

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
--TEST--
2+
Test NULLs
3+
--SKIPIF--
4+
<?php include("skipif.inc"); ?>
5+
--FILE--
6+
<?php
7+
8+
require("interbase.inc");
9+
ibase_connect($test_base);
10+
11+
(function(){
12+
ibase_query(
13+
"CREATE TABLE ITEMS (
14+
ID INTEGER NOT null,
15+
CODE1 VARCHAR(32) CHARACTER SET NONE,
16+
CODE10 VARCHAR(32) CHARACTER SET NONE,
17+
MAN_ID INTEGER
18+
)");
19+
ibase_commit_ret();
20+
21+
$data = [
22+
[1, "CODE1 1", "CODE10 1", null],
23+
[2, null, "CODE10 2", 101],
24+
[3, "CODE1 3", null, null],
25+
[4, null, null, 104],
26+
[5, "CODE1 5", null, 105],
27+
[6, "CODE1 6", "CODE10 6", null],
28+
[7, null, "CODE10 7", 107],
29+
[8, null, null, null],
30+
[9, "CODE1 8", "CODE10 9", 109],
31+
];
32+
33+
$p = ibase_prepare(
34+
"INSERT INTO ITEMS (
35+
ID, CODE1, CODE10, MAN_ID
36+
) VALUES (?, ?, ?, ?)");
37+
38+
foreach ($data as $row) {
39+
ibase_execute($p, ...$row);
40+
}
41+
42+
dump_table_rows("ITEMS");
43+
})();
44+
45+
?>
46+
--EXPECT--
47+
array(4) {
48+
["ID"]=>
49+
int(1)
50+
["CODE1"]=>
51+
string(7) "CODE1 1"
52+
["CODE10"]=>
53+
string(8) "CODE10 1"
54+
["MAN_ID"]=>
55+
NULL
56+
}
57+
array(4) {
58+
["ID"]=>
59+
int(2)
60+
["CODE1"]=>
61+
NULL
62+
["CODE10"]=>
63+
string(8) "CODE10 2"
64+
["MAN_ID"]=>
65+
int(101)
66+
}
67+
array(4) {
68+
["ID"]=>
69+
int(3)
70+
["CODE1"]=>
71+
string(7) "CODE1 3"
72+
["CODE10"]=>
73+
NULL
74+
["MAN_ID"]=>
75+
NULL
76+
}
77+
array(4) {
78+
["ID"]=>
79+
int(4)
80+
["CODE1"]=>
81+
NULL
82+
["CODE10"]=>
83+
NULL
84+
["MAN_ID"]=>
85+
int(104)
86+
}
87+
array(4) {
88+
["ID"]=>
89+
int(5)
90+
["CODE1"]=>
91+
string(7) "CODE1 5"
92+
["CODE10"]=>
93+
NULL
94+
["MAN_ID"]=>
95+
int(105)
96+
}
97+
array(4) {
98+
["ID"]=>
99+
int(6)
100+
["CODE1"]=>
101+
string(7) "CODE1 6"
102+
["CODE10"]=>
103+
string(8) "CODE10 6"
104+
["MAN_ID"]=>
105+
NULL
106+
}
107+
array(4) {
108+
["ID"]=>
109+
int(7)
110+
["CODE1"]=>
111+
NULL
112+
["CODE10"]=>
113+
string(8) "CODE10 7"
114+
["MAN_ID"]=>
115+
int(107)
116+
}
117+
array(4) {
118+
["ID"]=>
119+
int(8)
120+
["CODE1"]=>
121+
NULL
122+
["CODE10"]=>
123+
NULL
124+
["MAN_ID"]=>
125+
NULL
126+
}
127+
array(4) {
128+
["ID"]=>
129+
int(9)
130+
["CODE1"]=>
131+
string(7) "CODE1 8"
132+
["CODE10"]=>
133+
string(8) "CODE10 9"
134+
["MAN_ID"]=>
135+
int(109)
136+
}

0 commit comments

Comments
 (0)