ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilDBPdoManagerPostgres.php
Go to the documentation of this file.
1 <?php
2 require_once('class.ilDBPdoManager.php');
3 require_once('./Services/Database/classes/QueryUtils/class.ilPostgresQueryUtils.php');
4 
11 
15  public function getQueryUtils() {
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  return $this->getQueryUtils()->createTable($name, $fields, $options);
33  }
34 
35 
42  public function createTable($name, $fields, $options = array()) {
43  return $this->pdo->exec($this->getQueryUtils()->createTable($name, $fields, $options));
44  }
45 
46 
51  public function listTables($database = null) {
52  $db = $this->db_instance;
53 
54  // gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
55  $query = 'SELECT c.relname AS "Name"' . ' FROM pg_class c, pg_user u' . ' WHERE c.relowner = u.usesysid' . " AND c.relkind = 'r'"
56  . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views' . ' WHERE viewname = c.relname)' . " AND c.relname !~ '^(pg_|sql_)'" . ' UNION'
57  . ' SELECT c.relname AS "Name"' . ' FROM pg_class c' . " WHERE c.relkind = 'r'" . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_views'
58  . ' WHERE viewname = c.relname)' . ' AND NOT EXISTS' . ' (SELECT 1 FROM pg_user' . ' WHERE usesysid = c.relowner)'
59  . " AND c.relname !~ '^pg_'";
61 
62  if ($db->options['portability']) {
63  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
64  }
65  sort($result); // FSX Patch
66  return $result;
67  }
68 
69 
74  public function createDatabase($name) {
75  $db = $this->db_instance;
76  $name = $db->quoteIdentifier($name, true);
77 
78  return $db->manipulate("CREATE DATABASE $name");
79  }
80 
81 
86  public function dropDatabase($name) {
87  $db = $this->db_instance;
88 
89  $name = $db->quoteIdentifier($name, true);
90 
91  return $db->manipulate("DROP DATABASE $name");
92  }
93 
94 
101  public function alterTable($name, $changes, $check) {
102  $db = $this->db_instance;
103  $reverse = $db->loadModule(ilDBConstants::MODULE_REVERSE);
108  foreach ($changes as $change_name => $change) {
109  switch ($change_name) {
110  case 'add':
111  case 'remove':
112  case 'change':
113  case 'name':
114  case 'rename':
115  break;
116  default:
117  throw new ilDatabaseException('change type "' . $change_name . '\" not yet supported');
118  }
119  }
120 
121  if ($check) {
122  return true;
123  }
124 
125  if (!empty($changes['add']) && is_array($changes['add'])) {
126  foreach ($changes['add'] as $field_name => $field) {
127 
128  $query = 'ADD ' . $db->getFieldDefinition()->getDeclaration($field['type'], $field_name, $field);
129  $result = $db->manipulate("ALTER TABLE $name $query");
130  }
131  }
132 
133  if (!empty($changes['remove']) && is_array($changes['remove'])) {
134  foreach ($changes['remove'] as $field_name => $field) {
135  $field_name = $db->quoteIdentifier($field_name, true);
136  $query = 'DROP ' . $field_name;
137  $result = $db->manipulate("ALTER TABLE $name $query");
138  }
139  }
140 
141  if (!empty($changes['change']) && is_array($changes['change'])) {
142  foreach ($changes['change'] as $field_name => $field) {
143  $field_name = $db->quoteIdentifier($field_name, true);
144  if (!empty($field['type'])) {
145  $server_info = $db->getServerVersion();
146 
147  if (is_array($server_info) && $server_info['major'] < 8) {
148  throw new ilDatabaseException('changing column type for "' . $change_name . '\" requires PostgreSQL 8.0 or above');
149  }
150 
151  $query = "ALTER $field_name TYPE " . $db->getFieldDefinition()->getTypeDeclaration($field);
152  $result = $db->manipulate("ALTER TABLE $name $query");
153  }
154  if (array_key_exists('default', $field)) {
155  $query = "ALTER $field_name SET DEFAULT " . $db->quote($field['definition']['default'], $field['definition']['type']);
156  $result = $db->manipulate("ALTER TABLE $name $query");
157  }
158  if (!empty($field['notnull'])) {
159  $query = "ALTER $field_name " . ($field['definition']['notnull'] ? "SET" : "DROP") . ' NOT NULL';
160  $result = $db->manipulate("ALTER TABLE $name $query");
161  }
162  }
163  }
164 
165  if (!empty($changes['rename']) && is_array($changes['rename'])) {
166  foreach ($changes['rename'] as $field_name => $field) {
167  $field_name = $db->quoteIdentifier($field_name, true);
168  $result = $db->manipulate("ALTER TABLE $name RENAME COLUMN $field_name TO " . $db->quoteIdentifier($field['name'], true));
169  }
170  }
171 
172  if (!empty($changes['name'])) {
173  $result = $db->manipulate("ALTER TABLE " . $db->quoteIdentifier($name, true) . " RENAME TO " . $db->quoteIdentifier($changes['name']));
174 
175  $idx = array_merge($this->listTableIndexes($changes['name']), $this->listTableConstraints($changes['name']));
176  foreach ($idx as $index_name) {
177  $index_newname = preg_replace("/^$name/", $changes['name'], $index_name);
178  $result = $db->manipulate("ALTER INDEX " . $this->getIndexName($index_name) . " RENAME TO " . $this->getIndexName($index_newname));
179  }
180  }
181 
182  return true;
183  }
184 
185 
190  public function listTableFields($table) {
191  $db = $this->db_instance;
192 
193  $table = $db->quoteIdentifier($table, true);
194  $res = $this->pdo->query("select * from $table");
195  for ($i = 0; $i < $res->columnCount(); $i++) {
196  $data[] = $res->getColumnMeta($i)["name"];
197  }
198  return $data;
199  }
200 
201 
206  public function listTableIndexes($table) {
207  $db = $this->db_instance;
208 
209  $table = $db->quote($table, 'text');
210  $subquery = "SELECT indexrelid FROM pg_index, pg_class";
211  $subquery .= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'";
212  $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
213  $indexes = $db->queryCol($query, 'text');
214 
215  $result = array();
216  foreach ($indexes as $index) {
217  $index = $this->fixIndexName($index);
218  if (!empty($index)) {
219  $result[$index] = true;
220  }
221  }
222 
223  if ($db->options['portability']) {
224  $result = array_change_key_case($result, $db->options['field_case']);
225  }
226 
227  return array_keys($result);
228  }
229 
230 
235  public function listTableConstraints($table) {
236  $db = $this->db_instance;
237 
238  $table = $db->quote($table, 'text');
239  $subquery = "SELECT indexrelid FROM pg_index, pg_class";
240  $subquery .= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
241  $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
242  $constraints = $db->queryCol($query);
243 
244  $result = array();
245  foreach ($constraints as $constraint) {
246  $constraint = $this->fixIndexName($constraint);
247  if (!empty($constraint)) {
248  $result[$constraint] = true;
249  }
250  }
251 
252  if ($db->options['portability']
253  && $db->options['field_case'] == CASE_LOWER
254  ) {
255  $result = array_change_key_case($result, $db->options['field_case']);
256  }
257 
258  return array_keys($result);
259  }
260 
261 
268  public function createSequence($seq_name, $start = 1, $options = array()) {
269  $db = $this->db_instance;
270 
271  $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
272 
273  return $db->manipulate("CREATE SEQUENCE $sequence_name INCREMENT 1" . ($start < 1 ? " MINVALUE $start" : '') . " START $start");
274  }
275 
276 
281  public function dropSequence($seq_name) {
282  $db = $this->db_instance;
283 
284  $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
285 
286  return $db->manipulate("DROP SEQUENCE $sequence_name");
287  }
288 
289 
295  public function dropIndex($table, $name) {
296  $db = $this->db_instance;
297 
298  $name = $this->getIndexName($name);
299  $name = $db->quoteIdentifier($this->getDBInstance()->constraintName($table, $name), true);
300 
301  return $db->manipulate("DROP INDEX $name");
302  }
303 
304 
309  protected function fixIndexName($idx) {
310  $idx_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBPdoFieldDefinition::INDEX_FORMAT) . '$/i';
311  $idx_name = preg_replace($idx_pattern, '\\1', $idx);
312  if ($idx_name && !strcasecmp($idx, $this->db_instance->getIndexName($idx_name))) {
313  return $idx_name;
314  }
315 
316  return $idx;
317  }
318 
319 
324  public function listSequences($database = null) {
325  $db = $this->db_instance;
326 
327  $query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
328  $query .= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
329  $table_names = $db->queryCol($query);
330 
331  $result = array();
332  foreach ($table_names as $table_name) {
333  $result[] = $this->fixSequenceName($table_name);
334  }
335  if ($db->options['portability']) {
336  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
337  }
338  sort($result); // FSX patch
339 
340  return $result;
341  }
342 
343 
350  public function dropConstraint($table, $name, $primary = false) {
351  $table_quoted = $this->getDBInstance()->quoteIdentifier($table, true);
352  $name = $this->getDBInstance()->quoteIdentifier($table . '_' . $this->getDBInstance()->getIndexName($name), true);
353 
354  return $this->pdo->exec("ALTER TABLE $table_quoted DROP CONSTRAINT $name");
355  }
356 }
dropConstraint($table, $name, $primary=false)
alterTable($name, $changes, $check)
$result
fixSequenceName($sqn, $check=false)
getTableCreationQuery($name, $fields, $options=array())
Class ilDatabaseException.
createTable($name, $fields, $options=array())
if(!is_array($argv)) $options
createSequence($seq_name, $start=1, $options=array())
Create styles array
The data for the language used.
Class ilPostgresQueryUtils.
Class ilDBPdoManager.