1--TEST--
2PDO::ATTR_STATEMENT_CLASS
3--SKIPIF--
4<?php
5require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
6require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
7MySQLPDOTest::skip();
8$db = MySQLPDOTest::factory();
9?>
10--FILE--
11<?php
12	require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
13	$db = MySQLPDOTest::factory();
14	MySQLPDOTest::createTestTable($db);
15
16	$default =  $db->getAttribute(PDO::ATTR_STATEMENT_CLASS);
17	var_dump($default);
18
19	if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS)))
20		printf("[001] Expecting boolean/false got %s\n", var_export($tmp, true));
21
22	if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'foo')))
23		printf("[002] Expecting boolean/false got %s\n", var_export($tmp, true));
24
25	if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname'))))
26		printf("[003] Expecting boolean/false got %s\n", var_export($tmp, true));
27
28	// unknown class
29	if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname', array()))))
30		printf("[004] Expecting boolean/false got %s\n", var_export($tmp, true));
31
32	// class not derived from PDOStatement
33	class myclass {
34		function __construct() {
35			printf("myclass\n");
36		}
37	}
38	if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('myclass', array()))))
39		printf("[005] Expecting boolean/false got %s\n", var_export($tmp, true));
40
41	// public constructor not allowed
42	class mystatement extends PDOStatement {
43		public function __construct() {
44			printf("mystatement\n");
45		}
46	}
47
48	if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement', array()))))
49		printf("[006] Expecting boolean/false got %s\n", var_export($tmp, true));
50
51	// ... but a public destructor is allowed
52	class mystatement2 extends PDOStatement {
53		public function __destruct() {
54			printf("mystatement\n");
55		}
56	}
57
58	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement2', array()))))
59		printf("[007] Expecting boolean/true got %s\n", var_export($tmp, true));
60
61	// private constructor
62	class mystatement3 extends PDOStatement {
63		private function __construct($msg) {
64			printf("mystatement3\n");
65			var_dump($msg);
66		}
67	}
68	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement3', array('param1')))))
69		printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true));
70
71	// private constructor
72	class mystatement4 extends PDOStatement {
73		private function __construct($msg) {
74			printf("%s\n", get_class($this));
75			var_dump($msg);
76		}
77	}
78	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement4', array('param1')))))
79		printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true));
80
81	var_dump($db->getAttribute(PDO::ATTR_STATEMENT_CLASS));
82	$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2');
83
84	class mystatement5 extends mystatement4 {
85		public function fetchAll($fetch_style = 1, $column_index = 1, $ctor_args = array()) {
86			return "no data :)";
87		}
88	}
89
90	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement5', array('mystatement5')))))
91		printf("[009] Expecting boolean/true got %s\n", var_export($tmp, true));
92	$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2');
93	var_dump($stmt->fetchAll());
94
95	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement'))))
96		printf("[010] Expecting boolean/true got %s\n", var_export($tmp, true));
97
98	$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1');
99	var_dump($stmt->fetchAll());
100
101	// Yes, this is a fatal error and I want it to fail.
102	abstract class mystatement6 extends mystatement5 {
103	}
104	if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement6', array('mystatement6')))))
105		printf("[011] Expecting boolean/true got %s\n", var_export($tmp, true));
106	$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1');
107
108	print "done!";
109?>
110--EXPECTF--
111array(1) {
112  [0]=>
113  string(12) "PDOStatement"
114}
115
116Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); the classname must be a string specifying an existing class in %s on line %d
117
118Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
119
120Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: user-supplied statement class must be derived from PDOStatement in %s on line %d
121
122Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
123
124Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error: user-supplied statement class cannot have a public constructor in %s on line %d
125
126Warning: PDO::setAttribute(): SQLSTATE[HY000]: General error in %s on line %d
127array(2) {
128  [0]=>
129  string(12) "mystatement4"
130  [1]=>
131  array(1) {
132    [0]=>
133    string(6) "param1"
134  }
135}
136mystatement4
137string(6) "param1"
138mystatement5
139string(12) "mystatement5"
140string(10) "no data :)"
141array(1) {
142  [0]=>
143  array(4) {
144    ["id"]=>
145    string(1) "1"
146    [0]=>
147    string(1) "1"
148    ["label"]=>
149    string(1) "a"
150    [1]=>
151    string(1) "a"
152  }
153}
154
155Fatal error: Uncaught Error: Cannot instantiate abstract class mystatement6 in %s:%d
156Stack trace:
157#0 %s(%d): PDO->query('SELECT id, labe...')
158#1 {main}
159  thrown in %s on line %d
160