summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Marie Smith <auroraeosrose@gmail.com>2016-01-14 13:19:20 +0100
committerAnatol Belski <ab@php.net>2016-06-02 12:04:10 +0200
commit72c9324d706a809417429260b5baaf56e84eac1f (patch)
tree0e5c5df6af08d3269ae1099d90ced13225c1caaa
parent6e5958e37d9e04271216aa945168ee5bbf87a3f6 (diff)
downloadphp-git-72c9324d706a809417429260b5baaf56e84eac1f.tar.gz
Fix ODBC bug for varchars returning with length zero
-rw-r--r--ext/pdo_odbc/odbc_stmt.c18
-rw-r--r--ext/pdo_odbc/tests/max_columns.phpt46
2 files changed, 64 insertions, 0 deletions
diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index a2a2e2c3c3..bdb37d99a6 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -558,6 +558,24 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
sizeof(S->cols[colno].colname)-1, &colnamelen,
&S->cols[colno].coltype, &colsize, NULL, NULL);
+ /* This fixes a known issue with SQL Server and (max) lengths,
+ may affect others as well. If we are SQL_VARCHAR,
+ SQL_VARBINARY, or SQL_WVARCHAR (or any of the long variations)
+ and zero is returned from colsize then consider it long */
+ if (0 == colsize &&
+ (S->cols[colno].coltype == SQL_VARCHAR ||
+ S->cols[colno].coltype == SQL_LONGVARCHAR ||
+#ifdef SQL_WVARCHAR
+ S->cols[colno].coltype == SQL_WVARCHAR ||
+#endif
+#ifdef SQL_WLONGVARCHAR
+ S->cols[colno].coltype == SQL_WLONGVARCHAR ||
+#endif
+ S->cols[colno].coltype == SQL_VARBINARY ||
+ S->cols[colno].coltype == SQL_LONGVARBINARY)) {
+ S->going_long = 1;
+ }
+
if (rc != SQL_SUCCESS) {
pdo_odbc_stmt_error("SQLDescribeCol");
if (rc != SQL_SUCCESS_WITH_INFO) {
diff --git a/ext/pdo_odbc/tests/max_columns.phpt b/ext/pdo_odbc/tests/max_columns.phpt
new file mode 100644
index 0000000000..301fa764ca
--- /dev/null
+++ b/ext/pdo_odbc/tests/max_columns.phpt
@@ -0,0 +1,46 @@
+--TEST--
+PDO ODBC varying character with max/no length
+--SKIPIF--
+<?php # vim:ft=php
+if (!extension_loaded('pdo_odbc')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+require 'ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory('ext/pdo_odbc/tests/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
+
+if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data varchar(max))')) {
+ if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data longtext)')) {
+ if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data CLOB)')) {
+ die("BORK: don't know how to create a long column here:\n" . implode(", ", $db->errorInfo()));
+ }
+ }
+}
+
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$sizes = array(32, 64, 128, 253, 254, 255, 256, 257, 258, 512, 1024, 2048, 3998, 3999, 4000);
+
+$db->beginTransaction();
+$insert = $db->prepare('INSERT INTO TEST VALUES (?, ?)');
+foreach ($sizes as $num) {
+ $insert->execute(array($num, str_repeat('i', $num)));
+}
+$insert = null;
+$db->commit();
+
+foreach ($db->query('SELECT id, data from TEST') as $row) {
+ $expect = str_repeat('i', $row[0]);
+ if (strcmp($expect, $row[1])) {
+ echo "Failed on size $row[id]:\n";
+ printf("Expected %d bytes, got %d\n", strlen($expect), strlen($row['data']));
+ echo bin2hex($expect) . "\n";
+ echo bin2hex($row['data']) . "\n";
+ }
+}
+
+echo "Finished\n";
+
+--EXPECT--
+Finished