1--TEST--
2PDO_OCI: PDOStatement->getColumnMeta
3--SKIPIF--
4<?php
5if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) die('skip not loaded');
6require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
7PDOTest::skip();
8?>
9--FILE--
10<?php
11
12echo "Preparations before the test\n";
13
14require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
15try {
16    $db = PDOTest::factory();
17    $db->exec(<<<SQL
18BEGIN
19   EXECUTE IMMEDIATE 'DROP TABLE test';
20EXCEPTION
21   WHEN OTHERS THEN
22      IF SQLCODE != -942 THEN
23     RAISE;
24      END IF;
25END;
26SQL
27);
28    $db->exec("CREATE TABLE test(id INT)");
29
30    $db->beginTransaction();
31
32    $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC');
33
34    echo "Test 1. calling function with invalid parameters\n";
35
36    // execute() has not been called yet
37    // NOTE: no warning
38    $tmp = $stmt->getColumnMeta(0);
39    printf(" 1.1 Expecting false got %s\n", var_export($tmp, true));
40
41    echo(" 1.2 ");
42    $stmt->execute();
43    // PDOStatement::getColumnMeta() expects exactly 1 argument, 0 given in
44    try {
45        $tmp = $stmt->getColumnMeta();
46    } catch (ArgumentCountError $e) {
47        if (false !== $tmp) {
48            printf("[1.2] Expecting false got %s\n", var_export($tmp, true));
49        }
50        echo $e->getMessage(), "\n";
51    }
52
53    // invalid offset
54    echo " 1.3 ";
55    try {
56        $tmp = $stmt->getColumnMeta(-1);
57    } catch (ValueError $e) {
58        if (false !== $tmp) {
59            printf("[1.3] Expecting false got %s\n", var_export($tmp, true));
60        }
61        echo $e->getMessage(), "\n";
62    }
63
64    // PDOStatement::getColumnMeta(): Argument #1 must be of type int, array given in
65    echo " 1.4 ";
66    try {
67        $tmp = $stmt->getColumnMeta(array());
68    } catch (TypeError $e) {
69        if (false !== $tmp)
70            printf("[1.4] Expecting false got %s\n", var_export($tmp, true));
71        echo $e->getMessage(), "\n";
72    }
73
74    // PDOStatement::getColumnMeta() expects exactly 1 argument, 2 given in
75    echo " 1.5 ";
76    try {
77        $tmp = $stmt->getColumnMeta(1, 1);
78    } catch (ArgumentCountError $e) {
79        if (false !== $tmp)
80            printf("[1.5] Expecting false got %s\n", var_export($tmp, true));
81        echo $e->getMessage(), "\n";
82    }
83
84    // invalid offset
85    $tmp = $stmt->getColumnMeta(1);
86    printf(" 1.6 Expecting false because of invalid offset got %s\n", var_export($tmp, true));
87
88    echo "Test 2. testing return values\n";
89    echo "Test 2.1 testing array returned\n";
90
91    $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC');
92    $stmt->execute();
93    $native = $stmt->getColumnMeta(0);
94    if (count($native) == 0) {
95        printf("[008] Meta data seems wrong, %s / %s\n",
96            var_export($native, true), var_export($emulated, true));
97    }
98
99
100    function test_return($meta, $offset, $native_type, $pdo_type){
101        if (empty($meta)) {
102            printf("[%03d + 2] getColumnMeta() failed, %d - %s\n", $offset,
103                $stmt->errorCode(), var_export($stmt->errorInfo(), true));
104            return false;
105        }
106        $elements = array('flags', 'scale', 'name', 'len', 'precision', 'pdo_type');
107        foreach ($elements as $k => $element)
108            if (!isset($meta[$element])) {
109                printf("[%03d + 3] Element %s missing, %s\n", $offset,
110                    $element, var_export($meta, true));
111                return false;
112            }
113
114        if (!is_null($native_type)) {
115            if (!isset($meta['native_type'])) {
116                printf("[%03d + 4] Element native_type missing, %s\n", $offset,
117                    var_export($meta, true));
118                return false;
119            }
120
121            if (!is_array($native_type))
122                $native_type = array($native_type);
123
124            $found = false;
125            foreach ($native_type as $k => $type) {
126                if ($meta['native_type'] == $type) {
127                    $found = true;
128                    break;
129                }
130            }
131
132            if (!$found) {
133                printf("[%03d + 5] Expecting native type %s, %s\n", $offset,
134                    var_export($native_type, true), var_export($meta, true));
135                return false;
136            }
137        }
138
139        if (!is_null($pdo_type) && ($meta['pdo_type'] != $pdo_type)) {
140            printf("[%03d + 6] Expecting PDO type %s got %s (%s)\n", $offset,
141                $pdo_type, var_export($meta, true), var_export($meta['native_type']));
142            return false;
143        }
144
145        return true;
146    }
147
148
149    function test_meta(&$db, $offset, $sql_type, $value, $native_type, $pdo_type) {
150
151        $db->exec(<<<SQL
152BEGIN
153   EXECUTE IMMEDIATE 'DROP TABLE test';
154EXCEPTION
155   WHEN OTHERS THEN
156      IF SQLCODE != -942 THEN
157         RAISE;
158      END IF;
159END;
160SQL
161);
162
163        $sql = sprintf('CREATE TABLE test(id INT, label %s)', $sql_type);
164        $stmt = $db->prepare($sql);
165        $stmt->execute();
166
167        if (!$db->exec(sprintf("INSERT INTO test(id, label) VALUES (1, '%s')", $value))) {
168            printf("[%03d] + 1] Insert failed, %d - %s\n", $offset,
169                $db->errorCode(), var_export($db->errorInfo(), true));
170            return false;
171        }
172
173        $stmt = $db->prepare('SELECT id, label FROM test');
174        $stmt->execute();
175        $meta = $stmt->getColumnMeta(1);
176        return test_return($meta, $offset, $native_type, $pdo_type);
177    }
178
179    echo "Test 2.2 testing numeric columns\n";
180
181    test_meta($db, 20, 'NUMBER'         , 0                    , 'NUMBER', PDO::PARAM_STR);
182    test_meta($db, 30, 'NUMBER'         , 256                  , 'NUMBER', PDO::PARAM_STR);
183    test_meta($db, 40, 'INT'            , 256                  , 'NUMBER', PDO::PARAM_STR);
184    test_meta($db, 50, 'INTEGER'        , 256                  , 'NUMBER', PDO::PARAM_STR);
185    test_meta($db, 60, 'NUMBER'         , 256.01               , 'NUMBER', PDO::PARAM_STR);
186    test_meta($db, 70, 'NUMBER'         , -8388608             , 'NUMBER', PDO::PARAM_STR);
187
188    test_meta($db, 80, 'NUMBER'         , 2147483648           , 'NUMBER', PDO::PARAM_STR);
189    test_meta($db, 90, 'NUMBER'         , 4294967295           , 'NUMBER', PDO::PARAM_STR);
190
191    test_meta($db, 100, 'DEC'             , 1.01               , 'NUMBER'       , PDO::PARAM_STR);
192    test_meta($db, 110, 'DECIMAL'         , 1.01               , 'NUMBER'       , PDO::PARAM_STR);
193    test_meta($db, 120, 'FLOAT'           , 1.01               , 'FLOAT'        , PDO::PARAM_STR);
194    test_meta($db, 130, 'DOUBLE PRECISION', 1.01               , 'FLOAT'        , PDO::PARAM_STR);
195    test_meta($db, 140, 'BINARY_FLOAT'    , 1.01               , 'BINARY_FLOAT' , PDO::PARAM_STR);
196    test_meta($db, 150, 'BINARY_DOUBLE'   , 1.01               , 'BINARY_DOUBLE', PDO::PARAM_STR);
197
198    echo "Test 2.3 testing temporal columns\n";
199
200    $db->exec("alter session set nls_date_format='YYYY-MM-DD'");
201    test_meta($db, 160, 'DATE'           , '2008-04-23'        , 'DATE', PDO::PARAM_STR);
202
203    echo "Test 2.4 testing string columns\n";
204
205    test_meta($db, 170, 'CHAR(1)'       , 'a'                  , 'CHAR'     , PDO::PARAM_STR);
206    test_meta($db, 180, 'CHAR(10)'      , '0123456789'         , 'CHAR'     , PDO::PARAM_STR);
207    test_meta($db, 190, 'CHAR(255)'     , str_repeat('z', 255) , 'CHAR'     , PDO::PARAM_STR);
208    test_meta($db, 200, 'VARCHAR(1)'    , 'a'                  , 'VARCHAR2' , PDO::PARAM_STR);
209    test_meta($db, 210, 'VARCHAR(10)'   , '0123456789'         , 'VARCHAR2' , PDO::PARAM_STR);
210    test_meta($db, 220, 'VARCHAR(255)'  , str_repeat('z', 255) , 'VARCHAR2' , PDO::PARAM_STR);
211    test_meta($db, 230, 'VARCHAR2(1)'   , 'a'                  , 'VARCHAR2' , PDO::PARAM_STR);
212    test_meta($db, 240, 'VARCHAR2(10)'  , '0123456789'         , 'VARCHAR2' , PDO::PARAM_STR);
213    test_meta($db, 250, 'VARCHAR2(255)' , str_repeat('z', 255) , 'VARCHAR2' , PDO::PARAM_STR);
214
215    test_meta($db, 260, 'NCHAR(1)'      , 'a'                  , 'NCHAR'    , PDO::PARAM_STR);
216    test_meta($db, 270, 'NCHAR(10)'     , '0123456789'         , 'NCHAR'    , PDO::PARAM_STR);
217    test_meta($db, 280, 'NCHAR(255)'    , str_repeat('z', 255) , 'NCHAR'    , PDO::PARAM_STR);
218    test_meta($db, 290, 'NVARCHAR2(1)'  , 'a'                  , 'NVARCHAR2', PDO::PARAM_STR);
219    test_meta($db, 300, 'NVARCHAR2(10)' , '0123456789'         , 'NVARCHAR2', PDO::PARAM_STR);
220    test_meta($db, 310, 'NVARCHAR2(255)', str_repeat('z', 255) , 'NVARCHAR2', PDO::PARAM_STR);
221
222    echo "Test 2.5 testing lobs columns\n";
223
224    test_meta($db, 320, 'CLOB'          , str_repeat('b', 255) , 'CLOB'    , PDO::PARAM_LOB);
225    test_meta($db, 330, 'BLOB'          , str_repeat('b', 256) , 'BLOB'    , PDO::PARAM_LOB);
226    test_meta($db, 340, 'NCLOB'         , str_repeat('b', 255) , 'NCLOB'   , PDO::PARAM_LOB);
227
228    test_meta($db, 350, 'LONG'          , str_repeat('b', 256) , 'LONG'    , PDO::PARAM_STR);
229    test_meta($db, 360, 'LONG RAW'      , str_repeat('b', 256) , 'LONG RAW', PDO::PARAM_STR);
230    test_meta($db, 370, 'RAW(256)'      , str_repeat('b', 256) , 'RAW'     , PDO::PARAM_STR);
231
232
233    $db->exec(<<<SQL
234BEGIN
235   EXECUTE IMMEDIATE 'DROP TABLE test';
236EXCEPTION
237   WHEN OTHERS THEN
238      IF SQLCODE != -942 THEN
239         RAISE;
240      END IF;
241END;
242SQL
243);
244    echo "Test 2.6 testing function return\n";
245
246    $stmt = $db->query('SELECT count(*) FROM dual');
247    $meta = $stmt->getColumnMeta(0);
248    test_return($meta, 380, 'NUMBER', PDO::PARAM_STR);
249    $stmt = $db->query("SELECT TO_DATE('2008-04-23') FROM dual");
250    $meta = $stmt->getColumnMeta(0);
251    test_return($meta, 390, 'DATE', PDO::PARAM_STR);
252    $stmt = $db->query("SELECT TO_CHAR(542) FROM dual");
253    $meta = $stmt->getColumnMeta(0);
254    test_return($meta, 400, 'VARCHAR2', PDO::PARAM_STR);
255
256
257    echo "Test 2.7 testing flags returned\n";
258
259    $sql = sprintf('CREATE TABLE test(id INT NOT NULL, label INT NULL)');
260    $stmt = $db->prepare($sql);
261    $stmt->execute();
262    $db->exec('INSERT INTO test(id, label) VALUES (1, 1)');
263    $stmt = $db->query('SELECT id, label FROM test');
264    $meta = $stmt->getColumnMeta(0);
265    // verify the flags array contains a not_null flag and not nullable flags
266    if (!isset($meta['flags'])) {
267        printf("[1001] No flags contained in metadata %s\n", var_export($meta, true));
268    } else {
269        $flags = $meta['flags'];
270        $found = false;
271        foreach ($flags as $k => $flag) {
272            if ($flag == 'not_null')
273                $found = true;
274            if ($flag == 'nullable')
275                printf("[1003] Flags seem wrong %s\n", var_export($meta, true));
276        }
277        if (!$found)
278            printf("[1002] Flags seem wrong %s\n", var_export($meta, true));
279    }
280    $meta = $stmt->getColumnMeta(1);
281    // verify the flags array contains a nullable flag and not not_null flags
282    if (!isset($meta['flags'])) {
283        printf("[1003] No flags contained in metadata %s\n", var_export($meta, true));
284    } else {
285        $flags = $meta['flags'];
286        $found = false;
287        foreach ($flags as $k => $flag) {
288            if ($flag == 'not_null')
289                printf("[1004] Flags seem wrong %s\n", var_export($meta, true));
290            if ($flag == 'nullable')
291                $found = true;
292        }
293        if (!$found)
294            printf("[1005] Flags seem wrong %s\n", var_export($meta, true));
295    }
296
297} catch (PDOException $e) {
298    // we should never get here, we use warnings, but never trust a system...
299    printf("[001] %s, [%s} %s\n",
300        $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo()));
301}
302
303$db->exec(<<<SQL
304BEGIN
305   EXECUTE IMMEDIATE 'DROP TABLE test';
306EXCEPTION
307   WHEN OTHERS THEN
308      IF SQLCODE != -942 THEN
309         RAISE;
310      END IF;
311END;
312SQL
313);
314print "done!";
315?>
316--EXPECT--
317Preparations before the test
318Test 1. calling function with invalid parameters
319 1.1 Expecting false got false
320 1.2 PDOStatement::getColumnMeta() expects exactly 1 argument, 0 given
321 1.3 PDOStatement::getColumnMeta(): Argument #1 ($column) must be greater than or equal to 0
322 1.4 PDOStatement::getColumnMeta(): Argument #1 ($column) must be of type int, array given
323 1.5 PDOStatement::getColumnMeta() expects exactly 1 argument, 2 given
324 1.6 Expecting false because of invalid offset got false
325Test 2. testing return values
326Test 2.1 testing array returned
327Test 2.2 testing numeric columns
328Test 2.3 testing temporal columns
329Test 2.4 testing string columns
330Test 2.5 testing lobs columns
331Test 2.6 testing function return
332Test 2.7 testing flags returned
333done!
334