1--TEST--
2PDO ODBC "long" columns
3--SKIPIF--
4<?php
5if (!extension_loaded('pdo_odbc')) print 'skip not loaded';
6// make sure there is an ODBC driver and a DSN, or the test will fail
7include 'ext/pdo/tests/pdo_test.inc';
8$config = PDOTest::get_config('ext/pdo_odbc/tests/common.phpt');
9if (!isset($config['ENV']['PDOTEST_DSN']) || $config['ENV']['PDOTEST_DSN']===false) print 'skip';
10?>
11--FILE--
12<?php
13// setup: set PDOTEST_DSN environment variable
14//        for MyODBC (MySQL) and MS SQL Server, you need to also set PDOTEST_USER and PDOTEST_PASS
15//
16// can use MS SQL Server on Linux - using unixODBC
17//   -RHEL6.2
18//   -download & instructions: http://www.microsoft.com/en-us/download/details.aspx?id=28160
19//      -Linux6\sqlncli-11.0.1790.0.tar.gz (it calls RHEL6.x 'Linux6' for some reason)
20//   -follow instructions on web page and install script
21//   -may have to specify connection info in connection string without using a DSN (DSN-less connection)
22//      -for example:
23//            set PDOTEST_DSN='odbc:Driver=SQL Server Native Client 11.0;Server=10.200.51.179;Database=testdb'
24//            set PDOTEST_USER=sa
25//            set PDOTEST_PASS=Password01
26//
27// on Windows, the easy way to do this:
28// 1. install MS Access (part of MS Office) and include ODBC (Development tools feature)
29//       install the x86 build of the Drivers. You might not be able to load the x64 drivers.
30// 2. in Control Panel, search for ODBC and open "Setup data sources (ODBC)"
31// 3. click on System DSN tab
32// 4. click Add and choose "Microsoft Access Driver (*.mdb, *.accdb)" driver
33// 5. enter a DSN, ex: accdb12
34// 6. click 'Create' and select a file to save the database as
35//       -otherwise, you'll have to open MS Access, create a database, then load that file in this Window to map it to a DSN
36// 7. set the environment variable PDOTEST_DSN="odbc:<system dsn from step 5>" ex: SET PDOTEST_DSN=odbc:accdb12
37//         -note: on Windows, " is included in environment variable
38//
39// easy way to compile:
40// configure --disable-all --enable-cli --enable-zts --enable-pdo --with-pdo-odbc --enable-debug
41// configure --disable-all --enable-cli --enable-pdo --with-pdo-odbc=unixODBC,/usr,/usr --with-unixODBC=/usr --enable-debug
42//
43
44require 'ext/pdo/tests/pdo_test.inc';
45$db = PDOTest::test_factory('ext/pdo_odbc/tests/common.phpt');
46$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
47
48if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data CLOB)')) {
49    if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data longtext)')) {
50        if (false === $db->exec('CREATE TABLE TEST (id INT NOT NULL PRIMARY KEY, data varchar(4000))')) {
51            die("BORK: don't know how to create a long column here:\n" . implode(", ", $db->errorInfo()));
52        }
53    }
54}
55
56$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
57
58// the driver reads columns in blocks of 255 bytes and then reassembles those blocks into a single buffer.
59// test sizes around 255 to make sure that the reassembly works (and that the column is split into 255 byte blocks by the database)
60// also, test sizes below 255 to make sure that they work - and are not treated as a long column (should be read in a single read)
61$sizes = array(32, 53, 64, 79, 128, 253, 254, 255, 256, 257, 258, 1022, 1023, 1024, 1025, 1026, 510, 511, 512, 513, 514, 1278, 1279, 1280, 1281, 1282, 2046, 2047, 2048, 2049, 2050, 1534, 1535, 1536, 1537, 1538, 3070, 3071, 3072, 3073, 3074, 3998, 3999, 4000);
62
63function alpha_repeat($len) {
64    // use the alphabet instead of 'i' characters to make sure the blocks don't overlap when they are reassembled
65    $out = "";
66    while (strlen($out) < $len) {
67        $out .= "abcdefghijklmnopqrstuvwxyz";
68    }
69    return substr($out, 0, $len);
70}
71
72// don't use Prepared Statements. that fails on MS SQL server (works with Access, MyODBC), which is a separate failure, feature/code-path from what
73// this test does - nice to be able to test using MS SQL server
74foreach ($sizes as $num) {
75    $text = alpha_repeat($num);
76    $db->exec("INSERT INTO TEST VALUES($num, '$text')");
77}
78
79// verify data
80foreach ($db->query('SELECT id, data from TEST ORDER BY LEN(data) ASC') as $row) {
81    $expect = alpha_repeat($row[0]);
82    if (strcmp($expect, $row[1])) {
83        echo "Failed on size $row[id]:\n";
84        printf("Expected %d bytes, got %d\n", strlen($expect), strlen($row['data']));
85        echo ($expect) . "\n";
86        echo ($row['data']) . "\n";
87    } else {
88        echo "Passed on size $row[id]\n";
89    }
90}
91
92echo "Finished\n";
93?>
94--EXPECT--
95Passed on size 32
96Passed on size 53
97Passed on size 64
98Passed on size 79
99Passed on size 128
100Passed on size 253
101Passed on size 254
102Passed on size 255
103Passed on size 256
104Passed on size 257
105Passed on size 258
106Passed on size 510
107Passed on size 511
108Passed on size 512
109Passed on size 513
110Passed on size 514
111Passed on size 1022
112Passed on size 1023
113Passed on size 1024
114Passed on size 1025
115Passed on size 1026
116Passed on size 1278
117Passed on size 1279
118Passed on size 1280
119Passed on size 1281
120Passed on size 1282
121Passed on size 1534
122Passed on size 1535
123Passed on size 1536
124Passed on size 1537
125Passed on size 1538
126Passed on size 2046
127Passed on size 2047
128Passed on size 2048
129Passed on size 2049
130Passed on size 2050
131Passed on size 3070
132Passed on size 3071
133Passed on size 3072
134Passed on size 3073
135Passed on size 3074
136Passed on size 3998
137Passed on size 3999
138Passed on size 4000
139Finished
140