| Total Complexity | 50 |
| Total Lines | 671 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like Postgres74 often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Postgres74, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 17 | class Postgres74 extends Postgres80 |
||
| 18 | { |
||
| 19 | public $major_version = 7.4; |
||
| 20 | // List of all legal privileges that can be applied to different types |
||
| 21 | // of objects. |
||
| 22 | public $privlist = [ |
||
| 23 | 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'], |
||
| 24 | 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'], |
||
| 25 | 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'], |
||
| 26 | 'database' => ['CREATE', 'TEMPORARY', 'ALL PRIVILEGES'], |
||
| 27 | 'function' => ['EXECUTE', 'ALL PRIVILEGES'], |
||
| 28 | 'language' => ['USAGE', 'ALL PRIVILEGES'], |
||
| 29 | 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'], |
||
| 30 | ]; |
||
| 31 | |||
| 32 | // Database functions |
||
| 33 | |||
| 34 | /** |
||
| 35 | * Alters a database |
||
| 36 | * the multiple return vals are for postgres 8+ which support more functionality in alter database. |
||
| 37 | * |
||
| 38 | * @param string $dbName The name of the database |
||
| 39 | * @param string $newName new name for the database |
||
| 40 | * @param string $newOwner The new owner for the database |
||
| 41 | * @param string $comment |
||
| 42 | * |
||
| 43 | * @return bool|int 0 success |
||
| 44 | */ |
||
| 45 | public function alterDatabase($dbName, $newName, $newOwner = '', $comment = '') |
||
| 58 | } |
||
| 59 | |||
| 60 | /** |
||
| 61 | * Return all database available on the server. |
||
| 62 | * |
||
| 63 | * @param null|string $currentdatabase |
||
| 64 | * |
||
| 65 | * @return \ADORecordSet A list of databases, sorted alphabetically |
||
| 66 | */ |
||
| 67 | public function getDatabases($currentdatabase = null) |
||
| 68 | { |
||
| 69 | $conf = $this->conf; |
||
| 70 | $server_info = $this->server_info; |
||
|
|
|||
| 71 | |||
| 72 | if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) { |
||
| 73 | $username = $server_info['username']; |
||
| 74 | $this->clean($username); |
||
| 75 | $clause = " AND pu.usename='{$username}'"; |
||
| 76 | } else { |
||
| 77 | $clause = ''; |
||
| 78 | } |
||
| 79 | |||
| 80 | if ($currentdatabase != null) { |
||
| 81 | $this->clean($currentdatabase); |
||
| 82 | $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname"; |
||
| 83 | } else { |
||
| 84 | $orderby = 'ORDER BY pdb.datname'; |
||
| 85 | } |
||
| 86 | |||
| 87 | if (!$conf['show_system']) { |
||
| 88 | $where = ' AND NOT pdb.datistemplate'; |
||
| 89 | } else { |
||
| 90 | $where = ' AND pdb.datallowconn'; |
||
| 91 | } |
||
| 92 | |||
| 93 | $sql = "SELECT pdb.datname AS datname, |
||
| 94 | pu.usename AS datowner, |
||
| 95 | pg_encoding_to_char(encoding) AS datencoding, |
||
| 96 | (SELECT description FROM pg_description pd WHERE pdb.oid=pd.objoid) AS datcomment |
||
| 97 | FROM pg_database pdb, pg_user pu |
||
| 98 | WHERE pdb.datdba = pu.usesysid |
||
| 99 | {$where} |
||
| 100 | {$clause} |
||
| 101 | {$orderby}"; |
||
| 102 | |||
| 103 | return $this->selectSet($sql); |
||
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Searches all system catalogs to find objects that match a certain name. |
||
| 108 | * |
||
| 109 | * @param $term The search term |
||
| 110 | * @param $filter The object type to restrict to ('' means no restriction) |
||
| 111 | * |
||
| 112 | * @return \ADORecordSet A recordset |
||
| 113 | */ |
||
| 114 | public function findObject($term, $filter) |
||
| 115 | { |
||
| 116 | $conf = $this->conf; |
||
| 117 | |||
| 118 | /*about escaping: |
||
| 119 | * SET standard_conforming_string is not available before 8.2 |
||
| 120 | * So we must use PostgreSQL specific notation :/ |
||
| 121 | * E'' notation is not available before 8.1 |
||
| 122 | * $$ is available since 8.0 |
||
| 123 | * Nothing specific from 7.4 |
||
| 124 | */ |
||
| 125 | |||
| 126 | // Escape search term for ILIKE match |
||
| 127 | $term = str_replace('_', '\\_', $term); |
||
| 128 | $term = str_replace('%', '\\%', $term); |
||
| 129 | $this->clean($term); |
||
| 130 | $this->clean($filter); |
||
| 131 | |||
| 132 | // Exclude system relations if necessary |
||
| 133 | if (!$conf['show_system']) { |
||
| 134 | // XXX: The mention of information_schema here is in the wrong place, but |
||
| 135 | // it's the quickest fix to exclude the info schema from 7.4 |
||
| 136 | $where = " AND pn.nspname NOT LIKE 'pg\\\\_%' AND pn.nspname != 'information_schema'"; |
||
| 137 | $lan_where = 'AND pl.lanispl'; |
||
| 138 | } else { |
||
| 139 | $where = ''; |
||
| 140 | $lan_where = ''; |
||
| 141 | } |
||
| 142 | |||
| 143 | // Apply outer filter |
||
| 144 | $sql = ''; |
||
| 145 | if ($filter != '') { |
||
| 146 | $sql = 'SELECT * FROM ('; |
||
| 147 | } |
||
| 148 | |||
| 149 | $sql .= " |
||
| 150 | SELECT 'SCHEMA' AS type, oid, NULL AS schemaname, NULL AS relname, nspname AS name |
||
| 151 | FROM pg_catalog.pg_namespace pn WHERE nspname ILIKE '%{$term}%' {$where} |
||
| 152 | UNION ALL |
||
| 153 | SELECT CASE WHEN relkind='r' THEN 'TABLE' WHEN relkind='v' THEN 'VIEW' WHEN relkind='S' THEN 'SEQUENCE' END, pc.oid, |
||
| 154 | pn.nspname, NULL, pc.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn |
||
| 155 | WHERE pc.relnamespace=pn.oid AND relkind IN ('r', 'v', 'S') AND relname ILIKE '%{$term}%' {$where} |
||
| 156 | UNION ALL |
||
| 157 | SELECT CASE WHEN pc.relkind='r' THEN 'COLUMNTABLE' ELSE 'COLUMNVIEW' END, NULL, pn.nspname, pc.relname, pa.attname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn, |
||
| 158 | pg_catalog.pg_attribute pa WHERE pc.relnamespace=pn.oid AND pc.oid=pa.attrelid |
||
| 159 | AND pa.attname ILIKE '%{$term}%' AND pa.attnum > 0 AND NOT pa.attisdropped AND pc.relkind IN ('r', 'v') {$where} |
||
| 160 | UNION ALL |
||
| 161 | SELECT 'FUNCTION', pp.oid, pn.nspname, NULL, pp.proname || '(' || pg_catalog.oidvectortypes(pp.proargtypes) || ')' FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pn |
||
| 162 | WHERE pp.pronamespace=pn.oid AND NOT pp.proisagg AND pp.proname ILIKE '%{$term}%' {$where} |
||
| 163 | UNION ALL |
||
| 164 | SELECT 'INDEX', NULL, pn.nspname, pc.relname, pc2.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn, |
||
| 165 | pg_catalog.pg_index pi, pg_catalog.pg_class pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pi.indrelid |
||
| 166 | AND pi.indexrelid=pc2.oid |
||
| 167 | AND NOT EXISTS ( |
||
| 168 | SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c |
||
| 169 | ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) |
||
| 170 | WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p') |
||
| 171 | ) |
||
| 172 | AND pc2.relname ILIKE '%{$term}%' {$where} |
||
| 173 | UNION ALL |
||
| 174 | SELECT 'CONSTRAINTTABLE', NULL, pn.nspname, pc.relname, pc2.conname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn, |
||
| 175 | pg_catalog.pg_constraint pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pc2.conrelid AND pc2.conrelid != 0 |
||
| 176 | AND CASE WHEN pc2.contype IN ('f', 'c') THEN TRUE ELSE NOT EXISTS ( |
||
| 177 | SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c |
||
| 178 | ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) |
||
| 179 | WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p') |
||
| 180 | ) END |
||
| 181 | AND pc2.conname ILIKE '%{$term}%' {$where} |
||
| 182 | UNION ALL |
||
| 183 | SELECT 'CONSTRAINTDOMAIN', pt.oid, pn.nspname, pt.typname, pc.conname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn, |
||
| 184 | pg_catalog.pg_constraint pc WHERE pt.typnamespace=pn.oid AND pt.oid=pc.contypid AND pc.contypid != 0 |
||
| 185 | AND pc.conname ILIKE '%{$term}%' {$where} |
||
| 186 | UNION ALL |
||
| 187 | SELECT 'TRIGGER', NULL, pn.nspname, pc.relname, pt.tgname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn, |
||
| 188 | pg_catalog.pg_trigger pt WHERE pc.relnamespace=pn.oid AND pc.oid=pt.tgrelid |
||
| 189 | AND ( pt.tgisconstraint = 'f' OR NOT EXISTS |
||
| 190 | (SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c |
||
| 191 | ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) |
||
| 192 | WHERE d.classid = pt.tableoid AND d.objid = pt.oid AND d.deptype = 'i' AND c.contype = 'f')) |
||
| 193 | AND pt.tgname ILIKE '%{$term}%' {$where} |
||
| 194 | UNION ALL |
||
| 195 | SELECT 'RULETABLE', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r |
||
| 196 | JOIN pg_catalog.pg_class c ON c.oid = r.ev_class |
||
| 197 | LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace |
||
| 198 | WHERE c.relkind='r' AND r.rulename != '_RETURN' AND r.rulename ILIKE '%{$term}%' {$where} |
||
| 199 | UNION ALL |
||
| 200 | SELECT 'RULEVIEW', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r |
||
| 201 | JOIN pg_catalog.pg_class c ON c.oid = r.ev_class |
||
| 202 | LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace |
||
| 203 | WHERE c.relkind='v' AND r.rulename != '_RETURN' AND r.rulename ILIKE '%{$term}%' {$where} |
||
| 204 | "; |
||
| 205 | |||
| 206 | // Add advanced objects if show_advanced is set |
||
| 207 | if ($conf['show_advanced']) { |
||
| 208 | $sql .= " |
||
| 209 | UNION ALL |
||
| 210 | SELECT CASE WHEN pt.typtype='d' THEN 'DOMAIN' ELSE 'TYPE' END, pt.oid, pn.nspname, NULL, |
||
| 211 | pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn |
||
| 212 | WHERE pt.typnamespace=pn.oid AND typname ILIKE '%{$term}%' |
||
| 213 | AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid)) |
||
| 214 | {$where} |
||
| 215 | UNION ALL |
||
| 216 | SELECT 'OPERATOR', po.oid, pn.nspname, NULL, po.oprname FROM pg_catalog.pg_operator po, pg_catalog.pg_namespace pn |
||
| 217 | WHERE po.oprnamespace=pn.oid AND oprname ILIKE '%{$term}%' {$where} |
||
| 218 | UNION ALL |
||
| 219 | SELECT 'CONVERSION', pc.oid, pn.nspname, NULL, pc.conname FROM pg_catalog.pg_conversion pc, |
||
| 220 | pg_catalog.pg_namespace pn WHERE pc.connamespace=pn.oid AND conname ILIKE '%{$term}%' {$where} |
||
| 221 | UNION ALL |
||
| 222 | SELECT 'LANGUAGE', pl.oid, NULL, NULL, pl.lanname FROM pg_catalog.pg_language pl |
||
| 223 | WHERE lanname ILIKE '%{$term}%' {$lan_where} |
||
| 224 | UNION ALL |
||
| 225 | SELECT DISTINCT ON (p.proname) 'AGGREGATE', p.oid, pn.nspname, NULL, p.proname FROM pg_catalog.pg_proc p |
||
| 226 | LEFT JOIN pg_catalog.pg_namespace pn ON p.pronamespace=pn.oid |
||
| 227 | WHERE p.proisagg AND p.proname ILIKE '%{$term}%' {$where} |
||
| 228 | UNION ALL |
||
| 229 | SELECT DISTINCT ON (po.opcname) 'OPCLASS', po.oid, pn.nspname, NULL, po.opcname FROM pg_catalog.pg_opclass po, |
||
| 230 | pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid |
||
| 231 | AND po.opcname ILIKE '%{$term}%' {$where} |
||
| 232 | "; |
||
| 233 | } // Otherwise just add domains |
||
| 234 | else { |
||
| 235 | $sql .= " |
||
| 236 | UNION ALL |
||
| 237 | SELECT 'DOMAIN', pt.oid, pn.nspname, NULL, |
||
| 238 | pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn |
||
| 239 | WHERE pt.typnamespace=pn.oid AND pt.typtype='d' AND typname ILIKE '%{$term}%' |
||
| 240 | AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid)) |
||
| 241 | {$where} |
||
| 242 | "; |
||
| 243 | } |
||
| 244 | |||
| 245 | if ($filter != '') { |
||
| 246 | // We use like to make RULE, CONSTRAINT and COLUMN searches work |
||
| 247 | $sql .= ") AS sub WHERE type LIKE '{$filter}%' "; |
||
| 248 | } |
||
| 249 | |||
| 250 | $sql .= 'ORDER BY type, schemaname, relname, name'; |
||
| 251 | |||
| 252 | return $this->selectSet($sql); |
||
| 253 | } |
||
| 254 | |||
| 255 | /** |
||
| 256 | * Returns table locks information in the current database. |
||
| 257 | * |
||
| 258 | * @return \ADORecordSet A recordset |
||
| 259 | */ |
||
| 260 | public function getLocks() |
||
| 261 | { |
||
| 262 | $conf = $this->conf; |
||
| 263 | |||
| 264 | if (!$conf['show_system']) { |
||
| 265 | $where = "AND pn.nspname NOT LIKE 'pg\\\\_%'"; |
||
| 266 | } else { |
||
| 267 | $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'"; |
||
| 268 | } |
||
| 269 | |||
| 270 | $sql = "SELECT pn.nspname, pc.relname AS tablename, pl.transaction, pl.pid, pl.mode, pl.granted |
||
| 271 | FROM pg_catalog.pg_locks pl, pg_catalog.pg_class pc, pg_catalog.pg_namespace pn |
||
| 272 | WHERE pl.relation = pc.oid AND pc.relnamespace=pn.oid {$where} |
||
| 273 | ORDER BY nspname,tablename"; |
||
| 274 | |||
| 275 | return $this->selectSet($sql); |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * Returns the current database encoding. |
||
| 280 | * |
||
| 281 | * @return The encoding. eg. SQL_ASCII, UTF-8, etc. |
||
| 282 | */ |
||
| 283 | public function getDatabaseEncoding() |
||
| 284 | { |
||
| 285 | $sql = 'SELECT getdatabaseencoding() AS encoding'; |
||
| 286 | |||
| 287 | return $this->selectField($sql, 'encoding'); |
||
| 288 | } |
||
| 289 | |||
| 290 | // Table functions |
||
| 291 | |||
| 292 | /** |
||
| 293 | * Alters a column in a table OR view. |
||
| 294 | * |
||
| 295 | * @param $table The table in which the column resides |
||
| 296 | * @param $column The column to alter |
||
| 297 | * @param $name The new name for the column |
||
| 298 | * @param $notnull (boolean) True if not null, false otherwise |
||
| 299 | * @param $oldnotnull (boolean) True if column is already not null, false otherwise |
||
| 300 | * @param $default The new default for the column |
||
| 301 | * @param $olddefault The old default for the column |
||
| 302 | * @param $type The new type for the column |
||
| 303 | * @param $length The optional size of the column (ie. 30 for varchar(30)) |
||
| 304 | * @param $array True if array type, false otherwise |
||
| 305 | * @param $oldtype The old type for the column |
||
| 306 | * @param $comment Comment for the column |
||
| 307 | * |
||
| 308 | * @return array|bool|int 0 success |
||
| 309 | */ |
||
| 310 | public function alterColumn( |
||
| 311 | $table, |
||
| 312 | $column, |
||
| 313 | $name, |
||
| 314 | $notnull, |
||
| 315 | $oldnotnull, |
||
| 316 | $default, |
||
| 317 | $olddefault, |
||
| 318 | $type, |
||
| 319 | $length, |
||
| 320 | $array, |
||
| 321 | $oldtype, |
||
| 322 | $comment |
||
| 323 | ) { |
||
| 324 | $status = $this->beginTransaction(); |
||
| 325 | if ($status != 0) { |
||
| 326 | return -1; |
||
| 327 | } |
||
| 328 | |||
| 329 | // @@ NEED TO HANDLE "NESTED" TRANSACTION HERE |
||
| 330 | if ($notnull != $oldnotnull) { |
||
| 331 | $status = $this->setColumnNull($table, $column, !$notnull); |
||
| 332 | if ($status != 0) { |
||
| 333 | $this->rollbackTransaction(); |
||
| 334 | |||
| 335 | return -2; |
||
| 336 | } |
||
| 337 | } |
||
| 338 | |||
| 339 | // Set default, if it has changed |
||
| 340 | if ($default != $olddefault) { |
||
| 341 | if ($default == '') { |
||
| 342 | $status = $this->dropColumnDefault($table, $column); |
||
| 343 | } else { |
||
| 344 | $status = $this->setColumnDefault($table, $column, $default); |
||
| 345 | } |
||
| 346 | |||
| 347 | if ($status != 0) { |
||
| 348 | $this->rollbackTransaction(); |
||
| 349 | |||
| 350 | return -3; |
||
| 351 | } |
||
| 352 | } |
||
| 353 | |||
| 354 | // Rename the column, if it has been changed |
||
| 355 | if ($column != $name) { |
||
| 356 | $status = $this->renameColumn($table, $column, $name); |
||
| 357 | if ($status != 0) { |
||
| 358 | $this->rollbackTransaction(); |
||
| 359 | |||
| 360 | return -4; |
||
| 361 | } |
||
| 362 | } |
||
| 363 | |||
| 364 | // The $name and $table parameters must be cleaned for the setComment function. |
||
| 365 | // It's ok to do that here since this is the last time these variables are used. |
||
| 366 | $this->fieldClean($name); |
||
| 367 | $this->fieldClean($table); |
||
| 368 | $status = $this->setComment('COLUMN', $name, $table, $comment); |
||
| 369 | if ($status != 0) { |
||
| 370 | $this->rollbackTransaction(); |
||
| 371 | |||
| 372 | return -5; |
||
| 373 | } |
||
| 374 | |||
| 375 | return $this->endTransaction(); |
||
| 376 | } |
||
| 377 | |||
| 378 | /** |
||
| 379 | * Returns table information. |
||
| 380 | * |
||
| 381 | * @param $table The name of the table |
||
| 382 | * |
||
| 383 | * @return \ADORecordSet A recordset |
||
| 384 | */ |
||
| 385 | public function getTable($table) |
||
| 386 | { |
||
| 387 | $c_schema = $this->_schema; |
||
| 388 | $this->clean($c_schema); |
||
| 389 | $this->clean($table); |
||
| 390 | |||
| 391 | $sql = " |
||
| 392 | SELECT |
||
| 393 | c.relname, n.nspname, u.usename AS relowner, |
||
| 394 | pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment |
||
| 395 | FROM pg_catalog.pg_class c |
||
| 396 | LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner |
||
| 397 | LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace |
||
| 398 | WHERE c.relkind = 'r' |
||
| 399 | AND n.nspname = '{$c_schema}' |
||
| 400 | AND c.relname = '{$table}'"; |
||
| 401 | |||
| 402 | return $this->selectSet($sql); |
||
| 403 | } |
||
| 404 | |||
| 405 | /** |
||
| 406 | * Returns the current default_with_oids setting. |
||
| 407 | * |
||
| 408 | * @return default_with_oids setting |
||
| 409 | */ |
||
| 410 | public function getDefaultWithOid() |
||
| 411 | { |
||
| 412 | // 8.0 is the first release to have this setting |
||
| 413 | // Prior releases don't have this setting... oids always activated |
||
| 414 | return 'on'; |
||
| 415 | } |
||
| 416 | |||
| 417 | /** |
||
| 418 | * Returns a list of all constraints on a table, |
||
| 419 | * including constraint name, definition, related col and referenced namespace, |
||
| 420 | * table and col if needed. |
||
| 421 | * |
||
| 422 | * @param $table the table where we are looking for fk |
||
| 423 | * |
||
| 424 | * @return \ADORecordSet A recordset |
||
| 425 | */ |
||
| 426 | public function getConstraintsWithFields($table) |
||
| 427 | { |
||
| 428 | $c_schema = $this->_schema; |
||
| 429 | $this->clean($c_schema); |
||
| 430 | $this->clean($table); |
||
| 431 | |||
| 432 | // get the max number of col used in a constraint for the table |
||
| 433 | $sql = "SELECT DISTINCT |
||
| 434 | max(SUBSTRING(array_dims(c.conkey) FROM '^\\\\[.*:(.*)\\\\]$')) as nb |
||
| 435 | FROM pg_catalog.pg_constraint AS c |
||
| 436 | JOIN pg_catalog.pg_class AS r ON (c.conrelid=r.oid) |
||
| 437 | JOIN pg_catalog.pg_namespace AS ns ON (r.relnamespace=ns.oid) |
||
| 438 | WHERE |
||
| 439 | r.relname = '{$table}' AND ns.nspname='{$c_schema}'"; |
||
| 440 | |||
| 441 | $rs = $this->selectSet($sql); |
||
| 442 | |||
| 443 | if ($rs->EOF) { |
||
| 444 | $max_col = 0; |
||
|
1 ignored issue
–
show
|
|||
| 445 | } else { |
||
| 446 | $max_col = $rs->fields['nb']; |
||
| 447 | } |
||
| 448 | |||
| 449 | $sql = ' |
||
| 450 | SELECT |
||
| 451 | c.oid AS conid, c.contype, c.conname, pg_catalog.pg_get_constraintdef(c.oid, true) AS consrc, |
||
| 452 | ns1.nspname as p_schema, r1.relname as p_table, ns2.nspname as f_schema, |
||
| 453 | r2.relname as f_table, f1.attname as p_field, f1.attnum AS p_attnum, f2.attname as f_field, |
||
| 454 | f2.attnum AS f_attnum, pg_catalog.obj_description(c.oid, \'pg_constraint\') AS constcomment, |
||
| 455 | c.conrelid, c.confrelid |
||
| 456 | FROM |
||
| 457 | pg_catalog.pg_constraint AS c |
||
| 458 | JOIN pg_catalog.pg_class AS r1 ON (c.conrelid=r1.oid) |
||
| 459 | JOIN pg_catalog.pg_attribute AS f1 ON (f1.attrelid=r1.oid AND (f1.attnum=c.conkey[1]'; |
||
| 460 | for ($i = 2; $i <= $rs->fields['nb']; ++$i) { |
||
| 461 | $sql .= " OR f1.attnum=c.conkey[${i}]"; |
||
| 462 | } |
||
| 463 | $sql .= ')) |
||
| 464 | JOIN pg_catalog.pg_namespace AS ns1 ON r1.relnamespace=ns1.oid |
||
| 465 | LEFT JOIN ( |
||
| 466 | pg_catalog.pg_class AS r2 JOIN pg_catalog.pg_namespace AS ns2 ON (r2.relnamespace=ns2.oid) |
||
| 467 | ) ON (c.confrelid=r2.oid) |
||
| 468 | LEFT JOIN pg_catalog.pg_attribute AS f2 ON |
||
| 469 | (f2.attrelid=r2.oid AND ((c.confkey[1]=f2.attnum AND c.conkey[1]=f1.attnum)'; |
||
| 470 | for ($i = 2; $i <= $rs->fields['nb']; ++$i) { |
||
| 471 | $sql .= " OR (c.confkey[${i}]=f2.attnum AND c.conkey[${i}]=f1.attnum)"; |
||
| 472 | } |
||
| 473 | |||
| 474 | $sql .= sprintf(")) |
||
|
1 ignored issue
–
show
|
|||
| 475 | WHERE |
||
| 476 | r1.relname = '%s' AND ns1.nspname='%s' |
||
| 477 | ORDER BY 1", $table, $c_schema); |
||
|
1 ignored issue
–
show
|
|||
| 478 | |||
| 479 | return $this->selectSet($sql); |
||
| 480 | } |
||
| 481 | |||
| 482 | // Constraint functions |
||
| 483 | |||
| 484 | /** |
||
| 485 | * Returns all sequences in the current database. |
||
| 486 | * |
||
| 487 | * @param bool $all |
||
| 488 | * |
||
| 489 | * @return \ADORecordSet A recordset |
||
| 490 | */ |
||
| 491 | public function getSequences($all = false) |
||
| 492 | { |
||
| 493 | $c_schema = $this->_schema; |
||
| 494 | $this->clean($c_schema); |
||
| 495 | if ($all) { |
||
| 496 | // Exclude pg_catalog and information_schema tables |
||
| 497 | $sql = "SELECT n.nspname, c.relname AS seqname, u.usename AS seqowner |
||
| 498 | FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n |
||
| 499 | WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid |
||
| 500 | AND c.relkind = 'S' |
||
| 501 | AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') |
||
| 502 | ORDER BY nspname, seqname"; |
||
| 503 | } else { |
||
| 504 | $sql = "SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment |
||
| 505 | FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n |
||
| 506 | WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid |
||
| 507 | AND c.relkind = 'S' AND n.nspname='{$c_schema}' ORDER BY seqname"; |
||
| 508 | } |
||
| 509 | |||
| 510 | return $this->selectSet($sql); |
||
| 511 | } |
||
| 512 | |||
| 513 | // Sequence functions |
||
| 514 | |||
| 515 | /** |
||
| 516 | * Returns all details for a particular function. |
||
| 517 | * |
||
| 518 | * @param $function_oid |
||
| 519 | * |
||
| 520 | * @return \ADORecordSet Function info |
||
| 521 | * |
||
| 522 | * @internal param string The $func name of the function to retrieve |
||
| 523 | */ |
||
| 524 | public function getFunction($function_oid) |
||
| 525 | { |
||
| 526 | $this->clean($function_oid); |
||
| 527 | |||
| 528 | $sql = " |
||
| 529 | SELECT |
||
| 530 | pc.oid AS prooid, |
||
| 531 | proname, |
||
| 532 | pg_catalog.pg_get_userbyid(proowner) AS proowner, |
||
| 533 | nspname as proschema, |
||
| 534 | lanname as prolanguage, |
||
| 535 | pg_catalog.format_type(prorettype, NULL) as proresult, |
||
| 536 | prosrc, |
||
| 537 | probin, |
||
| 538 | proretset, |
||
| 539 | proisstrict, |
||
| 540 | provolatile, |
||
| 541 | prosecdef, |
||
| 542 | pg_catalog.oidvectortypes(pc.proargtypes) AS proarguments, |
||
| 543 | pg_catalog.obj_description(pc.oid, 'pg_proc') AS procomment |
||
| 544 | FROM |
||
| 545 | pg_catalog.pg_proc pc, pg_catalog.pg_language pl, pg_catalog.pg_namespace n |
||
| 546 | WHERE |
||
| 547 | pc.oid = '${function_oid}'::oid |
||
| 548 | AND pc.prolang = pl.oid |
||
| 549 | AND n.oid = pc.pronamespace |
||
| 550 | "; |
||
| 551 | |||
| 552 | return $this->selectSet($sql); |
||
| 553 | } |
||
| 554 | |||
| 555 | // Function functions |
||
| 556 | |||
| 557 | /** |
||
| 558 | * Returns a list of all casts in the database. |
||
| 559 | * |
||
| 560 | * @return All casts |
||
| 561 | */ |
||
| 562 | public function getCasts() |
||
| 563 | { |
||
| 564 | $conf = $this->conf; |
||
| 565 | |||
| 566 | if ($conf['show_system']) { |
||
| 567 | $where = ''; |
||
| 568 | } else { |
||
| 569 | $where = " |
||
| 570 | AND n1.nspname NOT LIKE 'pg\\\\_%' |
||
| 571 | AND n2.nspname NOT LIKE 'pg\\\\_%' |
||
| 572 | AND n3.nspname NOT LIKE 'pg\\\\_%' |
||
| 573 | "; |
||
| 574 | } |
||
| 575 | |||
| 576 | $sql = " |
||
| 577 | SELECT |
||
| 578 | c.castsource::pg_catalog.regtype AS castsource, |
||
| 579 | c.casttarget::pg_catalog.regtype AS casttarget, |
||
| 580 | CASE WHEN c.castfunc=0 THEN NULL |
||
| 581 | ELSE c.castfunc::pg_catalog.regprocedure END AS castfunc, |
||
| 582 | c.castcontext, |
||
| 583 | obj_description(c.oid, 'pg_cast') as castcomment |
||
| 584 | FROM |
||
| 585 | (pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p ON c.castfunc=p.oid JOIN pg_catalog.pg_namespace n3 ON p.pronamespace=n3.oid), |
||
| 586 | pg_catalog.pg_type t1, |
||
| 587 | pg_catalog.pg_type t2, |
||
| 588 | pg_catalog.pg_namespace n1, |
||
| 589 | pg_catalog.pg_namespace n2 |
||
| 590 | WHERE |
||
| 591 | c.castsource=t1.oid |
||
| 592 | AND c.casttarget=t2.oid |
||
| 593 | AND t1.typnamespace=n1.oid |
||
| 594 | AND t2.typnamespace=n2.oid |
||
| 595 | {$where} |
||
| 596 | ORDER BY 1, 2 |
||
| 597 | "; |
||
| 598 | |||
| 599 | return $this->selectSet($sql); |
||
| 600 | } |
||
| 601 | |||
| 602 | public function hasAlterColumnType() |
||
| 603 | { |
||
| 604 | return false; |
||
| 605 | } |
||
| 606 | |||
| 607 | // Capabilities |
||
| 608 | |||
| 609 | public function hasCreateFieldWithConstraints() |
||
|
1 ignored issue
–
show
|
|||
| 610 | { |
||
| 611 | return false; |
||
| 612 | } |
||
| 613 | |||
| 614 | public function hasAlterDatabaseOwner() |
||
| 615 | { |
||
| 616 | return false; |
||
| 617 | } |
||
| 618 | |||
| 619 | public function hasAlterSchemaOwner() |
||
| 620 | { |
||
| 621 | return false; |
||
| 622 | } |
||
| 623 | |||
| 624 | public function hasFunctionAlterOwner() |
||
| 625 | { |
||
| 626 | return false; |
||
| 627 | } |
||
| 628 | |||
| 629 | public function hasNamedParams() |
||
| 630 | { |
||
| 631 | return false; |
||
| 632 | } |
||
| 633 | |||
| 634 | public function hasQueryCancel() |
||
| 635 | { |
||
| 636 | return false; |
||
| 637 | } |
||
| 638 | |||
| 639 | public function hasTablespaces() |
||
| 640 | { |
||
| 641 | return false; |
||
| 642 | } |
||
| 643 | |||
| 644 | public function hasMagicTypes() |
||
| 645 | { |
||
| 646 | return false; |
||
| 647 | } |
||
| 648 | |||
| 649 | /** |
||
| 650 | * Protected method which alter a table |
||
| 651 | * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION. |
||
| 652 | * |
||
| 653 | * @param $tblrs The table recordSet returned by getTable() |
||
| 654 | * @param $name The new name for the table |
||
| 655 | * @param $owner The new owner for the table |
||
| 656 | * @param $schema The new schema for the table |
||
| 657 | * @param $comment The comment on the table |
||
| 658 | * @param $tablespace The new tablespace for the table ('' means leave as is) |
||
| 659 | * |
||
| 660 | * @return int 0 success |
||
| 661 | */ |
||
| 662 | protected function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace) |
||
| 688 | } |
||
| 689 | } |
||
| 690 |