1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class PgSqlDriver extends Object implements ISupplementalDriver
22: {
23:
24: private $connection;
25:
26:
27: public function __construct(Connection $connection, array $options)
28: {
29: $this->connection = $connection;
30: }
31:
32:
33:
34:
35:
36: 37: 38:
39: public function delimite($name)
40: {
41:
42: return '"' . str_replace('"', '""', $name) . '"';
43: }
44:
45:
46: 47: 48:
49: public function formatBool($value)
50: {
51: return $value ? 'TRUE' : 'FALSE';
52: }
53:
54:
55: 56: 57:
58: public function formatDateTime(DateTime $value)
59: {
60: return $value->format("'Y-m-d H:i:s'");
61: }
62:
63:
64: 65: 66:
67: public function formatLike($value, $pos)
68: {
69: $value = strtr($value, array("'" => "''", '\\' => '\\\\', '%' => '\\\\%', '_' => '\\\\_'));
70: return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
71: }
72:
73:
74: 75: 76:
77: public function applyLimit(& $sql, $limit, $offset)
78: {
79: if ($limit >= 0) {
80: $sql .= ' LIMIT ' . (int) $limit;
81: }
82: if ($offset > 0) {
83: $sql .= ' OFFSET ' . (int) $offset;
84: }
85: }
86:
87:
88: 89: 90:
91: public function normalizeRow($row, $statement)
92: {
93: return $row;
94: }
95:
96:
97:
98:
99:
100: 101: 102:
103: public function getTables()
104: {
105: $tables = array();
106: foreach ($this->connection->query("
107: SELECT
108: c.relname::varchar AS name,
109: c.relkind = 'v' AS view
110: FROM
111: pg_catalog.pg_class AS c
112: JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
113: WHERE
114: c.relkind IN ('r', 'v')
115: AND n.nspname = current_schema()
116: ORDER BY
117: c.relname
118: ") as $row) {
119: $tables[] = (array) $row;
120: }
121:
122: return $tables;
123: }
124:
125:
126: 127: 128:
129: public function getColumns($table)
130: {
131: $columns = array();
132: foreach ($this->connection->query("
133: SELECT
134: a.attname::varchar AS name,
135: c.relname::varchar AS table,
136: upper(t.typname) AS nativetype,
137: NULL AS size,
138: FALSE AS unsigned,
139: NOT (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS nullable,
140: ad.adsrc::varchar AS default,
141: coalesce(co.contype = 'p' AND strpos(ad.adsrc, 'nextval') = 1, FALSE) AS autoincrement,
142: coalesce(co.contype = 'p', FALSE) AS primary,
143: substring(ad.adsrc from 'nextval[(]''\"?([^''\"]+)') AS sequence
144: FROM
145: pg_catalog.pg_attribute AS a
146: JOIN pg_catalog.pg_class AS c ON a.attrelid = c.oid
147: JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
148: JOIN pg_catalog.pg_type AS t ON a.atttypid = t.oid
149: LEFT JOIN pg_catalog.pg_attrdef AS ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
150: LEFT JOIN pg_catalog.pg_constraint AS co ON co.connamespace = n.oid AND contype = 'p' AND co.conrelid = c.oid AND a.attnum = ANY(co.conkey)
151: WHERE
152: c.relkind IN ('r', 'v')
153: AND c.relname::varchar = {$this->connection->quote($table)}
154: AND n.nspname = current_schema()
155: AND a.attnum > 0
156: AND NOT a.attisdropped
157: ORDER BY
158: a.attnum
159: ") as $row) {
160: $column = (array) $row;
161: $column['vendor'] = $column;
162: unset($column['sequence']);
163:
164: $columns[] = $column;
165: }
166:
167: return $columns;
168: }
169:
170:
171: 172: 173:
174: public function getIndexes($table)
175: {
176: $indexes = array();
177: foreach ($this->connection->query("
178: SELECT
179: c2.relname::varchar AS name,
180: i.indisunique AS unique,
181: i.indisprimary AS primary,
182: a.attname::varchar AS column
183: FROM
184: pg_catalog.pg_class AS c1
185: JOIN pg_catalog.pg_namespace AS n ON c1.relnamespace = n.oid
186: JOIN pg_catalog.pg_index AS i ON c1.oid = i.indrelid
187: JOIN pg_catalog.pg_class AS c2 ON i.indexrelid = c2.oid
188: LEFT JOIN pg_catalog.pg_attribute AS a ON c1.oid = a.attrelid AND a.attnum = ANY(i.indkey)
189: WHERE
190: n.nspname = current_schema()
191: AND c1.relkind = 'r'
192: AND c1.relname = {$this->connection->quote($table)}
193: ") as $row) {
194: $indexes[$row['name']]['name'] = $row['name'];
195: $indexes[$row['name']]['unique'] = $row['unique'];
196: $indexes[$row['name']]['primary'] = $row['primary'];
197: $indexes[$row['name']]['columns'][] = $row['column'];
198: }
199:
200: return array_values($indexes);
201: }
202:
203:
204: 205: 206:
207: public function getForeignKeys($table)
208: {
209:
210: return $this->connection->query("
211: SELECT
212: co.conname::varchar AS name,
213: al.attname::varchar AS local,
214: cf.relname::varchar AS table,
215: af.attname::varchar AS foreign
216: FROM
217: pg_catalog.pg_constraint AS co
218: JOIN pg_catalog.pg_namespace AS n ON co.connamespace = n.oid
219: JOIN pg_catalog.pg_class AS cl ON co.conrelid = cl.oid
220: JOIN pg_catalog.pg_class AS cf ON co.confrelid = cf.oid
221: JOIN pg_catalog.pg_attribute AS al ON al.attrelid = cl.oid AND al.attnum = co.conkey[1]
222: JOIN pg_catalog.pg_attribute AS af ON af.attrelid = cf.oid AND af.attnum = co.confkey[1]
223: WHERE
224: n.nspname = current_schema()
225: AND co.contype = 'f'
226: AND cl.relname = {$this->connection->quote($table)}
227: ")->fetchAll();
228: }
229:
230:
231: 232: 233:
234: public function isSupported($item)
235: {
236: return $item === self::SUPPORT_COLUMNS_META || $item === self::SUPPORT_SEQUENCE;
237: }
238:
239: }
240: