|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Select builder for PostgreSQL database engine. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * @addtogroup database |
|
10 * @{ |
|
11 */ |
|
12 |
|
13 class SelectQuery_pgsql extends SelectQuery { |
|
14 |
|
15 public function orderRandom() { |
|
16 $alias = $this->addExpression('RANDOM()', 'random_field'); |
|
17 $this->orderBy($alias); |
|
18 return $this; |
|
19 } |
|
20 |
|
21 /** |
|
22 * Overrides SelectQuery::orderBy(). |
|
23 * |
|
24 * PostgreSQL adheres strictly to the SQL-92 standard and requires that when |
|
25 * using DISTINCT or GROUP BY conditions, fields and expressions that are |
|
26 * ordered on also need to be selected. This is a best effort implementation |
|
27 * to handle the cases that can be automated by adding the field if it is not |
|
28 * yet selected. |
|
29 * |
|
30 * @code |
|
31 * $query = db_select('node', 'n'); |
|
32 * $query->join('node_revision', 'nr', 'n.vid = nr.vid'); |
|
33 * $query |
|
34 * ->distinct() |
|
35 * ->fields('n') |
|
36 * ->orderBy('timestamp'); |
|
37 * @endcode |
|
38 * |
|
39 * In this query, it is not possible (without relying on the schema) to know |
|
40 * whether timestamp belongs to node_revisions and needs to be added or |
|
41 * belongs to node and is already selected. Queries like this will need to be |
|
42 * corrected in the original query by adding an explicit call to |
|
43 * SelectQuery::addField() or SelectQuery::fields(). |
|
44 * |
|
45 * Since this has a small performance impact, both by the additional |
|
46 * processing in this function and in the database that needs to return the |
|
47 * additional fields, this is done as an override instead of implementing it |
|
48 * directly in SelectQuery::orderBy(). |
|
49 */ |
|
50 public function orderBy($field, $direction = 'ASC') { |
|
51 // Call parent function to order on this. |
|
52 $return = parent::orderBy($field, $direction); |
|
53 |
|
54 // If there is a table alias specified, split it up. |
|
55 if (strpos($field, '.') !== FALSE) { |
|
56 list($table, $table_field) = explode('.', $field); |
|
57 } |
|
58 // Figure out if the field has already been added. |
|
59 foreach ($this->fields as $existing_field) { |
|
60 if (!empty($table)) { |
|
61 // If table alias is given, check if field and table exists. |
|
62 if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) { |
|
63 return $return; |
|
64 } |
|
65 } |
|
66 else { |
|
67 // If there is no table, simply check if the field exists as a field or |
|
68 // an aliased field. |
|
69 if ($existing_field['alias'] == $field) { |
|
70 return $return; |
|
71 } |
|
72 } |
|
73 } |
|
74 |
|
75 // Also check expression aliases. |
|
76 foreach ($this->expressions as $expression) { |
|
77 if ($expression['alias'] == $field) { |
|
78 return $return; |
|
79 } |
|
80 } |
|
81 |
|
82 // If a table loads all fields, it can not be added again. It would |
|
83 // result in an ambiguous alias error because that field would be loaded |
|
84 // twice: Once through table_alias.* and once directly. If the field |
|
85 // actually belongs to a different table, it must be added manually. |
|
86 foreach ($this->tables as $table) { |
|
87 if (!empty($table['all_fields'])) { |
|
88 return $return; |
|
89 } |
|
90 } |
|
91 |
|
92 // If $field contains an characters which are not allowed in a field name |
|
93 // it is considered an expression, these can't be handled automatically |
|
94 // either. |
|
95 if ($this->connection->escapeField($field) != $field) { |
|
96 return $return; |
|
97 } |
|
98 |
|
99 // This is a case that can be handled automatically, add the field. |
|
100 $this->addField(NULL, $field); |
|
101 return $return; |
|
102 } |
|
103 } |
|
104 |
|
105 /** |
|
106 * @} End of "addtogroup database". |
|
107 */ |
|
108 |