ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilDBPdoManagerPostgres.php
Go to the documentation of this file.
1<?php
2
9{
10
14 public function getQueryUtils()
15 {
16 if (!$this->query_utils) {
17 $this->query_utils = new ilPostgresQueryUtils($this->db_instance);
18 }
19
20 return $this->query_utils;
21 }
22
23
31 public function getTableCreationQuery($name, $fields, $options = array())
32 {
33 return $this->getQueryUtils()->createTable($name, $fields, $options);
34 }
35
36
43 public function createTable($name, $fields, $options = array())
44 {
45 return $this->pdo->exec($this->getQueryUtils()->createTable($name, $fields, $options));
46 }
47
48
53 public function listTables($database = null)
54 {
56
57 // gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
58 $query = 'SELECT c.relname AS "Name"' . ' FROM pg_class c, pg_user u' . ' WHERE c.relowner = u.usesysid' . " AND c.relkind = 'r'"
59 . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views' . ' WHERE viewname = c.relname)' . " AND c.relname !~ '^(pg_|sql_)'" . ' UNION'
60 . ' SELECT c.relname AS "Name"' . ' FROM pg_class c' . " WHERE c.relkind = 'r'" . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views'
61 . ' WHERE viewname = c.relname)' . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_user' . ' WHERE usesysid = c.relowner)'
62 . " AND c.relname !~ '^pg_'";
64
65 if ($db->options['portability']) {
66 $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
67 }
68 sort($result); // FSX Patch
69 return $result;
70 }
71
72
77 public function createDatabase($name)
78 {
80 $name = $db->quoteIdentifier($name, true);
81
82 return $db->manipulate("CREATE DATABASE $name");
83 }
84
85
90 public function dropDatabase($name)
91 {
93
94 $name = $db->quoteIdentifier($name, true);
95
96 return $db->manipulate("DROP DATABASE $name");
97 }
98
99
106 public function alterTable($name, $changes, $check)
107 {
108 $db = $this->db_instance;
109 $reverse = $db->loadModule(ilDBConstants::MODULE_REVERSE);
114 foreach ($changes as $change_name => $change) {
115 switch ($change_name) {
116 case 'add':
117 case 'remove':
118 case 'change':
119 case 'name':
120 case 'rename':
121 break;
122 default:
123 throw new ilDatabaseException('change type "' . $change_name . '\" not yet supported');
124 }
125 }
126
127 if ($check) {
128 return true;
129 }
130
131 if (!empty($changes['add']) && is_array($changes['add'])) {
132 foreach ($changes['add'] as $field_name => $field) {
133 $query = 'ADD ' . $db->getFieldDefinition()->getDeclaration($field['type'], $field_name, $field);
134 $result = $db->manipulate("ALTER TABLE $name $query");
135 }
136 }
137
138 if (!empty($changes['remove']) && is_array($changes['remove'])) {
139 foreach ($changes['remove'] as $field_name => $field) {
140 $field_name = $db->quoteIdentifier($field_name, true);
141 $query = 'DROP ' . $field_name;
142 $result = $db->manipulate("ALTER TABLE $name $query");
143 }
144 }
145
146 if (!empty($changes['change']) && is_array($changes['change'])) {
147 foreach ($changes['change'] as $field_name => $field) {
148 $field_name = $db->quoteIdentifier($field_name, true);
149 if (!empty($field['type'])) {
150 $server_info = $db->getServerVersion();
151
152 if (is_array($server_info) && $server_info['major'] < 8) {
153 throw new ilDatabaseException('changing column type for "' . $change_name . '\" requires PostgreSQL 8.0 or above');
154 }
155
156 $query = "ALTER $field_name TYPE " . $db->getFieldDefinition()->getTypeDeclaration($field);
157 $result = $db->manipulate("ALTER TABLE $name $query");
158 }
159 if (array_key_exists('default', $field)) {
160 $query = "ALTER $field_name SET DEFAULT " . $db->quote($field['definition']['default'], $field['definition']['type']);
161 $result = $db->manipulate("ALTER TABLE $name $query");
162 }
163 if (!empty($field['notnull'])) {
164 $query = "ALTER $field_name " . ($field['definition']['notnull'] ? "SET" : "DROP") . ' NOT NULL';
165 $result = $db->manipulate("ALTER TABLE $name $query");
166 }
167 }
168 }
169
170 if (!empty($changes['rename']) && is_array($changes['rename'])) {
171 foreach ($changes['rename'] as $field_name => $field) {
172 $field_name = $db->quoteIdentifier($field_name, true);
173 $result = $db->manipulate("ALTER TABLE $name RENAME COLUMN $field_name TO " . $db->quoteIdentifier($field['name'], true));
174 }
175 }
176
177 if (!empty($changes['name'])) {
178 $result = $db->manipulate("ALTER TABLE " . $db->quoteIdentifier($name, true) . " RENAME TO " . $db->quoteIdentifier($changes['name']));
179
180 $idx = array_merge($this->listTableIndexes($changes['name']), $this->listTableConstraints($changes['name']));
181 foreach ($idx as $index_name) {
182 $index_newname = preg_replace("/^$name/", $changes['name'], $index_name);
183 $result = $db->manipulate("ALTER INDEX " . $this->getIndexName($index_name) . " RENAME TO " . $this->getIndexName($index_newname));
184 }
185 }
186
187 return true;
188 }
189
190
195 public function listTableFields($table)
196 {
197 $db = $this->db_instance;
198
199 $table = $db->quoteIdentifier($table, true);
200 $res = $this->pdo->query("select * from $table");
201 for ($i = 0; $i < $res->columnCount(); $i++) {
202 $data[] = $res->getColumnMeta($i)["name"];
203 }
204 return $data;
205 }
206
207
212 public function listTableIndexes($table)
213 {
214 $db = $this->db_instance;
215
216 $table = $db->quote($table, 'text');
217 $subquery = "SELECT indexrelid FROM pg_index, pg_class";
218 $subquery .= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'";
219 $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
220 $indexes = $db->queryCol($query, 'text');
221
222 $result = array();
223 foreach ($indexes as $index) {
224 $index = $this->fixIndexName($index);
225 if (!empty($index)) {
226 $result[$index] = true;
227 }
228 }
229
230 if ($db->options['portability']) {
231 $result = array_change_key_case($result, $db->options['field_case']);
232 }
233
234 return array_keys($result);
235 }
236
237
242 public function listTableConstraints($table)
243 {
244 $db = $this->db_instance;
245
246 $table = $db->quote($table, 'text');
247 $subquery = "SELECT indexrelid FROM pg_index, pg_class";
248 $subquery .= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
249 $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
250 $constraints = $db->queryCol($query);
251
252 $result = array();
253 foreach ($constraints as $constraint) {
254 $constraint = $this->fixIndexName($constraint);
255 if (!empty($constraint)) {
256 $result[$constraint] = true;
257 }
258 }
259
260 if ($db->options['portability']
261 && $db->options['field_case'] == CASE_LOWER
262 ) {
263 $result = array_change_key_case($result, $db->options['field_case']);
264 }
265
266 return array_keys($result);
267 }
268
269
276 public function createSequence($seq_name, $start = 1, $options = array())
277 {
278 $db = $this->db_instance;
279
280 $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
281
282 return $db->manipulate("CREATE SEQUENCE $sequence_name INCREMENT 1" . ($start < 1 ? " MINVALUE $start" : '') . " START $start");
283 }
284
285
290 public function dropSequence($seq_name)
291 {
292 $db = $this->db_instance;
293
294 $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
295
296 return $db->manipulate("DROP SEQUENCE $sequence_name");
297 }
298
299
305 public function dropIndex($table, $name)
306 {
307 $db = $this->db_instance;
308
309 $name = $this->getIndexName($name);
310 $name = $db->quoteIdentifier($this->getDBInstance()->constraintName($table, $name), true);
311
312 return $db->manipulate("DROP INDEX $name");
313 }
314
315
320 protected function fixIndexName($idx)
321 {
322 $idx_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBPdoFieldDefinition::INDEX_FORMAT) . '$/i';
323 $idx_name = preg_replace($idx_pattern, '\\1', $idx);
324 if ($idx_name && !strcasecmp($idx, $this->db_instance->getIndexName($idx_name))) {
325 return $idx_name;
326 }
327
328 return $idx;
329 }
330
331
336 public function listSequences($database = null)
337 {
338 $db = $this->db_instance;
339
340 $query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
341 $query .= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
342 $table_names = $db->queryCol($query);
343
344 $result = array();
345 foreach ($table_names as $table_name) {
346 $result[] = $this->fixSequenceName($table_name);
347 }
348 if ($db->options['portability']) {
349 $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
350 }
351 sort($result); // FSX patch
352
353 return $result;
354 }
355
356
363 public function dropConstraint($table, $name, $primary = false)
364 {
365 $table_quoted = $this->getDBInstance()->quoteIdentifier($table, true);
366 $name = $this->getDBInstance()->quoteIdentifier($table . '_' . $this->getDBInstance()->getIndexName($name), true);
367
368 return $this->pdo->exec("ALTER TABLE $table_quoted DROP CONSTRAINT $name");
369 }
370}
$result
An exception for terminatinating execution or to throw for unit testing.
getTableCreationQuery($name, $fields, $options=array())
dropConstraint($table, $name, $primary=false)
createTable($name, $fields, $options=array())
createSequence($seq_name, $start=1, $options=array())
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
fixSequenceName($sqn, $check=false)
alterTable($name, $changes, $check)
Class ilDatabaseException.
Class ilPostgresQueryUtils.
if($format !==null) $name
Definition: metadata.php:230
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
$query
foreach($_POST as $key=> $value) $res
$data
Definition: storeScorm.php:23