Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: Pgsql.php 7689 2010-08-25 23:50:42Z jwage $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information, see
19
 * <http://www.doctrine-project.org>.
20
 */
21
 
22
/**
23
 * @package     Doctrine
24
 * @subpackage  Import
25
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
26
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
27
 * @author      Paul Cooper <pgc@ucecom.com>
28
 * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
29
 * @version     $Revision: 7689 $
30
 * @link        www.doctrine-project.org
31
 * @since       1.0
32
 */
33
class Doctrine_Import_Pgsql extends Doctrine_Import
34
{
35
 
36
    protected $sql = array(
37
                        'listDatabases' => 'SELECT datname FROM pg_database',
38
                        'listFunctions' => "SELECT
39
                                                proname
40
                                            FROM
41
                                                pg_proc pr,
42
                                                pg_type tp
43
                                            WHERE
44
                                                tp.oid = pr.prorettype
45
                                                AND pr.proisagg = FALSE
46
                                                AND tp.typname <> 'trigger'
47
                                                AND pr.pronamespace IN
48
                                                    (SELECT oid FROM pg_namespace
49
                                                     WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema'",
50
                        'listSequences' => "SELECT
51
                                                regexp_replace(relname, '_seq$', '')
52
                                            FROM
53
                                                pg_class
54
                                            WHERE relkind = 'S' AND relnamespace IN
55
                                                (SELECT oid FROM pg_namespace
56
                                                 WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')",
57
                        'listTables'    => "SELECT
58
                                                c.relname AS table_name
59
                                            FROM pg_class c, pg_user u
60
                                            WHERE c.relowner = u.usesysid
61
                                                AND c.relkind = 'r'
62
                                                AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname AND schemaname <> 'information_schema')
63
                                                AND c.relname !~ '^(pg_|sql_)'
64
                                            UNION
65
                                            SELECT c.relname AS table_name
66
                                            FROM pg_class c
67
                                            WHERE c.relkind = 'r'
68
                                                AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)
69
                                                AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner)
70
                                                AND c.relname !~ '^pg_'",
71
                        'listViews'     => 'SELECT viewname FROM pg_views',
72
                        'listUsers'     => 'SELECT usename FROM pg_user',
73
                        'listTableConstraints' => "SELECT
74
                                                        relname
75
                                                   FROM
76
                                                        pg_class
77
                                                   WHERE oid IN (
78
                                                        SELECT indexrelid
79
                                                        FROM pg_index, pg_class
80
                                                        WHERE pg_class.relname = %s
81
                                                            AND pg_class.oid = pg_index.indrelid
82
                                                            AND (indisunique = 't' OR indisprimary = 't')
83
                                                        )",
84
                        'listTableIndexes'     => "SELECT
85
                                                        relname
86
                                                   FROM
87
                                                        pg_class
88
                                                   WHERE oid IN (
89
                                                        SELECT indexrelid
90
                                                        FROM pg_index, pg_class
91
                                                        WHERE pg_class.relname = %s
92
                                                            AND pg_class.oid=pg_index.indrelid
93
                                                            AND indisunique != 't'
94
                                                            AND indisprimary != 't'
95
                                                        )",
96
                        'listTableColumns'     => "SELECT
97
                                                     ordinal_position as attnum,
98
                                                     column_name as field,
99
                                                     udt_name as type,
100
                                                     data_type as complete_type,
101
                                                     is_nullable as isnotnull,
102
                                                     column_default as default,
103
                                                     (
104
                                                       SELECT 't'
105
                                                         FROM pg_index, pg_attribute a, pg_class c, pg_type t
106
                                                         WHERE c.relname = table_name AND a.attname = column_name
107
                                                         AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid
108
                                                         AND c.oid = pg_index.indrelid AND a.attnum = ANY (pg_index.indkey)
109
                                                         AND pg_index.indisprimary = 't'
110
                                                     ) as pri,
111
                                                     character_maximum_length as length
112
                                                   FROM information_schema.COLUMNS
113
                                                   WHERE table_name = %s
114
                                                   ORDER BY ordinal_position",
115
                        'listTableRelations'   => "SELECT pg_catalog.pg_get_constraintdef(oid, true) as condef
116
                                                          FROM pg_catalog.pg_constraint r
117
                                                          WHERE r.conrelid =
118
                                                          (
119
                                                              SELECT c.oid
120
                                                              FROM pg_catalog.pg_class c
121
                                                              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
122
                                                              WHERE c.relname ~ ? AND pg_catalog.pg_table_is_visible(c.oid)
123
                                                          )
124
                                                          AND r.contype = 'f'"
125
                        );
126
 
127
    /**
128
     * lists all database triggers
129
     *
130
     * @param string|null $database
131
     * @return array
132
     */
133
    public function listTriggers($database = null)
134
    {
135
 
136
    }
137
 
138
    /**
139
     * lists table constraints
140
     *
141
     * @param string $table     database table name
142
     * @return array
143
     */
144
    public function listTableConstraints($table)
145
    {
146
        $table = $this->conn->quote($table);
147
        $query = sprintf($this->sql['listTableConstraints'], $table);
148
 
149
        return $this->conn->fetchColumn($query);
150
    }
151
 
152
    /**
153
     * lists table constraints
154
     *
155
     * @param string $table     database table name
156
     * @return array
157
     */
158
    public function listTableColumns($table)
159
    {
160
        $table = $this->conn->quote($table);
161
        $query = sprintf($this->sql['listTableColumns'], $table);
162
        $result = $this->conn->fetchAssoc($query);
163
 
164
        $columns     = array();
165
        foreach ($result as $key => $val) {
166
            $val = array_change_key_case($val, CASE_LOWER);
167
 
168
            if ($val['type'] == 'character varying') {
169
                // get length from varchar definition
170
                $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $val['complete_type']);
171
                $val['length'] = $length;
172
            } else if (strpos($val['complete_type'], 'character varying') !== false) {
173
                // get length from varchar definition
174
                $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $val['complete_type']);
175
                $val['length'] = $length;
176
            }
177
 
178
            $decl = $this->conn->dataDict->getPortableDeclaration($val);
179
 
180
            $description = array(
181
                'name'      => $val['field'],
182
                'ntype'     => $val['type'],
183
                'type'      => $decl['type'][0],
184
                'alltypes'  => $decl['type'],
185
                'length'    => $decl['length'],
186
                'fixed'     => (bool) $decl['fixed'],
187
                'unsigned'  => (bool) $decl['unsigned'],
188
                'notnull'   => ($val['isnotnull'] == 'NO'),
189
                'default'   => $val['default'],
190
                'primary'   => ($val['pri'] == 't'),
191
            );
192
 
193
            // If postgres enum type
194
            if ($val['typtype'] == 'e'){
195
                $description['default'] = isset($decl['default']) ? $decl['default'] : null;
196
                $t_result = $this->conn->fetchAssoc(sprintf('select enum_range(null::%s) as range ', $decl['enum_name']));
197
                if (isset($t_result[0])){
198
                    $range =  $t_result[0]['range'];
199
                    $range = str_replace('{','',$range);
200
                    $range = str_replace('}','',$range);
201
                    $range = explode(',',$range);
202
                    $description['values'] = $range;
203
                }
204
            }
205
 
206
            $matches = array();
207
 
208
            if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $description['default'], $matches)) {
209
                $description['sequence'] = $this->conn->formatter->fixSequenceName($matches[1]);
210
                $description['default'] = null;
211
            } else if (preg_match("/^'(.*)'::character varying$/", $description['default'], $matches)) {
212
                $description['default'] = $matches[1];
213
            } else if (preg_match("/^(.*)::character varying$/", $description['default'], $matches)) {
214
                $description['default'] = $matches[1];
215
            } else if ($description['type'] == 'boolean') {
216
                if ($description['default'] === 'true') {
217
                   $description['default'] = true;
218
                } else if ($description['default'] === 'false') {
219
                   $description['default'] = false;
220
                }
221
            }
222
 
223
            $columns[$val['field']] = $description;
224
        }
225
 
226
        return $columns;
227
    }
228
 
229
    /**
230
     * list all indexes in a table
231
     *
232
     * @param string $table     database table name
233
     * @return array
234
     */
235
    public function listTableIndexes($table)
236
    {
237
        $table = $this->conn->quote($table);
238
        $query = sprintf($this->sql['listTableIndexes'], $table);
239
 
240
        return $this->conn->fetchColumn($query);
241
    }
242
 
243
    /**
244
     * lists tables
245
     *
246
     * @param string|null $database
247
     * @return array
248
     */
249
    public function listTables($database = null)
250
    {
251
        return $this->conn->fetchColumn($this->sql['listTables']);
252
    }
253
 
254
    /**
255
     * lists table triggers
256
     *
257
     * @param string $table     database table name
258
     * @return array
259
     */
260
    public function listTableTriggers($table)
261
    {
262
        $query = 'SELECT trg.tgname AS trigger_name
263
                    FROM pg_trigger trg,
264
                         pg_class tbl
265
                   WHERE trg.tgrelid = tbl.oid';
266
        if ($table !== null) {
267
            $table = $this->conn->quote(strtoupper($table), 'string');
268
            $query .= " AND tbl.relname = $table";
269
        }
270
        return $this->conn->fetchColumn($query);
271
    }
272
 
273
    /**
274
     * list the views in the database that reference a given table
275
     *
276
     * @param string $table     database table name
277
     * @return array
278
     */
279
    public function listTableViews($table)
280
    {
281
        return $this->conn->fetchColumn($table);
282
    }
283
 
284
    public function listTableRelations($table)
285
    {
286
        $sql = $this->sql['listTableRelations'];
287
        $param = array('^(' . $table . ')$');
288
 
289
        $relations = array();
290
 
291
        $results = $this->conn->fetchAssoc($sql, $param);
292
        foreach ($results as $result) {
293
            preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $result['condef'], $values);
294
            if ((strpos($values[1], ',') === false) && (strpos($values[3], ',') === false)) {
295
                $tableName = trim($values[2], '"');
296
                $relations[] = array('table'   => $tableName,
297
                                     'local'   => $values[1],
298
                                     'foreign' => $values[3]);
299
            }
300
        }
301
 
302
        return $relations;
303
    }
304
}