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