summaryrefslogtreecommitdiff
path: root/ext/pdo_dblib
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2016-04-06 12:23:14 +0200
committerAnatol Belski <ab@php.net>2016-04-06 12:23:14 +0200
commit2267812cd21c87d2f6ff61090def2ed7ed77125f (patch)
tree5490ccd3c046ef7eaf7c59274697555097ed79c2 /ext/pdo_dblib
parentfe757f09a417b9e0a0b604337bbbf760b2ba24a1 (diff)
parent1e1500a2bc30e0f7b0846e16567ffb3728f57eef (diff)
downloadphp-git-2267812cd21c87d2f6ff61090def2ed7ed77125f.tar.gz
Merge branch 'PHP-7.0'
* PHP-7.0: return zvals instead of strings, cast or not based on stringify attribute
Diffstat (limited to 'ext/pdo_dblib')
-rw-r--r--ext/pdo_dblib/dblib_stmt.c230
-rw-r--r--ext/pdo_dblib/tests/bug_38955.phpt8
-rw-r--r--ext/pdo_dblib/tests/bug_45876.phpt4
-rw-r--r--ext/pdo_dblib/tests/bug_47588.phpt6
-rw-r--r--ext/pdo_dblib/tests/types.phpt66
5 files changed, 239 insertions, 75 deletions
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
index 49b75ee2bb..6098ae515d 100644
--- a/ext/pdo_dblib/dblib_stmt.c
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -232,7 +232,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
}
col->maxlen = dbcollen(H->link, colno+1);
- col->param_type = PDO_PARAM_STR;
+ col->param_type = PDO_PARAM_ZVAL;
return 1;
}
@@ -245,78 +245,161 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
pdo_dblib_db_handle *H = S->H;
int coltype;
- unsigned int tmp_len;
- char *tmp_ptr = NULL;
+ char *data, *tmp_data;
+ unsigned int data_len, tmp_data_len;
+ zval *zv = NULL;
coltype = dbcoltype(H->link, colno+1);
-
- *len = dbdatlen(H->link, colno+1);
- *ptr = dbdata(H->link, colno+1);
-
- if (*len == 0 && *ptr == NULL) {
- return 1;
- }
-
- switch (coltype) {
- case SQLVARBINARY:
- case SQLBINARY:
- case SQLIMAGE:
- case SQLTEXT:
- /* FIXME: Above types should be returned as a stream as they can be VERY large */
- case SQLCHAR:
- case SQLVARCHAR:
- tmp_ptr = emalloc(*len + 1);
- memcpy(tmp_ptr, *ptr, *len);
- tmp_ptr[*len] = '\0';
- *ptr = tmp_ptr;
- break;
- case SQLMONEY:
- case SQLMONEY4:
- case SQLMONEYN: {
- DBFLT8 money_value;
- dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
- *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
- *ptr = tmp_ptr;
- break;
- }
- case SQLUNIQUE: {
- *len = 37;
- tmp_ptr = emalloc(*len + 1);
- *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
- php_strtoupper(tmp_ptr, *len);
- tmp_ptr[36] = '\0';
- *ptr = tmp_ptr;
- break;
+ data = dbdata(H->link, colno+1);
+ data_len = dbdatlen(H->link, colno+1);
+
+ if (data_len != 0 || data != NULL) {
+ if (stmt->dbh->stringify) {
+ switch (coltype) {
+ case SQLFLT4:
+ case SQLFLT8:
+ case SQLINT4:
+ case SQLINT2:
+ case SQLINT1:
+ case SQLBIT: {
+ if (dbwillconvert(coltype, SQLCHAR)) {
+ tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
+ tmp_data = emalloc(tmp_data_len);
+ data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
+
+ zv = emalloc(sizeof(zval));
+ ZVAL_STRING(zv, tmp_data);
+
+ efree(tmp_data);
+ }
+ break;
+ }
+ }
}
- case SQLDATETIM4:
- case SQLDATETIME: {
- DBDATETIME dt;
- DBDATEREC di;
-
- dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
- dbdatecrack(H->link, &di, &dt);
- *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
+ if (!zv) {
+ switch (coltype) {
+ case SQLCHAR:
+ case SQLVARCHAR:
+ case SQLTEXT: {
+#if ilia_0
+ while (data_len>0 && data[data_len-1] == ' ') { /* nuke trailing whitespace */
+ data_len--;
+ }
+#endif
+ }
+ case SQLVARBINARY:
+ case SQLBINARY:
+ case SQLIMAGE: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_STRINGL(zv, data, data_len);
+
+ break;
+ }
+ case SQLDATETIME:
+ case SQLDATETIM4: {
+ int dl;
+ DBDATEREC di;
+ DBDATEREC dt;
+
+ dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1);
+ dbdatecrack(H->link, &di, (DBDATETIME *) &dt);
+
+ dl = spprintf(&tmp_data, 20, "%d-%02d-%02d %02d:%02d:%02d",
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
- di.year, di.month, di.day, di.hour, di.minute, di.second
+ di.year, di.month, di.day, di.hour, di.minute, di.second
+#else
+ di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
+#endif
+ );
+
+ zv = emalloc(sizeof(zval));
+ ZVAL_STRINGL(zv, tmp_data, dl);
+
+ efree(tmp_data);
+
+ break;
+ }
+ case SQLFLT4: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_DOUBLE(zv, (double) (*(DBFLT4 *) data));
+
+ break;
+ }
+ case SQLFLT8: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_DOUBLE(zv, (double) (*(DBFLT8 *) data));
+
+ break;
+ }
+ case SQLINT4: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_LONG(zv, (long) ((int) *(DBINT *) data));
+
+ break;
+ }
+ case SQLINT2: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_LONG(zv, (long) ((int) *(DBSMALLINT *) data));
+
+ break;
+ }
+ case SQLINT1:
+ case SQLBIT: {
+ zv = emalloc(sizeof(zval));
+ ZVAL_LONG(zv, (long) ((int) *(DBTINYINT *) data));
+
+ break;
+ }
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN: {
+ DBFLT8 money_value;
+ dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1);
+
+ zv = emalloc(sizeof(zval));
+ ZVAL_DOUBLE(zv, money_value);
+
+ if (stmt->dbh->stringify) {
+ convert_to_string(zv);
+ }
+
+ break;
+ }
+#ifdef SQLUNIQUE
+ case SQLUNIQUE: {
#else
- di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
+ case 36: { /* FreeTDS hack */
#endif
- );
+ zv = emalloc(sizeof(zval));
+ ZVAL_STRINGL(zv, data, 16); /* uniqueidentifier is a 16-byte binary number */
- *ptr = (char*) tmp_ptr;
- break;
- }
- default:
- if (dbwillconvert(coltype, SQLCHAR)) {
- tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
- tmp_ptr = emalloc(tmp_len);
- *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
- *ptr = tmp_ptr;
- } else {
- *len = 0; /* FIXME: Silently fails and returns null on conversion errors */
- *ptr = NULL;
+ break;
+ }
+ default: {
+ if (dbwillconvert(coltype, SQLCHAR)) {
+ tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
+ tmp_data = emalloc(tmp_data_len);
+ data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
+
+ zv = emalloc(sizeof(zval));
+ ZVAL_STRING(zv, tmp_data);
+
+ efree(tmp_data);
+ }
+
+ break;
+ }
}
+ }
+ }
+
+ if (zv != NULL) {
+ *ptr = (char*)zv;
+ *len = sizeof(zval);
+ } else {
+ *ptr = NULL;
+ *len = 0;
}
*caller_frees = 1;
@@ -335,6 +418,7 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
DBTYPEINFO* dbtypeinfo;
+ int coltype;
if(colno >= stmt->column_count || colno < 0) {
return FAILURE;
@@ -346,14 +430,28 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
if(!dbtypeinfo) return FAILURE;
+ coltype = dbcoltype(H->link, colno+1);
+
add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
- add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
- add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
+ add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype));
+ add_assoc_long(return_value, "native_type_id", coltype);
add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));
+ switch (coltype) {
+ case SQLBIT:
+ case SQLINT1:
+ case SQLINT2:
+ case SQLINT4:
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
+ break;
+ default:
+ add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
+ break;
+ }
+
return 1;
}
diff --git a/ext/pdo_dblib/tests/bug_38955.phpt b/ext/pdo_dblib/tests/bug_38955.phpt
index 1954ed460b..57adbf6c40 100644
--- a/ext/pdo_dblib/tests/bug_38955.phpt
+++ b/ext/pdo_dblib/tests/bug_38955.phpt
@@ -37,21 +37,21 @@ array(4) {
[0]=>
array(1) {
["val"]=>
- string(1) "1"
+ int(1)
}
[1]=>
array(1) {
["val"]=>
- string(1) "2"
+ int(2)
}
[2]=>
array(1) {
["val"]=>
- string(1) "3"
+ int(3)
}
[3]=>
array(1) {
["val"]=>
- string(1) "4"
+ int(4)
}
}
diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt
index 3d527e5ffe..5f1026e623 100644
--- a/ext/pdo_dblib/tests/bug_45876.phpt
+++ b/ext/pdo_dblib/tests/bug_45876.phpt
@@ -30,10 +30,10 @@ array(10) {
int(%d)
["native_usertype_id"]=>
int(%d)
+ ["pdo_type"]=>
+ int(2)
["name"]=>
string(13) "TABLE_CATALOG"
["len"]=>
int(255)
- ["pdo_type"]=>
- int(2)
}
diff --git a/ext/pdo_dblib/tests/bug_47588.phpt b/ext/pdo_dblib/tests/bug_47588.phpt
index d8f424e872..262720f632 100644
--- a/ext/pdo_dblib/tests/bug_47588.phpt
+++ b/ext/pdo_dblib/tests/bug_47588.phpt
@@ -23,21 +23,21 @@ array(3) {
[0]=>
array(2) {
["My Field"]=>
- string(1) "1"
+ int(1)
["Another Field"]=>
string(11) "test_string"
}
[1]=>
array(2) {
["My Field"]=>
- string(1) "2"
+ int(2)
["Another Field"]=>
string(11) "test_string"
}
[2]=>
array(2) {
["My Field"]=>
- string(1) "3"
+ int(3)
["Another Field"]=>
string(11) "test_string"
}
diff --git a/ext/pdo_dblib/tests/types.phpt b/ext/pdo_dblib/tests/types.phpt
new file mode 100644
index 0000000000..dd849adcf8
--- /dev/null
+++ b/ext/pdo_dblib/tests/types.phpt
@@ -0,0 +1,66 @@
+--TEST--
+PDO_DBLIB: Column data types, with or without stringifying
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require __DIR__ . '/config.inc';
+?>
+--FILE--
+<?php
+require __DIR__ . '/config.inc';
+
+$sql = "
+ SELECT
+ 'foo' AS [char],
+ CAST('2030-01-01 23:59:59' AS DATETIME) AS [datetime],
+ CAST(0 AS BIT) AS [false],
+ 10.5 AS [float],
+ 1000 AS [int],
+ CAST(10.5 AS MONEY) AS [money],
+ CAST('1950-01-18 23:00:00' AS SMALLDATETIME) as [smalldatetime],
+ CAST(1 AS BIT) AS [true]
+";
+
+$stmt = $db->query($sql);
+$row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+var_dump($row['char'] === 'foo');
+var_dump($row['datetime'] === '2030-01-01 23:59:59');
+var_dump($row['false'] === 0);
+var_dump($row['float'] === 10.5);
+var_dump($row['int'] === 1000);
+var_dump($row['money'] === 10.5);
+var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
+var_dump($row['true'] === 1);
+
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
+$stmt = $db->query($sql);
+$row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+var_dump($row['char'] === 'foo');
+var_dump($row['datetime'] === '2030-01-01 23:59:59');
+var_dump($row['false'] === '0');
+var_dump($row['float'] === '10.5');
+var_dump($row['int'] === '1000');
+var_dump($row['money'] === '10.5');
+var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
+var_dump($row['true'] === '1');
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)