xref: /PHP-8.2/ext/pdo/tests/pdo_018.phpt (revision 858d0c09)
1--TEST--
2PDO Common: serializing
3--EXTENSIONS--
4pdo
5--SKIPIF--
6<?php
7$dir = getenv('REDIR_TEST_DIR');
8if (false == $dir) die('skip no driver');
9require_once $dir . 'pdo_test.inc';
10PDOTest::skip();
11?>
12--FILE--
13<?php
14if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
15require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
16$db = PDOTest::factory();
17
18class TestBase implements Serializable
19{
20    public    $BasePub = 'Public';
21    protected $BasePro = 'Protected';
22    private   $BasePri = 'Private';
23
24    function serialize()
25    {
26        $serialized = array();
27        foreach($this as $prop => $val) {
28            $serialized[$prop] = $val;
29        }
30        $serialized = serialize($serialized);
31        echo __METHOD__ . "() = '$serialized'\n";
32        return $serialized;
33    }
34
35    function unserialize($serialized)
36    {
37        echo __METHOD__ . "($serialized)\n";
38        foreach(unserialize($serialized) as $prop => $val) {
39            $this->$prop = '#'.$val;
40        }
41        return true;
42    }
43}
44
45class TestDerived extends TestBase
46{
47    public    $BasePub    = 'DerivedPublic';
48    protected $BasePro    = 'DerivdeProtected';
49    public    $DerivedPub = 'Public';
50    protected $DerivedPro = 'Protected';
51    private   $DerivedPri = 'Private';
52
53    function serialize()
54    {
55        echo __METHOD__ . "()\n";
56        return TestBase::serialize();
57    }
58
59    function unserialize($serialized)
60    {
61        echo __METHOD__ . "()\n";
62        return TestBase::unserialize($serialized);
63    }
64}
65
66class TestLeaf extends TestDerived
67{
68}
69
70$db->exec('CREATE TABLE classtypes(id int NOT NULL PRIMARY KEY, name VARCHAR(20) NOT NULL UNIQUE)');
71$db->exec('INSERT INTO classtypes VALUES(0, \'stdClass\')');
72$db->exec('INSERT INTO classtypes VALUES(1, \'TestBase\')');
73$db->exec('INSERT INTO classtypes VALUES(2, \'TestDerived\')');
74
75switch ($db->getAttribute(PDO::ATTR_DRIVER_NAME)) {
76  case 'dblib':
77    // environment settings can influence how the table is created if specifics are missing
78    // https://msdn.microsoft.com/en-us/library/ms174979.aspx#Nullability Rules Within a Table Definition
79    $sql = 'CREATE TABLE test(id int NOT NULL PRIMARY KEY, classtype int NULL, val VARCHAR(255) NULL)';
80    break;
81  default:
82    $sql = 'CREATE TABLE test(id int NOT NULL PRIMARY KEY, classtype int, val VARCHAR(255))';
83    break;
84}
85$db->exec($sql);
86
87$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
88
89var_dump($db->query('SELECT COUNT(*) FROM classtypes')->fetchColumn());
90var_dump($db->query('SELECT id, name FROM classtypes ORDER by id')->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE));
91
92$objs = array();
93$objs[0] = new stdClass;
94$objs[1] = new TestBase;
95$objs[2] = new TestDerived;
96$objs[3] = new TestLeaf;
97
98$stmt = $db->prepare('SELECT id FROM classtypes WHERE name=:cname');
99$stmt->bindParam(':cname', $cname);
100
101$ctypes = array();
102
103foreach($objs as $obj)
104{
105    $cname = get_class($obj);
106    $ctype = NULL; /* set default for non stored class name */
107    $stmt->execute();
108    $stmt->bindColumn('id', $ctype);
109    $stmt->fetch(PDO::FETCH_BOUND);
110    $ctypes[$cname] = $ctype;
111}
112
113echo "===TYPES===\n";
114var_dump($ctypes);
115
116unset($stmt);
117
118echo "===INSERT===\n";
119$stmt = $db->prepare('INSERT INTO test VALUES(:id, :classtype, :val)');
120$stmt->bindParam(':id', $idx);
121$stmt->bindParam(':classtype', $ctype);
122$stmt->bindParam(':val', $val);
123
124foreach($objs as $idx => $obj)
125{
126    $ctype = $ctypes[get_class($obj)];
127    if (method_exists($obj, 'serialize'))
128    {
129        $val = $obj->serialize();
130    }
131    else
132    {
133        $val = '';
134    }
135    $stmt->execute();
136}
137
138unset($stmt);
139
140echo "===DATA===\n";
141$res = $db->query('SELECT test.val FROM test')->fetchAll(PDO::FETCH_COLUMN);
142
143switch ($db->getAttribute(PDO::ATTR_DRIVER_NAME)) {
144    case 'dblib':
145        // map whitespace (from early TDS versions) to empty string so the test doesn't diff
146        if ($res[0] === ' ') {
147            $res[0] = '';
148        }
149        break;
150
151    case 'oci':
152        // map NULL to empty string so the test doesn't diff
153        if ($res[0] === null) {
154            $res[0] = '';
155        }
156        break;
157}
158var_dump($res);
159
160echo "===FAILURE===\n";
161try
162{
163    $db->query('SELECT classtypes.name AS name, test.val AS val FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id')->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_SERIALIZE, 'TestLeaf', array());
164}
165catch (PDOException $e)
166{
167    echo 'Exception:';
168    echo $e->getMessage()."\n";
169}
170
171echo "===COUNT===\n";
172var_dump($db->query('SELECT COUNT(*) FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id WHERE (classtypes.id IS NULL OR classtypes.id > 0)')->fetchColumn());
173
174echo "===DATABASE===\n";
175$stmt = $db->prepare('SELECT classtypes.name AS name, test.val AS val FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id WHERE (classtypes.id IS NULL OR classtypes.id > 0)');
176
177$stmt->execute();
178var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
179
180echo "===FETCHCLASS===\n";
181$stmt->execute();
182var_dump($stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_SERIALIZE, 'TestLeaf'));
183
184
185?>
186--EXPECTF--
187Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d
188
189Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d
190
191Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d
192string(1) "3"
193array(3) {
194  [0]=>
195  string(8) "stdClass"
196  [1]=>
197  string(8) "TestBase"
198  [2]=>
199  string(11) "TestDerived"
200}
201===TYPES===
202array(4) {
203  ["stdClass"]=>
204  string(1) "0"
205  ["TestBase"]=>
206  string(1) "1"
207  ["TestDerived"]=>
208  string(1) "2"
209  ["TestLeaf"]=>
210  NULL
211}
212===INSERT===
213TestBase::serialize() = 'a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}'
214TestDerived::serialize()
215TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}'
216TestDerived::serialize()
217TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}'
218===DATA===
219array(4) {
220  [0]=>
221  string(0) ""
222  [1]=>
223  string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
224  [2]=>
225  string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}"
226  [3]=>
227  string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}"
228}
229===FAILURE===
230
231Deprecated: PDOStatement::fetchAll(): The PDO::FETCH_SERIALIZE mode is deprecated in %s on line %d
232Exception:SQLSTATE[HY000]: General error: cannot unserialize class
233===COUNT===
234string(1) "3"
235===DATABASE===
236array(3) {
237  [0]=>
238  array(2) {
239    ["name"]=>
240    string(8) "TestBase"
241    ["val"]=>
242    string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
243  }
244  [1]=>
245  array(2) {
246    ["name"]=>
247    string(11) "TestDerived"
248    ["val"]=>
249    string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}"
250  }
251  [2]=>
252  array(2) {
253    ["name"]=>
254    NULL
255    ["val"]=>
256    string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";}"
257  }
258}
259===FETCHCLASS===
260
261Deprecated: PDOStatement::fetchAll(): The PDO::FETCH_SERIALIZE mode is deprecated in %s on line %d
262TestBase::unserialize(a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";})
263TestDerived::unserialize()
264TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";})
265TestDerived::unserialize()
266TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:7:"BasePri";s:7:"Private";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";})
267array(3) {
268  [0]=>
269  object(TestBase)#%d (3) {
270    ["BasePub"]=>
271    string(7) "#Public"
272    ["BasePro":protected]=>
273    string(10) "#Protected"
274    ["BasePri":"TestBase":private]=>
275    string(8) "#Private"
276  }
277  [1]=>
278  object(TestDerived)#%d (6) {
279    ["BasePub"]=>
280    string(14) "#DerivedPublic"
281    ["BasePro":protected]=>
282    string(17) "#DerivdeProtected"
283    ["BasePri":"TestBase":private]=>
284    string(8) "#Private"
285    ["DerivedPub"]=>
286    string(7) "#Public"
287    ["DerivedPro":protected]=>
288    string(10) "#Protected"
289    ["DerivedPri":"TestDerived":private]=>
290    string(7) "Private"
291  }
292  [2]=>
293  object(TestLeaf)#%d (6) {
294    ["BasePub"]=>
295    string(14) "#DerivedPublic"
296    ["BasePro":protected]=>
297    string(17) "#DerivdeProtected"
298    ["BasePri":"TestBase":private]=>
299    string(8) "#Private"
300    ["DerivedPub"]=>
301    string(7) "#Public"
302    ["DerivedPro":protected]=>
303    string(10) "#Protected"
304    ["DerivedPri":"TestDerived":private]=>
305    string(7) "Private"
306  }
307}
308