annotate examples/trac/trac/db/postgres_backend.py @ 39:93b4dcbafd7b trunk

Copy Trac to main branch.
author cmlenz
date Mon, 03 Jul 2006 18:53:27 +0000
parents
children
rev   line source
39
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
2 #
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2005 Edgewall Software
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
4 # Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
5 # All rights reserved.
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
6 #
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
7 # This software is licensed as described in the file COPYING, which
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
8 # you should have received as part of this distribution. The terms
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
9 # are also available at http://trac.edgewall.com/license.html.
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
10 #
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
11 # This software consists of voluntary contributions made by many
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
12 # individuals. For the exact contribution history, see the revision
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
13 # history and logs, available at http://projects.edgewall.com/trac/.
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
14 #
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
15 # Author: Christopher Lenz <cmlenz@gmx.de>
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
16
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
17 import re
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
18
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
19 from trac.core import *
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
20 from trac.db.api import IDatabaseConnector
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
21 from trac.db.util import ConnectionWrapper
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
22
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
23 psycopg = None
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
24 PgSQL = None
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
25 PGSchemaError = None
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
26
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
27 _like_escape_re = re.compile(r'([/_%])')
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
28
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
29
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
30 class PostgreSQLConnector(Component):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
31 """PostgreSQL database support."""
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
32
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
33 implements(IDatabaseConnector)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
34
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
35 def get_supported_schemes(self):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
36 return [('postgres', 1)]
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
37
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
38 def get_connection(self, path, user=None, password=None, host=None,
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
39 port=None, params={}):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
40 return PostgreSQLConnection(path, user, password, host, port, params)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
41
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
42 def init_db(self, path, user=None, password=None, host=None, port=None,
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
43 params={}):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
44 cnx = self.get_connection(path, user, password, host, port, params)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
45 cursor = cnx.cursor()
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
46 if cnx.schema:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
47 cursor.execute('CREATE SCHEMA %s' % cnx.schema)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
48 cursor.execute('SET search_path TO %s, public', (cnx.schema,))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
49 from trac.db_default import schema
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
50 for table in schema:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
51 for stmt in self.to_sql(table):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
52 cursor.execute(stmt)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
53 cnx.commit()
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
54
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
55 def to_sql(self, table):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
56 sql = ["CREATE TABLE %s (" % table.name]
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
57 coldefs = []
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
58 for column in table.columns:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
59 ctype = column.type
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
60 if column.auto_increment:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
61 ctype = "SERIAL"
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
62 if len(table.key) == 1 and column.name in table.key:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
63 ctype += " PRIMARY KEY"
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
64 coldefs.append(" %s %s" % (column.name, ctype))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
65 if len(table.key) > 1:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
66 coldefs.append(" CONSTRAINT %s_pk PRIMARY KEY (%s)"
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
67 % (table.name, ','.join(table.key)))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
68 sql.append(',\n'.join(coldefs) + '\n)')
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
69 yield '\n'.join(sql)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
70 for index in table.indices:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
71 yield "CREATE INDEX %s_%s_idx ON %s (%s)" % (table.name,
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
72 '_'.join(index.columns), table.name, ','.join(index.columns))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
73
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
74
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
75 class PostgreSQLConnection(ConnectionWrapper):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
76 """Connection wrapper for PostgreSQL."""
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
77
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
78 poolable = True
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
79
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
80 def __init__(self, path, user=None, password=None, host=None, port=None,
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
81 params={}):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
82 if path.startswith('/'):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
83 path = path[1:]
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
84 # We support both psycopg and PgSQL but prefer psycopg
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
85 global psycopg
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
86 global PgSQL
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
87 global PGSchemaError
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
88
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
89 if not psycopg and not PgSQL:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
90 try:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
91 import psycopg2 as psycopg
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
92 import psycopg2.extensions
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
93 from psycopg2 import ProgrammingError as PGSchemaError
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
94 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
95 except ImportError:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
96 from pyPgSQL import PgSQL
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
97 from pyPgSQL.libpq import OperationalError as PGSchemaError
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
98 if psycopg:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
99 dsn = []
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
100 if path:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
101 dsn.append('dbname=' + path)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
102 if user:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
103 dsn.append('user=' + user)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
104 if password:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
105 dsn.append('password=' + password)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
106 if host:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
107 dsn.append('host=' + host)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
108 if port:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
109 dsn.append('port=' + str(port))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
110 cnx = psycopg.connect(' '.join(dsn))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
111 cnx.set_client_encoding('UNICODE')
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
112 else:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
113 cnx = PgSQL.connect('', user, password, host, path, port,
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
114 client_encoding='utf-8', unicode_results=True)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
115 try:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
116 self.schema = None
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
117 if 'schema' in params:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
118 self.schema = params['schema']
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
119 cnx.cursor().execute('SET search_path TO %s, public',
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
120 (self.schema,))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
121 except PGSchemaError:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
122 cnx.rollback()
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
123 ConnectionWrapper.__init__(self, cnx)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
124
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
125 def cast(self, column, type):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
126 # Temporary hack needed for the union of selects in the search module
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
127 return 'CAST(%s AS %s)' % (column, type)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
128
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
129 def like(self):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
130 # Temporary hack needed for the case-insensitive string matching in the
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
131 # search module
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
132 return "ILIKE %s ESCAPE '/'"
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
133
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
134 def like_escape(self, text):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
135 return _like_escape_re.sub(r'/\1', text)
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
136
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
137 def get_last_id(self, cursor, table, column='id'):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
138 cursor.execute("SELECT CURRVAL('%s_%s_seq')" % (table, column))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
139 return cursor.fetchone()[0]
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
140
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
141 def rollback(self):
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
142 self.cnx.rollback()
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
143 if self.schema:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
144 try:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
145 self.cnx.cursor().execute("SET search_path TO %s, public",
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
146 (self.schema,))
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
147 except PGSchemaError:
93b4dcbafd7b Copy Trac to main branch.
cmlenz
parents:
diff changeset
148 self.cnx.rollback()
Copyright (C) 2012-2017 Edgewall Software