1--TEST--
2PDO ODBC "long" columns
3--SKIPIF--
4<?php # vim:ft=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 --eanble-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--EXPECT--
94Passed on size 32
95Passed on size 53
96Passed on size 64
97Passed on size 79
98Passed on size 128
99Passed on size 253
100Passed on size 254
101Passed on size 255
102Passed on size 256
103Passed on size 257
104Passed on size 258
105Passed on size 510
106Passed on size 511
107Passed on size 512
108Passed on size 513
109Passed on size 514
110Passed on size 1022
111Passed on size 1023
112Passed on size 1024
113Passed on size 1025
114Passed on size 1026
115Passed on size 1278
116Passed on size 1279
117Passed on size 1280
118Passed on size 1281
119Passed on size 1282
120Passed on size 1534
121Passed on size 1535
122Passed on size 1536
123Passed on size 1537
124Passed on size 1538
125Passed on size 2046
126Passed on size 2047
127Passed on size 2048
128Passed on size 2049
129Passed on size 2050
130Passed on size 3070
131Passed on size 3071
132Passed on size 3072
133Passed on size 3073
134Passed on size 3074
135Passed on size 3998
136Passed on size 3999
137Passed on size 4000
138Finished
139