Yaffs site version 1.1
[yaffs-website] / vendor / gabordemooij / redbean / testing / RedUNIT / Base / Database.php
1 <?php
2
3 namespace RedUNIT\Base;
4
5 use RedUNIT\Base as Base;
6 use RedBeanPHP\Facade as R;
7 use RedBeanPHP\QueryWriter\SQLiteT as SQLiteT;
8 use RedBeanPHP\OODB as OODB;
9 use RedBeanPHP\OODBBean as OODBBean;
10 use RedBeanPHP\ToolBox as ToolBox;
11 use RedBeanPHP\AssociationManager as AssociationManager;
12 use RedBeanPHP\RedException as RedException;
13 use RedBeanPHP\RedException\SQL as SQL;
14 use RedBeanPHP\QueryWriter\MySQL as MySQL;
15 use RedBeanPHP\QueryWriter\PostgreSQL as PostgreSQL;
16 use RedBeanPHP\QueryWriter\CUBRID as CUBRID;
17 use RedBeanPHP\Adapter\DBAdapter as DBAdapter;
18
19 /**
20  * Database
21  *
22  * Tests basic RedBeanPHP database functionality.
23  *
24  * @file    RedUNIT/Base/Database.php
25  * @desc    Tests basic database behaviors
26  * @author  Gabor de Mooij and the RedBeanPHP Community
27  * @license New BSD/GPLv2
28  *
29  * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
30  * This source file is subject to the New BSD/GPLv2 License that is bundled
31  * with this source code in the file license.txt.
32  */
33 class Database extends Base
34 {
35         /**
36          * What drivers should be loaded for this test pack?
37          */
38         public function getTargetDrivers()
39         {
40                 return array( 'mysql', 'pgsql', 'sqlite', 'CUBRID' );
41         }
42
43         /**
44          * Test setter maximum integer bindings.
45          *
46          * @return void
47          */
48         public function testSetMaxBind()
49         {
50                 $driver = R::getDatabaseAdapter()->getDatabase();
51                 $old = $driver->setMaxIntBind( 10 );
52                 //use SQLite to confirm...
53                 if ( $this->currentlyActiveDriverID === 'sqlite' ) {
54                         $type = R::getCell( 'SELECT typeof( ? ) ', array( 11 ) );
55                         asrt( $type, 'text' );
56                         $type = R::getCell( 'SELECT typeof( ? ) ', array( 10 ) );
57                         asrt( $type, 'integer' );
58                         $type = R::getCell( 'SELECT typeof( ? ) ', array( 9 ) );
59                         asrt( $type, 'integer' );
60                 }
61                 $new = $driver->setMaxIntBind( $old );
62                 asrt( $new, 10 );
63                 try {
64                         $driver->setMaxIntBind( '10' );
65                         fail();
66                 } catch( RedException $e ) {
67                         pass();
68                 }
69                 $new = $driver->setMaxIntBind( $old );
70                 asrt( $new, $old );
71                 $new = $driver->setMaxIntBind( $old );
72                 asrt( $new, $old );
73         }
74
75         /**
76          * Can we use colons in SQL?
77          *
78          * @return void
79          */
80         public function testColonsInSQL()
81         {
82                 R::nuke();
83                 $book = R::dispense( 'book' );
84                 $book->title = 'About :';
85                 R::store( $book );
86                 pass();
87                 $book = R::findOne( 'book', ' title LIKE :this ', array(
88                         ':this' => 'About :'
89                 ) );
90                 asrt( ( $book instanceof OODBBean ), TRUE );
91                 //without the colon?
92                 $book = R::findOne( 'book', ' title LIKE :this ', array(
93                         'this' => 'About :'
94                 ) );
95                 asrt( ( $book instanceof OODBBean ), TRUE );
96                 $book = R::findOne( 'book', ' title LIKE :this ', array(
97                         ':this' => '%:%'
98                 ) );
99                 asrt( ( $book instanceof OODBBean ), TRUE );
100                 $book = R::findOne( 'book', ' title LIKE :this OR title LIKE :that', array(
101                         'this' => '%:%', ':that' => 'That'
102                 ) );
103                 asrt( ( $book instanceof OODBBean ), TRUE );
104                 $records = R::getAll('SELECT * FROM book WHERE title LIKE :this', array( ':this' => 'About :' ) );
105                 asrt( count( $records ), 1 );
106                 $records = R::getAll('SELECT * FROM book WHERE title LIKE :this', array( 'this' => 'About :' ) );
107                 asrt( count( $records ), 1 );
108                 $records = R::getAll('SELECT * FROM book WHERE title LIKE :this OR title LIKE :that', array( ':this' => 'About :', ':that' => 'That' ) );
109                 asrt( count( $records ), 1 );
110                 $records = R::getRow('SELECT * FROM book WHERE title LIKE :this', array( ':this' => 'About :' ) );
111                 asrt( count( $records ), 2 );
112                 $records = R::getRow('SELECT * FROM book WHERE title LIKE :this', array( 'this' => 'About :' ) );
113                 asrt( count( $records ), 2 );
114                 $records = R::getRow('SELECT * FROM book WHERE title LIKE :this OR title LIKE :that', array( ':this' => 'About :', ':that' => 'That' ) );
115                 asrt( count( $records ), 2 );
116         }
117
118         /**
119          * Test setting direct PDO.
120          * Not much to test actually.
121          *
122          * @return void
123          */
124         public function testDirectPDO()
125         {
126                 $pdo = R::getDatabaseAdapter()->getDatabase()->getPDO();
127                 R::getDatabaseAdapter()->getDatabase()->setPDO( $pdo );
128                 pass();
129         }
130
131         /**
132          * Test for testConnection() method.
133          *
134          * @return void
135          */
136         public function testConnectionTester()
137         {
138                 asrt( R::testConnection(), TRUE );
139         }
140
141         /**
142          * Tests the various ways to fetch (select queries)
143          * data using adapter methods in the facade.
144          * Also tests the new R::getAssocRow() method,
145          * as requested in issue #324.
146          */
147         public function testFetchTypes()
148         {
149                 R::nuke();
150
151                 $page = R::dispense( 'page' );
152                 $page->a = 'a';
153                 $page->b = 'b';
154                 R::store( $page );
155
156                 $page = R::dispense( 'page' );
157                 $page->a = 'c';
158                 $page->b = 'd';
159                 R::store( $page );
160
161                 $expect = '[{"id":"1","a":"a","b":"b"},{"id":"2","a":"c","b":"d"}]';
162                 asrt( json_encode( R::getAll( 'SELECT * FROM page' ) ), $expect );
163
164                 $expect = '{"1":"a","2":"c"}';
165                 asrt( json_encode( R::getAssoc( 'SELECT id, a FROM page' ) ), $expect );
166
167                 $expect = '{"1":{"a":"a","b":"b"},"2":{"a":"c","b":"d"}}';
168                 asrt( json_encode( R::getAssoc( 'SELECT id, a, b FROM page' ) ), $expect );
169
170                 $expect = '[{"id":"1","a":"a"},{"id":"2","a":"c"}]';
171                 asrt( json_encode( R::getAssocRow( 'SELECT id, a FROM page' ) ), $expect );
172
173                 $expect = '[{"id":"1","a":"a","b":"b"},{"id":"2","a":"c","b":"d"}]';
174                 asrt( json_encode( R::getAssocRow( 'SELECT id, a, b FROM page' ) ), $expect );
175
176                 $expect = '{"id":"1","a":"a","b":"b"}';
177                 asrt( json_encode( R::getRow( 'SELECT * FROM page WHERE id = 1' ) ), $expect );
178
179                 $expect = '"a"';
180                 asrt( json_encode( R::getCell( 'SELECT a FROM page WHERE id = 1' ) ), $expect );
181
182                 $expect = '"b"';
183                 asrt( json_encode( R::getCell( 'SELECT b FROM page WHERE id = 1') ), $expect );
184
185                 $expect = '"c"';
186                 asrt( json_encode( R::getCell('SELECT a FROM page WHERE id = 2') ), $expect );
187
188                 $expect = '["a","c"]';
189                 asrt( json_encode( R::getCol( 'SELECT a FROM page' ) ), $expect );
190
191                 $expect = '["b","d"]';
192                 asrt( json_encode( R::getCol('SELECT b FROM page') ), $expect );
193         }
194
195         /**
196          * Tests whether we can store an empty bean.
197          * An empty bean has no properties, only ID. Normally we would
198          * skip the ID field in an INSERT, this test forces the driver
199          * to specify a value for the ID field. Different writers have to
200          * use different values: Mysql uses NULL to insert a new auto-generated ID,
201          * while Postgres has to use DEFAULT.
202          */
203         public function testEmptyBean()
204         {
205                 testpack( 'Test Empty Bean Storage.' );
206                 R::nuke();
207                 $bean = R::dispense( 'emptybean' );
208                 $id = R::store( $bean );
209                 asrt( ( $id > 0 ), TRUE );
210                 asrt( R::count( 'emptybean' ), 1 );
211                 $bean = R::dispense( 'emptybean' );
212                 $id = R::store( $bean );
213                 asrt( ( $id > 0 ), TRUE );
214                 asrt( R::count( 'emptybean' ), 2 );
215                 //also test in frozen mode
216                 R::freeze( TRUE );
217                 $bean = R::dispense( 'emptybean' );
218                 $id = R::store( $bean );
219                 asrt( ( $id > 0 ), TRUE );
220                 asrt( R::count( 'emptybean' ), 3 );
221                 R::freeze( FALSE );
222         }
223
224         /**
225          * Test the database driver and low level functions.
226          *
227          * @return void
228          */
229         public function testDriver()
230         {
231                 $currentDriver = $this->currentlyActiveDriverID;
232
233                 R::store( R::dispense( 'justabean' ) );
234
235                 $adapter = new TroubleDapter( R::getToolBox()->getDatabaseAdapter()->getDatabase() );
236
237                 $adapter->setSQLState( 'HY000' );
238
239                 $writer  = new SQLiteT( $adapter );
240                 $redbean = new OODB( $writer );
241                 $toolbox = new ToolBox( $redbean, $adapter, $writer );
242
243                 // We can only test this for a known driver...
244                 if ( $currentDriver === 'sqlite' ) {
245                         try {
246                                 $redbean->find( 'bean' );
247
248                                 pass();
249                         } catch (\Exception $e ) {
250                                 var_dump( $e->getSQLState() );
251
252                                 fail();
253                         }
254                 }
255
256                 $adapter->setSQLState( -999 );
257
258                 try {
259                         $redbean->find( 'bean' );
260
261                         fail();
262                 } catch (\Exception $e ) {
263                         pass();
264                 }
265
266                 try {
267                         $redbean->wipe( 'justabean' );
268
269                         fail();
270                 } catch (\Exception $e ) {
271                         pass();
272                 }
273
274                 $toolbox = R::getToolBox();
275                 $adapter = $toolbox->getDatabaseAdapter();
276                 $writer  = $toolbox->getWriter();
277                 $redbean = $toolbox->getRedBean();
278                 $pdo     = $adapter->getDatabase();
279
280                 $page = $redbean->dispense( "page" );
281
282                 try {
283                         $adapter->exec( "an invalid query" );
284                         fail();
285                 } catch ( SQL $e ) {
286                         pass();
287                 }
288
289                 // Special data type description should result in magic number 99 (specified)
290                 if ( $currentDriver == 'mysql' ) {
291                         asrt( $writer->code( MySQL::C_DATATYPE_SPECIAL_DATE ), 99 );
292                 }
293
294                 if ( $currentDriver == 'pgsql' ) {
295                         asrt( $writer->code( PostgreSQL::C_DATATYPE_SPECIAL_DATE ), 99 );
296                 }
297
298                 if ( $currentDriver == 'CUBRID' ) {
299                         asrt( $writer->code( CUBRID::C_DATATYPE_SPECIAL_DATE ), 99 );
300                 }
301
302                 asrt( (int) $adapter->getCell( "SELECT 123" ), 123 );
303
304                 $page->aname = "my page";
305
306                 $id = (int) $redbean->store( $page );
307
308                 asrt( (int) $page->id, 1 );
309                 asrt( (int) $pdo->GetCell( "SELECT count(*) FROM page" ), 1 );
310                 asrt( $pdo->GetCell( "SELECT aname FROM page LIMIT 1" ), "my page" );
311                 asrt( (int) $id, 1 );
312
313                 $page = $redbean->load( "page", 1 );
314
315                 asrt( $page->aname, "my page" );
316                 asrt( ( (bool) $page->getMeta( "type" ) ), TRUE );
317                 asrt( isset( $page->id ), TRUE );
318                 asrt( ( $page->getMeta( "type" ) ), "page" );
319                 asrt( (int) $page->id, $id );
320         }
321
322         /**
323          * Test selecting.
324          *
325          * @return void
326          */
327         public function testSelects()
328         {
329                 $rooms = R::dispense( 'room', 2 );
330
331                 $rooms[0]->kind   = 'suite';
332                 $rooms[1]->kind   = 'classic';
333                 $rooms[0]->number = 6;
334                 $rooms[1]->number = 7;
335
336                 R::store( $rooms[0] );
337                 R::store( $rooms[1] );
338
339                 $rooms = R::getAssoc('SELECT * FROM room WHERE id < -999');
340                 asrt(is_array($rooms), TRUE);
341                 asrt(count($rooms), 0);
342
343                 $rooms = R::getAssoc( 'SELECT ' . R::getWriter()->esc( 'number' ) . ', kind FROM room ORDER BY kind ASC' );
344
345                 foreach ( $rooms as $key => $room ) {
346                         asrt( ( $key === 6 || $key === 7 ), TRUE );
347                         asrt( ( $room == 'classic' || $room == 'suite' ), TRUE );
348                 }
349
350                 $rooms = R::getDatabaseAdapter()->getAssoc( 'SELECT kind FROM room' );
351                 foreach ( $rooms as $key => $room ) {
352                         asrt( ( $room == 'classic' || $room == 'suite' ), TRUE );
353                         asrt( $room, $key );
354                 }
355
356                 $rooms = R::getAssoc( 'SELECT `number`, kind FROM rooms2 ORDER BY kind ASC' );
357
358                 asrt( count( $rooms ), 0 );
359                 asrt( is_array( $rooms ), TRUE );
360
361                 // GetCell should return NULL in case of exception
362                 asrt( NULL, R::getCell( 'SELECT dream FROM fantasy' ) );
363         }
364 }
365
366 /**
367  * Malfunctioning database adapter to test exceptions.
368  */
369 class TroubleDapter extends DBAdapter
370 {
371         private $sqlState;
372
373         public function setSQLState( $sqlState )
374         {
375                 $this->sqlState = $sqlState;
376         }
377
378         public function get( $sql, $values = array() )
379         {
380                 $exception = new SQL( 'Just a trouble maker' );
381                 $exception->setSQLState( $this->sqlState );
382                 throw $exception;
383         }
384
385         public function getRow( $sql, $aValues = array() )
386         {
387                 $this->get( $sql, $aValues );
388         }
389
390         public function exec( $sql, $aValues = array(), $noEvent = FALSE )
391         {
392                 $this->get( $sql, $aValues );
393         }
394 }
395