3 namespace RedUNIT\Postgres;
5 use RedUNIT\Postgres as Postgres;
6 use RedBeanPHP\Facade as R;
11 * Tests creation and validity of foreign keys,
12 * foreign key constraints and indexes in PostgreSQL.
13 * Also tests whether the correct contraint action has been selected.
15 * @file RedUNIT/Postgres/Foreignkeys.php
16 * @desc Tests the 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 Postgres
27 * Test foreign keys with postgres.
29 public function testForeignKeysWithPostgres()
31 testpack( 'Test Postgres Foreign keys' );
32 $a = R::getWriter()->addFK( 'a', 'b', 'c', 'd' ); //must fail
33 pass(); //survive without exception
34 asrt( $a, FALSE ); //must return false
35 $book = R::dispense( 'book' );
36 $page = R::dispense( 'page' );
37 $cover = R::dispense( 'cover' );
38 list( $g1, $g2 ) = R::dispense( 'genre', 2 );
41 $book->ownPage = array( $page );
42 $book->cover = $cover;
43 $book->sharedGenre = array( $g1, $g2 );
46 tc.constraint_name, tc.table_name, kcu.column_name,
47 ccu.table_name AS foreign_table_name,
48 ccu.column_name AS foreign_column_name
50 information_schema.table_constraints AS tc
51 JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
52 JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
53 WHERE constraint_type = 'FOREIGN KEY' AND (tc.table_name='book' OR tc.table_name='book_genre' OR tc.table_name='page');";
54 $fks = R::getAll( $sql );
57 "constraint_name": "book_cover_id_fkey",
59 "column_name": "cover_id",
60 "foreign_table_name": "cover",
61 "foreign_column_name": "id"
64 "constraint_name": "page_book_id_fkey",
66 "column_name": "book_id",
67 "foreign_table_name": "book",
68 "foreign_column_name": "id"
71 "constraint_name": "book_genre_genre_id_fkey",
72 "table_name": "book_genre",
73 "column_name": "genre_id",
74 "foreign_table_name": "genre",
75 "foreign_column_name": "id"
78 "constraint_name": "book_genre_book_id_fkey",
79 "table_name": "book_genre",
80 "column_name": "book_id",
81 "foreign_table_name": "book",
82 "foreign_column_name": "id"
85 $j = json_encode( $fks );
86 $j1 = json_decode( $j, TRUE );
87 $j2 = json_decode( $json, TRUE );
88 foreach ( $j1 as $jrow ) {
89 $s = json_encode( $jrow );
91 foreach ( $j2 as $k => $j2row ) {
92 if ( json_encode( $j2row ) === $s ) {
98 if ( !$found ) fail();
103 * Test constraint function directly in Writer.
107 public function testConstraint()
110 $database = R::getCell('SELECT current_database()');
111 $sql = 'CREATE TABLE book (id SERIAL PRIMARY KEY)';
113 $sql = 'CREATE TABLE page (id SERIAL PRIMARY KEY)';
115 $sql = 'CREATE TABLE book_page (
116 id SERIAL PRIMARY KEY,
121 $writer = R::getWriter();
125 FROM information_schema.key_column_usage AS k
126 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
127 WHERE k.table_catalog = '$database'
128 AND k.table_schema = 'public'
129 AND k.table_name = 'book_page'
130 AND c.constraint_type = 'FOREIGN KEY'";
131 $numFKS = R::getCell( $sql );
132 asrt( (int) $numFKS, 0 );
133 $writer->addFK( 'book_page', 'book', 'book_id', 'id', TRUE );
134 $writer->addFK( 'book_page', 'page', 'page_id', 'id', TRUE );
135 $numFKS = R::getCell( $sql );
136 asrt( (int) $numFKS, 2 );
137 $writer->addFK( 'book_page', 'book', 'book_id', 'id', TRUE );
138 $writer->addFK( 'book_page', 'page', 'page_id', 'id', TRUE );
139 $numFKS = R::getCell( $sql );
140 asrt( (int) $numFKS, 2 );
144 * Test adding foreign keys.
148 public function testAddingForeignKey()
151 $database = R::getCell('SELECT current_database()');
152 $sql = 'CREATE TABLE book (
153 id SERIAL PRIMARY KEY
156 $sql = 'CREATE TABLE page (
157 id SERIAL PRIMARY KEY,
161 $writer = R::getWriter();
165 FROM information_schema.key_column_usage AS k
166 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
167 WHERE k.table_catalog = '$database'
168 AND k.table_schema = 'public'
169 AND k.table_name = 'page'
170 AND c.constraint_type = 'FOREIGN KEY'";
171 $numFKS = R::getCell( $sql );
172 asrt( (int) $numFKS, 0 );
173 $writer->addFK('page', 'page', 'book_id', 'id', TRUE);
177 FROM information_schema.key_column_usage AS k
178 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
179 WHERE k.table_catalog = '$database'
180 AND k.table_schema = 'public'
181 AND k.table_name = 'page'
182 AND c.constraint_type = 'FOREIGN KEY'";
183 $numFKS = R::getCell( $sql );
184 asrt( (int) $numFKS, 1 );
186 $writer->addFK('page', 'page', 'book_id', 'id', TRUE);
190 FROM information_schema.key_column_usage AS k
191 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
192 WHERE k.table_catalog = '$database'
193 AND k.table_schema = 'public'
194 AND k.table_name = 'page'
195 AND c.constraint_type = 'FOREIGN KEY'";
196 $numFKS = R::getCell( $sql );
197 asrt( (int) $numFKS, 1 );
198 //even if it is different
199 $writer->addFK('page', 'page', 'book_id', 'id', FALSE);
203 FROM information_schema.key_column_usage AS k
204 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
205 WHERE k.table_catalog = '$database'
206 AND k.table_schema = 'public'
207 AND k.table_name = 'page'
208 AND c.constraint_type = 'FOREIGN KEY'";
209 $numFKS = R::getCell( $sql );
210 asrt( (int) $numFKS, 1 );
212 $sql = 'CREATE TABLE book (
213 id SERIAL PRIMARY KEY
216 $sql = 'CREATE TABLE page (
217 id SERIAL PRIMARY KEY,
221 $writer = R::getWriter();
225 FROM information_schema.key_column_usage AS k
226 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
227 WHERE k.table_catalog = '$database'
228 AND k.table_schema = 'public'
229 AND k.table_name = 'page'
230 AND c.constraint_type = 'FOREIGN KEY'";
231 $numFKS = R::getCell( $sql );
232 asrt( (int) $numFKS, 0 );
233 $writer->addFK('page', 'page', 'book_id', 'id', FALSE);
237 FROM information_schema.key_column_usage AS k
238 LEFT JOIN information_schema.table_constraints AS c ON c.constraint_name = k.constraint_name
239 WHERE k.table_catalog = '$database'
240 AND k.table_schema = 'public'
241 AND k.table_name = 'page'
242 AND c.constraint_type = 'FOREIGN KEY'";
243 $numFKS = R::getCell( $sql );
244 asrt( (int) $numFKS, 1 );
248 * Test whether we can manually create indexes.
252 public function testAddingIndex()
255 $sql = 'CREATE TABLE song (
256 id SERIAL PRIMARY KEY,
258 category VARCHAR(255)
261 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
262 asrt( count( $indexes ), 1 );
263 $writer = R::getWriter();
264 $writer->addIndex( 'song', 'index1', 'album_id' );
265 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
266 asrt( count( $indexes ), 2 );
267 //Cant add the same index twice
268 $writer->addIndex( 'song', 'index1', 'album_id' );
269 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
270 asrt( count( $indexes ), 2 );
271 $writer->addIndex( 'song', 'index2', 'category' );
272 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
273 asrt( count( $indexes ), 3 );
274 //Dont fail, just dont
276 $writer->addIndex( 'song', 'index3', 'nonexistant' );
278 } catch( \Exception $e ) {
281 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
282 asrt( count( $indexes ), 3 );
284 $writer->addIndex( 'nonexistant', 'index4', 'nonexistant' );
286 } catch( \Exception $e ) {
289 $indexes = R::getAll( " SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'song' ");
290 asrt( count( $indexes ), 3 );