ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
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  {
55  $db = $this->db_instance;
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  {
79  $db = $this->db_instance;
80  $name = $db->quoteIdentifier($name, true);
81 
82  return $db->manipulate("CREATE DATABASE $name");
83  }
84 
85 
90  public function dropDatabase($name)
91  {
92  $db = $this->db_instance;
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 }
dropConstraint($table, $name, $primary=false)
alterTable($name, $changes, $check)
$data
Definition: storeScorm.php:23
$result
fixSequenceName($sqn, $check=false)
getTableCreationQuery($name, $fields, $options=array())
Class ilDatabaseException.
$index
Definition: metadata.php:128
createTable($name, $fields, $options=array())
if($format !==null) $name
Definition: metadata.php:230
foreach($_POST as $key=> $value) $res
$query
createSequence($seq_name, $start=1, $options=array())
Class ilPostgresQueryUtils.
Class ilDBPdoManager.
$i
Definition: metadata.php:24