Passed
Push — develop ( a33225...c5f03c )
by Felipe
09:45
created

IndexTrait::dropConstraint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 4
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.47
5
 */
6
7
namespace PHPPgAdmin\DatabaseTraits;
8
9
/**
10
 * Common trait for indexes and constraints manipulation.
11
 */
12
trait IndexTrait
13
{
14
    /**
15
     * Test if a table has been clustered on an index.
16
     *
17
     * @param string $table The table to test
18
     *
19
     * @return bool true if the table has been already clustered
20
     */
21
    public function alreadyClustered($table)
22
    {
23
        $c_schema = $this->_schema;
24
        $this->clean($c_schema);
25
        $this->clean($table);
26
27
        $sql = "SELECT i.indisclustered
28
			FROM pg_catalog.pg_class c, pg_catalog.pg_index i
29
			WHERE c.relname = '{$table}'
30
				AND c.oid = i.indrelid AND i.indisclustered
31
				AND c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
32
					WHERE nspname='{$c_schema}')
33
				";
34
35
        $v = $this->selectSet($sql);
36
37
        return !($v->RecordCount() == 0);
38
    }
39
40
    /**
41
     * Creates an index.
42
     *
43
     * @param string       $name         The index name (can be blank)
44
     * @param string       $table        The table on which to add the index
45
     * @param array|string $columns      An array of columns that form the index  or a string expression for a functional index
46
     * @param string       $type         The index type
47
     * @param bool         $unique       True if unique, false otherwise
48
     * @param string       $where        Index predicate ('' for none)
49
     * @param string       $tablespace   The tablespaces ('' means none/default)
50
     * @param bool         $concurrently true to create index concurrently
51
     *
52
     * @return array status (0 if operation was successful) and sql sentence
53
     */
54
    public function createIndex($name, $table, $columns, $type, $unique, $where, $tablespace, $concurrently)
55
    {
56
        $f_schema = $this->_schema;
57
        $this->fieldClean($f_schema);
58
        $this->fieldClean($name);
59
        $this->fieldClean($table);
60
61
        $sql = 'CREATE ';
62
63
        $sql .= $unique ? ' UNIQUE ' : '';
64
65
        $sql .= ' INDEX ';
66
67
        $sql .= $concurrently ? ' CONCURRENTLY ' : '';
68
69
        $sql .= $name ? "  \"{$name}\" " : '';
70
71
        $sql .= " ON \"{$f_schema}\".\"{$table}\" USING {$type} ";
72
73
        if (is_array($columns)) {
74
            $this->arrayClean($columns);
75
            $sql .= '("' . implode('","', $columns) . '")';
76
        } else {
77
            $sql .= '(' . $columns . ')';
78
        }
79
80
        // Tablespace
81
        if ($this->hasTablespaces() && $tablespace != '') {
82
            $this->fieldClean($tablespace);
83
            $sql .= " TABLESPACE \"{$tablespace}\"";
84
        }
85
86
        // Predicate
87
        if (trim($where) != '') {
88
            $sql .= " WHERE ({$where})";
89
        }
90
91
        $status = $this->execute($sql);
92
93
        return [$status, $sql];
94
    }
95
96
    /**
97
     * Removes an index from the database.
98
     *
99
     * @param string $index   The index to drop
100
     * @param bool   $cascade True to cascade drop, false to restrict
101
     *
102
     * @return array<integer,mixed|string> 0 if operation was successful
103
     */
104
    public function dropIndex($index, $cascade)
105
    {
106
        $f_schema = $this->_schema;
107
        $this->fieldClean($f_schema);
108
        $this->fieldClean($index);
109
110
        $sql = "DROP INDEX \"{$f_schema}\".\"{$index}\"";
111
        if ($cascade) {
112
            $sql .= ' CASCADE';
113
        }
114
115
        $status = $this->execute($sql);
116
117
        return [$status, $sql];
118
    }
119
120
    /**
121
     * Rebuild indexes.
122
     *
123
     * @param string $type  'DATABASE' or 'TABLE' or 'INDEX'
124
     * @param string $name  The name of the specific database, table, or index to be reindexed
125
     * @param bool   $force If true, recreates indexes forcedly in PostgreSQL 7.0-7.1, forces rebuild of system indexes in
126
     *                      7.2-7.3, ignored in >=7.4
127
     *
128
     * @return int 0 if operation was successful
129
     */
130
    public function reindex($type, $name, $force = false)
131
    {
132
        $f_schema = $this->_schema;
133
        $this->fieldClean($f_schema);
134
        $this->fieldClean($name);
135
        switch ($type) {
136
            case 'DATABASE':
137
                $sql = "REINDEX {$type} \"{$name}\"";
138
                if ($force) {
139
                    $sql .= ' FORCE';
140
                }
141
142
                break;
143
            case 'TABLE':
144
            case 'INDEX':
145
                $sql = "REINDEX {$type} \"{$f_schema}\".\"{$name}\"";
146
                if ($force) {
147
                    $sql .= ' FORCE';
148
                }
149
150
                break;
151
            default:
152
                return -1;
153
        }
154
155
        return $this->execute($sql);
156
    }
157
158
    /**
159
     * Clusters an index.
160
     *
161
     * @param string $table The table the index is on
162
     * @param string $index The name of the index
163
     *
164
     * @return array<integer,mixed|string> 0 if operation was successful
165
     */
166
    public function clusterIndex($table = '', $index = '')
167
    {
168
        $sql = 'CLUSTER';
169
170
        // We don't bother with a transaction here, as there's no point rolling
171
        // back an expensive cluster if a cheap analyze fails for whatever reason
172
173
        if (!empty($table)) {
174
            $f_schema = $this->_schema;
175
            $this->fieldClean($f_schema);
176
            $this->fieldClean($table);
177
            $sql .= " \"{$f_schema}\".\"{$table}\"";
178
179
            if (!empty($index)) {
180
                $this->fieldClean($index);
181
                $sql .= " USING \"{$index}\"";
182
            }
183
        }
184
185
        $status = $this->execute($sql);
186
187
        return [$status, $sql];
188
    }
189
190
    /**
191
     * Returns a list of all constraints on a table,
192
     * including constraint name, definition, related col and referenced namespace,
193
     * table and col if needed.
194
     *
195
     * @param string $table the table where we are looking for fk
196
     *
197
     * @return \PHPPgAdmin\ADORecordSet A recordset
198
     */
199
    public function getConstraintsWithFields($table)
200
    {
201
        $c_schema = $this->_schema;
202
        $this->clean($c_schema);
203
        $this->clean($table);
204
205
        // get the max number of col used in a constraint for the table
206
        $sql = "SELECT DISTINCT
207
			max(SUBSTRING(array_dims(c.conkey) FROM  \$patern\$^\\[.*:(.*)\\]$\$patern\$)) as nb
208
		FROM pg_catalog.pg_constraint AS c
209
			JOIN pg_catalog.pg_class AS r ON (c.conrelid=r.oid)
210
			JOIN pg_catalog.pg_namespace AS ns ON (r.relnamespace=ns.oid)
211
		WHERE
212
			r.relname = '{$table}' AND ns.nspname='{$c_schema}'";
213
214
        $rs = $this->selectSet($sql);
215
216
        if ($rs->EOF) {
217
            $max_col = 0;
1 ignored issue
show
Unused Code introduced by
The assignment to $max_col is dead and can be removed.
Loading history...
218
        } else {
219
            $max_col = $rs->fields['nb'];
220
        }
221
222
        $sql = '
223
			SELECT
224
				c.oid AS conid, c.contype, c.conname, pg_catalog.pg_get_constraintdef(c.oid, true) AS consrc,
225
				ns1.nspname as p_schema, r1.relname as p_table, ns2.nspname as f_schema,
226
				r2.relname as f_table, f1.attname as p_field, f1.attnum AS p_attnum, f2.attname as f_field,
227
				f2.attnum AS f_attnum, pg_catalog.obj_description(c.oid, \'pg_constraint\') AS constcomment,
228
				c.conrelid, c.confrelid
229
			FROM
230
				pg_catalog.pg_constraint AS c
231
				JOIN pg_catalog.pg_class AS r1 ON (c.conrelid=r1.oid)
232
				JOIN pg_catalog.pg_attribute AS f1 ON (f1.attrelid=r1.oid AND (f1.attnum=c.conkey[1]';
233
        for ($i = 2; $i <= $rs->fields['nb']; ++$i) {
234
            $sql .= " OR f1.attnum=c.conkey[${i}]";
235
        }
236
        $sql .= '))
237
				JOIN pg_catalog.pg_namespace AS ns1 ON r1.relnamespace=ns1.oid
238
				LEFT JOIN (
239
					pg_catalog.pg_class AS r2 JOIN pg_catalog.pg_namespace AS ns2 ON (r2.relnamespace=ns2.oid)
240
				) ON (c.confrelid=r2.oid)
241
				LEFT JOIN pg_catalog.pg_attribute AS f2 ON
242
					(f2.attrelid=r2.oid AND ((c.confkey[1]=f2.attnum AND c.conkey[1]=f1.attnum)';
243
        for ($i = 2; $i <= $rs->fields['nb']; ++$i) {
244
            $sql .= " OR (c.confkey[${i}]=f2.attnum AND c.conkey[${i}]=f1.attnum)";
245
        }
246
247
        $sql .= sprintf("))
248
			WHERE
249
				r1.relname = '%s' AND ns1.nspname='%s'
250
			ORDER BY 1", $table, $c_schema);
251
252
        return $this->selectSet($sql);
253
    }
254
255
    /**
256
     * Adds a primary key constraint to a table.
257
     *
258
     * @param string $table      The table to which to add the primery key
259
     * @param array  $fields     (array) An array of fields over which to add the primary key
260
     * @param string $name       (optional) The name to give the key, otherwise default name is assigned
261
     * @param string $tablespace (optional) The tablespace for the schema, '' indicates default
262
     *
263
     * @return int 0 if operation was successful
264
     */
265
    public function addPrimaryKey($table, $fields, $name = '', $tablespace = '')
266
    {
267
        if (!is_array($fields) || sizeof($fields) == 0) {
1 ignored issue
show
introduced by
The condition is_array($fields) is always true.
Loading history...
268
            return -1;
269
        }
270
271
        $f_schema = $this->_schema;
272
        $this->fieldClean($f_schema);
273
        $this->fieldClean($table);
274
        $this->fieldArrayClean($fields);
275
        $this->fieldClean($name);
276
        $this->fieldClean($tablespace);
277
278
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
279
        if ($name != '') {
280
            $sql .= "CONSTRAINT \"{$name}\" ";
281
        }
282
283
        $sql .= 'PRIMARY KEY ("' . join('","', $fields) . '")';
284
285
        if ($tablespace != '' && $this->hasTablespaces()) {
286
            $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
287
        }
288
289
        return $this->execute($sql);
290
    }
291
292
    /**
293
     * Adds a unique constraint to a table.
294
     *
295
     * @param string      $table      The table to which to add the unique key
296
     * @param array|mixed $fields     (array) An array of fields over which to add the unique key
297
     * @param string      $name       (optional) The name to give the key, otherwise default name is assigned
298
     * @param string      $tablespace (optional) The tablespace for the schema, '' indicates default
299
     *
300
     * @return int 0 if operation was successful
301
     */
302
    public function addUniqueKey($table, $fields, $name = '', $tablespace = '')
303
    {
304
        if (!is_array($fields) || sizeof($fields) == 0) {
305
            return -1;
306
        }
307
308
        $f_schema = $this->_schema;
309
        $this->fieldClean($f_schema);
310
        $this->fieldClean($table);
311
        $this->fieldArrayClean($fields);
312
        $this->fieldClean($name);
313
        $this->fieldClean($tablespace);
314
315
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
316
        if ($name != '') {
317
            $sql .= "CONSTRAINT \"{$name}\" ";
318
        }
319
320
        $sql .= 'UNIQUE ("' . join('","', $fields) . '")';
321
322
        if ($tablespace != '' && $this->hasTablespaces()) {
323
            $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
324
        }
325
326
        return $this->execute($sql);
327
    }
328
329
    // Function functions
330
331
    /**
332
     * Adds a check constraint to a table.
333
     *
334
     * @param string $table      The table to which to add the check
335
     * @param string $definition The definition of the check
336
     * @param string $name       (optional) The name to give the check, otherwise default name is assigned
337
     *
338
     * @return int 0 if operation was successful
339
     */
340
    public function addCheckConstraint($table, $definition, $name = '')
341
    {
342
        $f_schema = $this->_schema;
343
        $this->fieldClean($f_schema);
344
        $this->fieldClean($table);
345
        $this->fieldClean($name);
346
        // @@ How the heck do you clean a definition???
347
348
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
349
        if ($name != '') {
350
            $sql .= "CONSTRAINT \"{$name}\" ";
351
        }
352
353
        $sql .= "CHECK ({$definition})";
354
355
        return $this->execute($sql);
356
    }
357
358
    /**
359
     * Drops a check constraint from a table.
360
     *
361
     * @param string $table The table from which to drop the check
362
     * @param string $name  The name of the check to be dropped
363
     *
364
     * @return bool|int 0 success
365
     */
366
    public function dropCheckConstraint($table, $name)
367
    {
368
        $f_schema = $this->_schema;
369
        $this->fieldClean($f_schema);
370
        $c_schema = $this->_schema;
371
        $this->clean($c_schema);
372
        $c_table = $table;
373
        $this->fieldClean($table);
374
        $this->clean($c_table);
375
        $this->clean($name);
376
377
        // Begin transaction
378
        $status = $this->beginTransaction();
379
        if ($status != 0) {
380
            return -2;
381
        }
382
383
        // Properly lock the table
384
        $sql    = "LOCK TABLE \"{$f_schema}\".\"{$table}\" IN ACCESS EXCLUSIVE MODE";
385
        $status = $this->execute($sql);
386
        if ($status != 0) {
387
            $this->rollbackTransaction();
388
389
            return -3;
390
        }
391
392
        // Delete the check constraint
393
        $sql = "DELETE FROM pg_relcheck WHERE rcrelid=(SELECT oid FROM pg_catalog.pg_class WHERE relname='{$c_table}'
394
			AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
395
			nspname = '{$c_schema}')) AND rcname='{$name}'";
396
        $status = $this->execute($sql);
397
        if ($status != 0) {
398
            $this->rollbackTransaction();
399
400
            return -4;
401
        }
402
403
        // Update the pg_class catalog to reflect the new number of checks
404
        $sql = "UPDATE pg_class SET relchecks=(SELECT COUNT(*) FROM pg_relcheck WHERE
405
					rcrelid=(SELECT oid FROM pg_catalog.pg_class WHERE relname='{$c_table}'
406
						AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
407
						nspname = '{$c_schema}')))
408
					WHERE relname='{$c_table}'";
409
        $status = $this->execute($sql);
410
        if ($status != 0) {
411
            $this->rollbackTransaction();
412
413
            return -4;
414
        }
415
416
        // Otherwise, close the transaction
417
        return $this->endTransaction();
418
    }
419
420
    /**
421
     * Adds a foreign key constraint to a table.
422
     *
423
     * @param string $table      The table on which to add an FK
424
     * @param string $targschema The schema that houses the target table to which to add the foreign key
425
     * @param string $targtable  The table to which to add the foreign key
426
     * @param array  $sfields    (array) An array of source fields over which to add the foreign key
427
     * @param array  $tfields    (array) An array of target fields over which to add the foreign key
428
     * @param string $upd_action The action for updates (eg. RESTRICT)
429
     * @param string $del_action The action for deletes (eg. RESTRICT)
430
     * @param string $match      The match type (eg. MATCH FULL)
431
     * @param string $deferrable The deferrability (eg. NOT DEFERRABLE)
432
     * @param string $initially  The initially parameter for the FK (eg. INITIALLY IMMEDIATE)
433
     * @param string $name       [optional] The name to give the key, otherwise default name is assigned
434
     *
435
     * @return int 0 if operation was successful
436
     *
437
     * @internal param \PHPPgAdmin\Database\The $target table that contains the target columns
438
     * @internal param \PHPPgAdmin\Database\The $intially initial deferrability (eg. INITIALLY IMMEDIATE)
439
     */
440
    public function addForeignKey(
441
        $table,
442
        $targschema,
443
        $targtable,
444
        $sfields,
445
        $tfields,
446
        $upd_action,
447
        $del_action,
448
        $match,
449
        $deferrable,
450
        $initially,
451
        $name = ''
452
    ) {
453
        if (!is_array($sfields) || sizeof($sfields) == 0 ||
1 ignored issue
show
introduced by
The condition is_array($sfields) is always true.
Loading history...
454
            !is_array($tfields) || sizeof($tfields) == 0) {
455
            return -1;
456
        }
457
458
        $f_schema = $this->_schema;
459
        $this->fieldClean($f_schema);
460
        $this->fieldClean($table);
461
        $this->fieldClean($targschema);
462
        $this->fieldClean($targtable);
463
        $this->fieldArrayClean($sfields);
464
        $this->fieldArrayClean($tfields);
465
        $this->fieldClean($name);
466
467
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
468
        if ($name != '') {
469
            $sql .= "CONSTRAINT \"{$name}\" ";
470
        }
471
472
        $sql .= 'FOREIGN KEY ("' . join('","', $sfields) . '") ';
473
        // Target table needs to be fully qualified
474
        $sql .= "REFERENCES \"{$targschema}\".\"{$targtable}\"(\"" . join('","', $tfields) . '") ';
475
        if ($match != $this->fkmatches[0]) {
476
            $sql .= " {$match}";
477
        }
478
479
        if ($upd_action != $this->fkactions[0]) {
480
            $sql .= " ON UPDATE {$upd_action}";
481
        }
482
483
        if ($del_action != $this->fkactions[0]) {
484
            $sql .= " ON DELETE {$del_action}";
485
        }
486
487
        if ($deferrable != $this->fkdeferrable[0]) {
488
            $sql .= " {$deferrable}";
489
        }
490
491
        if ($initially != $this->fkinitial[0]) {
492
            $sql .= " {$initially}";
493
        }
494
495
        return $this->execute($sql);
496
    }
497
498
    /**
499
     * Removes a constraint from a relation.
500
     *
501
     * @param string $constraint The constraint to drop
502
     * @param string $relation   The relation from which to drop
503
     * @param string $type       The type of constraint (c, f, u or p)
504
     * @param bool   $cascade    True to cascade drop, false to restrict
505
     *
506
     * @return int 0 if operation was successful
507
     */
508
    public function dropConstraint($constraint, $relation, $type, $cascade)
1 ignored issue
show
Unused Code introduced by
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

508
    public function dropConstraint($constraint, $relation, /** @scrutinizer ignore-unused */ $type, $cascade)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
509
    {
510
        $f_schema = $this->_schema;
511
        $this->fieldClean($f_schema);
512
        $this->fieldClean($constraint);
513
        $this->fieldClean($relation);
514
515
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$relation}\" DROP CONSTRAINT \"{$constraint}\"";
516
        if ($cascade) {
517
            $sql .= ' CASCADE';
518
        }
519
520
        return $this->execute($sql);
521
    }
522
523
    /**
524
     * A function for getting all columns linked by foreign keys given a group of tables.
525
     *
526
     * @param array $tables multi dimensional assoc array that holds schema and table name
527
     *
528
     * @return int|\PHPPgAdmin\ADORecordSet recordset of linked tables and columns or -1 if $tables isn't an array
529
     */
530
    public function getLinkingKeys($tables)
531
    {
532
        if (!is_array($tables)) {
1 ignored issue
show
introduced by
The condition is_array($tables) is always true.
Loading history...
533
            return -1;
534
        }
535
536
        $this->clean($tables[0]['tablename']);
537
        $this->clean($tables[0]['schemaname']);
538
        $tables_list        = "'{$tables[0]['tablename']}'";
539
        $schema_list        = "'{$tables[0]['schemaname']}'";
540
        $schema_tables_list = "'{$tables[0]['schemaname']}.{$tables[0]['tablename']}'";
541
542
        for ($i = 1; $i < sizeof($tables); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
543
            $this->clean($tables[$i]['tablename']);
544
            $this->clean($tables[$i]['schemaname']);
545
            $tables_list .= ", '{$tables[$i]['tablename']}'";
546
            $schema_list .= ", '{$tables[$i]['schemaname']}'";
547
            $schema_tables_list .= ", '{$tables[$i]['schemaname']}.{$tables[$i]['tablename']}'";
548
        }
549
550
        $maxDimension = 1;
551
552
        $sql = "
553
			SELECT DISTINCT
554
				array_dims(pc.conkey) AS arr_dim,
555
				pgc1.relname AS p_table
556
			FROM
557
				pg_catalog.pg_constraint AS pc,
558
				pg_catalog.pg_class AS pgc1
559
			WHERE
560
				pc.contype = 'f'
561
				AND (pc.conrelid = pgc1.relfilenode OR pc.confrelid = pgc1.relfilenode)
562
				AND pgc1.relname IN (${tables_list})
563
			";
564
565
        //parse our output to find the highest dimension of foreign keys since pc.conkey is stored in an array
566
        $rs = $this->selectSet($sql);
567
        while (!$rs->EOF) {
568
            $arrData      = explode(':', $rs->fields['arr_dim']);
569
            $tmpDimension = (int) (substr($arrData[1], 0, strlen($arrData[1] - 1)));
570
            $maxDimension = $tmpDimension > $maxDimension ? $tmpDimension : $maxDimension;
571
            $rs->MoveNext();
572
        }
573
574
        //we know the highest index for foreign keys that conkey goes up to, expand for us in an IN query
575
        $cons_str = '( (pfield.attnum = conkey[1] AND cfield.attnum = confkey[1]) ';
576
        for ($i = 2; $i <= $maxDimension; ++$i) {
577
            $cons_str .= "OR (pfield.attnum = conkey[{$i}] AND cfield.attnum = confkey[{$i}]) ";
578
        }
579
        $cons_str .= ') ';
580
581
        $sql = "
582
			SELECT
583
				pgc1.relname AS p_table,
584
				pgc2.relname AS f_table,
585
				pfield.attname AS p_field,
586
				cfield.attname AS f_field,
587
				pgns1.nspname AS p_schema,
588
				pgns2.nspname AS f_schema
589
			FROM
590
				pg_catalog.pg_constraint AS pc,
591
				pg_catalog.pg_class AS pgc1,
592
				pg_catalog.pg_class AS pgc2,
593
				pg_catalog.pg_attribute AS pfield,
594
				pg_catalog.pg_attribute AS cfield,
595
				(SELECT oid AS ns_id, nspname FROM pg_catalog.pg_namespace WHERE nspname IN (${schema_list}) ) AS pgns1,
596
 				(SELECT oid AS ns_id, nspname FROM pg_catalog.pg_namespace WHERE nspname IN (${schema_list}) ) AS pgns2
597
			WHERE
598
				pc.contype = 'f'
599
				AND pgc1.relnamespace = pgns1.ns_id
600
 				AND pgc2.relnamespace = pgns2.ns_id
601
				AND pc.conrelid = pgc1.relfilenode
602
				AND pc.confrelid = pgc2.relfilenode
603
				AND pfield.attrelid = pc.conrelid
604
				AND cfield.attrelid = pc.confrelid
605
				AND ${cons_str}
606
				AND pgns1.nspname || '.' || pgc1.relname IN (${schema_tables_list})
607
				AND pgns2.nspname || '.' || pgc2.relname IN (${schema_tables_list})
608
		";
609
610
        return $this->selectSet($sql);
611
    }
612
613
    /**
614
     * Finds the foreign keys that refer to the specified table.
615
     *
616
     * @param string $table The table to find referrers for
617
     *
618
     * @return int|\PHPPgAdmin\ADORecordSet A recordset or -1 in case of error
619
     */
620
    public function getReferrers($table)
621
    {
622
        $this->clean($table);
623
624
        $status = $this->beginTransaction();
625
        if ($status != 0) {
626
            return -1;
627
        }
628
629
        $c_schema = $this->_schema;
630
        $this->clean($c_schema);
631
632
        $sql = "
633
			SELECT
634
				pn.nspname,
635
				pl.relname,
636
				pc.conname,
637
				pg_catalog.pg_get_constraintdef(pc.oid) AS consrc
638
			FROM
639
				pg_catalog.pg_constraint pc,
640
				pg_catalog.pg_namespace pn,
641
				pg_catalog.pg_class pl
642
			WHERE
643
				pc.connamespace = pn.oid
644
				AND pc.conrelid = pl.oid
645
				AND pc.contype = 'f'
646
				AND confrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='{$table}'
647
					AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
648
					WHERE nspname='{$c_schema}'))
649
			ORDER BY 1,2,3
650
		";
651
652
        return $this->selectSet($sql);
653
    }
654
655
    abstract public function fieldClean(&$str);
656
657
    abstract public function beginTransaction();
658
659
    abstract public function rollbackTransaction();
660
661
    abstract public function endTransaction();
662
663
    abstract public function execute($sql);
664
665
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
666
667
    abstract public function selectSet($sql);
668
669
    abstract public function clean(&$str);
670
671
    abstract public function hasTablespaces();
672
673
    abstract public function arrayClean($flags);
674
675
    abstract public function fieldArrayClean(&$arr);
676
}
677