xref: /PHP-7.2/ext/pdo/tests/pdo_018.phpt (revision 7af945e2)
1--TEST--
2PDO Common: serializing
3--SKIPIF--
4<?php # vim:ft=php
5if (!extension_loaded('pdo')) die('skip');
6if (!interface_exists('Serializable')) die('skip no Serializable interface');
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='.dirname(__FILE__) . '/../../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--
187string(1) "3"
188array(3) {
189  [0]=>
190  string(8) "stdClass"
191  [1]=>
192  string(8) "TestBase"
193  [2]=>
194  string(11) "TestDerived"
195}
196===TYPES===
197array(4) {
198  ["stdClass"]=>
199  string(1) "0"
200  ["TestBase"]=>
201  string(1) "1"
202  ["TestDerived"]=>
203  string(1) "2"
204  ["TestLeaf"]=>
205  NULL
206}
207===INSERT===
208TestBase::serialize() = 'a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}'
209TestDerived::serialize()
210TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}'
211TestDerived::serialize()
212TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}'
213===DATA===
214array(4) {
215  [0]=>
216  string(0) ""
217  [1]=>
218  string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
219  [2]=>
220  string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
221  [3]=>
222  string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
223}
224===FAILURE===
225Exception:SQLSTATE[HY000]: General error: cannot unserialize class
226===COUNT===
227string(1) "3"
228===DATABASE===
229array(3) {
230  [0]=>
231  array(2) {
232    ["name"]=>
233    string(8) "TestBase"
234    ["val"]=>
235    string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
236  }
237  [1]=>
238  array(2) {
239    ["name"]=>
240    string(11) "TestDerived"
241    ["val"]=>
242    string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
243  }
244  [2]=>
245  array(2) {
246    ["name"]=>
247    NULL
248    ["val"]=>
249    string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}"
250  }
251}
252===FETCHCLASS===
253TestBase::unserialize(a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";})
254TestDerived::unserialize()
255TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";})
256TestDerived::unserialize()
257TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";})
258array(3) {
259  [0]=>
260  object(TestBase)#%d (3) {
261    ["BasePub"]=>
262    string(7) "#Public"
263    ["BasePro":protected]=>
264    string(10) "#Protected"
265    ["BasePri":"TestBase":private]=>
266    string(8) "#Private"
267  }
268  [1]=>
269  object(TestDerived)#%d (6) {
270    ["BasePub"]=>
271    string(14) "#DerivedPublic"
272    ["BasePro":protected]=>
273    string(17) "#DerivdeProtected"
274    ["DerivedPub"]=>
275    string(7) "#Public"
276    ["DerivedPro":protected]=>
277    string(10) "#Protected"
278    ["DerivedPri":"TestDerived":private]=>
279    string(7) "Private"
280    ["BasePri":"TestBase":private]=>
281    string(8) "#Private"
282  }
283  [2]=>
284  object(TestLeaf)#%d (6) {
285    ["BasePub"]=>
286    string(14) "#DerivedPublic"
287    ["BasePro":protected]=>
288    string(17) "#DerivdeProtected"
289    ["DerivedPub"]=>
290    string(7) "#Public"
291    ["DerivedPro":protected]=>
292    string(10) "#Protected"
293    ["DerivedPri":"TestDerived":private]=>
294    string(7) "Private"
295    ["BasePri":"TestBase":private]=>
296    string(8) "#Private"
297  }
298}
299