3 namespace RedUNIT\Mysql;
5 use RedUNIT\Mysql as Mysql;
6 use RedBeanPHP\Facade as R;
11 * Tests creation and validity of foreign keys,
12 * foreign key constraints and indexes in Mysql/MariaDB.
13 * Also tests whether the correct contraint action has been selected.
15 * @file RedUNIT/Mysql/Foreignkeys.php
16 * @desc Tests creation of foreign keys.
17 * @author Gabor de Mooij and the RedBeanPHP Community
18 * @license New BSD/GPLv2
20 * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
21 * This source file is subject to the New BSD/GPLv2 License that is bundled
22 * with this source code in the file license.txt.
24 class Foreignkeys extends Mysql
27 * Test whether we can use foreign keys with keywords.
31 public function testKWConflicts()
34 $metrics = R::dispense( 'metrics' );
35 $constraint = R::dispense( 'constraint' );
36 $constraint->xownMetrics[] = $metrics;
37 R::store( $constraint );
38 asrt( 1, R::count( 'metrics' ) );
39 R::trash($constraint);
40 asrt( 0, R::count( 'metrics') );
48 public function testFKS()
50 $book = R::dispense( 'book' );
51 $page = R::dispense( 'page' );
52 $cover = R::dispense( 'cover' );
54 list( $g1, $g2 ) = R::dispense( 'genre', 2 );
59 $book->ownPage = array( $page );
61 $book->cover = $cover;
63 $book->sharedGenre = array( $g1, $g2 );
67 $fkbook = R::getAll( 'describe book' );
68 $fkgenre = R::getAll( 'describe book_genre' );
69 $fkpage = R::getAll( 'describe cover' );
71 $j = json_encode( R::getAll( 'SELECT
72 ke.referenced_table_name parent,
76 information_schema.KEY_COLUMN_USAGE ke
78 ke.referenced_table_name IS NOT NULL
79 AND ke.CONSTRAINT_SCHEMA="oodb"
81 constraint_name;' ) );
86 "child": "book_genre",
87 "constraint_name": "c_fk_book_genre_genre_id"
91 "child": "book_genre",
92 "constraint_name": "c_fk_book_genre_book_id"
97 "constraint_name": "c_fk_book_cover_id"
102 "constraint_name": "c_fk_page_book_id"
106 $j1 = json_decode( $j, TRUE );
108 $j2 = json_decode( $json, TRUE );
110 foreach ( $j1 as $jrow ) {
111 $s = json_encode( $jrow );
115 foreach ( $j2 as $k => $j2row ) {
117 if ( json_encode( $j2row ) === $s ) {
127 if ( !$found ) fail();
132 * Test widen for constraint.
136 public function testWideningColumnForConstraint()
138 testpack( 'widening column for constraint' );
140 $bean1 = R::dispense( 'project' );
141 $bean2 = R::dispense( 'invoice' );
143 $bean3 = R::getRedBean()->dispense( 'invoice_project' );
145 $bean3->project_id = false;
146 $bean3->invoice_id = true;
150 $cols = R::getColumns( 'invoice_project' );
152 asrt( $cols['project_id'], "int(11) unsigned" );
153 asrt( $cols['invoice_id'], "int(11) unsigned" );
157 * Test adding of constraints directly by invoking
162 public function testContrain()
168 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
178 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
187 CREATE TABLE book_page (
188 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
189 book_id INT( 11 ) UNSIGNED NOT NULL,
190 page_id INT( 11 ) UNSIGNED NOT NULL,
198 $numOfFKS = R::getCell('
200 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
201 WHERE TABLE_NAME = "book_page" AND DELETE_RULE = "CASCADE"');
203 asrt( (int) $numOfFKS, 0 );
205 $writer = R::getWriter();
207 $writer->addFK( 'book_page', 'book', 'book_id', 'id', TRUE );
208 $writer->addFK( 'book_page', 'page', 'page_id', 'id', TRUE );
210 $numOfFKS = R::getCell('
212 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
213 WHERE TABLE_NAME = "book_page" AND DELETE_RULE = "CASCADE"');
215 asrt( (int) $numOfFKS, 2 );
217 $writer->addFK( 'book_page', 'book', 'book_id', 'id', TRUE );
218 $writer->addFK( 'book_page', 'page', 'page_id', 'id', TRUE );
220 $numOfFKS = R::getCell('
222 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
223 WHERE TABLE_NAME = "book_page" AND DELETE_RULE = "CASCADE"');
225 asrt( (int) $numOfFKS, 2 );
229 * Test adding foreign keys.
233 public function testAddingForeignKey()
239 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
249 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
250 book_id INT( 11 ) UNSIGNED NOT NULL,
258 $numOfFKS = R::getCell('
260 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
261 WHERE TABLE_NAME = "page" AND DELETE_RULE = "CASCADE"');
263 asrt( (int) $numOfFKS, 0 );
265 $writer = R::getWriter();
267 //Can we add a foreign key with cascade?
268 $writer->addFK('page', 'book', 'book_id', 'id', TRUE);
270 $numOfFKS = R::getCell('
272 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
273 WHERE TABLE_NAME = "page" AND DELETE_RULE = "CASCADE"');
275 asrt( (int) $numOfFKS, 1 );
278 $writer->addFK('page', 'book', 'book_id', 'id', TRUE);
280 $numOfFKS = R::getCell('
282 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
283 WHERE TABLE_NAME = "page" AND DELETE_RULE = "CASCADE"');
285 asrt( (int) $numOfFKS, 1 );
288 $writer->addFK('page', 'book', 'book_id', 'id', FALSE);
290 $numOfFKS = R::getCell('
292 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
293 WHERE TABLE_NAME = "page" ');
295 asrt( (int) $numOfFKS, 1 );
297 //Now add non-dep key
302 id INT( 11 ) UNSIGNED NULL AUTO_INCREMENT,
312 id INT( 11 ) UNSIGNED AUTO_INCREMENT,
313 book_id INT( 11 ) UNSIGNED NULL,
321 $numOfFKS = R::getCell('
323 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
324 WHERE TABLE_NAME = "page" AND DELETE_RULE = "CASCADE"');
326 asrt( (int) $numOfFKS, 0 );
329 $writer->addFK('page', 'book', 'book_id', 'id', FALSE);
331 $numOfFKS = R::getCell('
333 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
334 WHERE TABLE_NAME = "page" AND DELETE_RULE = "CASCADE"');
336 asrt( (int) $numOfFKS, 0 );
338 $numOfFKS = R::getCell('
340 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
341 WHERE TABLE_NAME = "page" AND DELETE_RULE = "SET NULL"');
343 asrt( (int) $numOfFKS, 1 );
345 $writer->addFK('page', 'book', 'book_id', 'id', TRUE);
347 $numOfFKS = R::getCell('
349 FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
350 WHERE TABLE_NAME = "page" ');
354 * Test whether we can manually create indexes.
358 public function testAddingIndex()
364 id INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
365 album_id INT( 11 ) UNSIGNED NOT NULL,
366 category VARCHAR( 255 ),
374 $sql = 'SHOW INDEX FROM song';
376 $indexes = R::getAll( $sql );
378 asrt( count( $indexes ), 1 );
379 asrt( $indexes[0]['Table'], 'song' );
380 asrt( $indexes[0]['Key_name'], 'PRIMARY' );
382 $writer = R::getWriter();
384 $writer->addIndex('song', 'index1', 'album_id');
386 $indexes = R::getAll( 'SHOW INDEX FROM song' );
388 asrt( count( $indexes ), 2 );
389 asrt( $indexes[0]['Table'], 'song' );
390 asrt( $indexes[0]['Key_name'], 'PRIMARY' );
391 asrt( $indexes[1]['Table'], 'song' );
392 asrt( $indexes[1]['Key_name'], 'index1' );
394 //Cant add the same index twice
395 $writer->addIndex('song', 'index2', 'category');
397 $indexes = R::getAll( 'SHOW INDEX FROM song' );
399 asrt( count( $indexes ), 3 );
401 //Dont fail, just dont
403 $writer->addIndex('song', 'index3', 'nonexistant');
405 } catch( \Exception $e ) {
409 asrt( count( $indexes ), 3 );
412 $writer->addIndex('nonexistant', 'index4', 'nonexistant');
414 } catch( \Exception $e ) {
418 asrt( count( $indexes ), 3 );
421 $writer->addIndex('nonexistant', '', 'nonexistant');
423 } catch( \Exception $e ) {
427 asrt( count( $indexes ), 3 );