Mercurial > p > roundup > code
annotate roundup/backends/rdbms_common.py @ 2077:3e0961d6d44d
Added the "actor" property.
Metakit backend not done (still not confident I know how it's supposed
to work ;)
Currently it will come up as NULL in the RDBMS backends for older items.
The *dbm backends will look up the journal. I hope to remedy the former
before 0.7's release.
Fixed a bunch of migration issues in the rdbms backends while I was at it
(index changes for key prop changes) and simplified the class table update
code for RDBMSes that have "alter table" in their command set (ie. not
sqlite) ... migration from "version 1" to "version 2" still hasn't
actually been tested yet though.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Mon, 15 Mar 2004 05:50:20 +0000 |
| parents | 2a4309450202 |
| children | fb4bf55b94d7 |
| rev | line source |
|---|---|
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1 # $Id: rdbms_common.py,v 1.79 2004-03-15 05:50:20 richard Exp $ |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
2 ''' Relational database (SQL) backend common code. |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
3 |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
4 Basics: |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
5 |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
6 - map roundup classes to relational tables |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
7 - automatically detect schema changes and modify the table schemas |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
8 appropriately (we store the "database version" of the schema in the |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
9 database itself as the only row of the "schema" table) |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
10 - multilinks (which represent a many-to-many relationship) are handled through |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
11 intermediate tables |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
12 - journals are stored adjunct to the per-class tables |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
13 - table names and columns have "_" prepended so the names can't clash with |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
14 restricted names (like "order") |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
15 - retirement is determined by the __retired__ column being true |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
16 |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
17 Database-specific changes may generally be pushed out to the overridable |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
18 sql_* methods, since everything else should be fairly generic. There's |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
19 probably a bit of work to be done if a database is used that actually |
|
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
20 honors column typing, since the initial databases don't (sqlite stores |
|
1528
96cd422532ef
bye bye gadfly - you served your purpose well [SF#701127]
Richard Jones <richard@users.sourceforge.net>
parents:
1523
diff
changeset
|
21 everything as a string.) |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
22 |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
23 The schema of the hyperdb being mapped to the database is stored in the |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
24 database itself as a repr()'ed dictionary of information about each Class |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
25 that maps to a table. If that information differs from the hyperdb schema, |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
26 then we update it. We also store in the schema dict a version which |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
27 allows us to upgrade the database schema when necessary. See upgrade_db(). |
|
1244
8dd4f736370b
merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents:
1222
diff
changeset
|
28 ''' |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
29 __docformat__ = 'restructuredtext' |
| 1165 | 30 |
| 31 # standard python modules | |
| 32 import sys, os, time, re, errno, weakref, copy | |
| 33 | |
| 34 # roundup modules | |
| 35 from roundup import hyperdb, date, password, roundupdb, security | |
| 36 from roundup.hyperdb import String, Password, Date, Interval, Link, \ | |
|
1417
472c21af7f69
fixed error in indexargs_url (thanks Patrick Ohly)
Richard Jones <richard@users.sourceforge.net>
parents:
1415
diff
changeset
|
37 Multilink, DatabaseError, Boolean, Number, Node |
|
1333
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
38 from roundup.backends import locking |
| 1165 | 39 |
| 40 # support | |
| 41 from blobfiles import FileStorage | |
| 42 from roundup.indexer import Indexer | |
|
1467
378081f066cc
registration is now a two-step process with confirmation from the
Richard Jones <richard@users.sourceforge.net>
parents:
1442
diff
changeset
|
43 from sessions import Sessions, OneTimeKeys |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
44 from roundup.date import Range |
| 1165 | 45 |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
46 # number of rows to keep in memory |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
47 ROW_CACHE_SIZE = 100 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
48 |
| 1165 | 49 class Database(FileStorage, hyperdb.Database, roundupdb.Database): |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
50 ''' Wrapper around an SQL database that presents a hyperdb interface. |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
51 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
52 - some functionality is specific to the actual SQL database, hence |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
53 the sql_* methods that are NotImplemented |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
54 - we keep a cache of the latest ROW_CACHE_SIZE row fetches. |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
55 ''' |
| 1165 | 56 def __init__(self, config, journaltag=None): |
| 57 ''' Open the database and load the schema from it. | |
| 58 ''' | |
| 59 self.config, self.journaltag = config, journaltag | |
| 60 self.dir = config.DATABASE | |
| 61 self.classes = {} | |
| 62 self.indexer = Indexer(self.dir) | |
| 63 self.sessions = Sessions(self.config) | |
|
1467
378081f066cc
registration is now a two-step process with confirmation from the
Richard Jones <richard@users.sourceforge.net>
parents:
1442
diff
changeset
|
64 self.otks = OneTimeKeys(self.config) |
| 1165 | 65 self.security = security.Security(self) |
| 66 | |
| 67 # additional transaction support for external files and the like | |
| 68 self.transactions = [] | |
| 69 | |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
70 # keep a cache of the N most recently retrieved rows of any kind |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
71 # (classname, nodeid) = row |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
72 self.cache = {} |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
73 self.cache_lru = [] |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
74 |
|
1333
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
75 # database lock |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
76 self.lockfile = None |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
77 |
| 1165 | 78 # open a connection to the database, creating the "conn" attribute |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
79 self.sql_open_connection() |
| 1165 | 80 |
|
1181
49aebf5a8691
some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents:
1176
diff
changeset
|
81 def clearCache(self): |
|
49aebf5a8691
some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents:
1176
diff
changeset
|
82 self.cache = {} |
|
49aebf5a8691
some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents:
1176
diff
changeset
|
83 self.cache_lru = [] |
|
49aebf5a8691
some speedups, some fixes to the benchmarking
Richard Jones <richard@users.sourceforge.net>
parents:
1176
diff
changeset
|
84 |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
85 def sql_open_connection(self): |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
86 ''' Open a connection to the database, creating it if necessary. |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
87 |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
88 Must call self.load_dbschema() |
| 1165 | 89 ''' |
| 90 raise NotImplemented | |
| 91 | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
92 def sql(self, sql, args=None): |
| 1165 | 93 ''' Execute the sql with the optional args. |
| 94 ''' | |
| 95 if __debug__: | |
| 96 print >>hyperdb.DEBUG, (self, sql, args) | |
| 97 if args: | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
98 self.cursor.execute(sql, args) |
| 1165 | 99 else: |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
100 self.cursor.execute(sql) |
| 1165 | 101 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
102 def sql_fetchone(self): |
| 1165 | 103 ''' Fetch a single row. If there's nothing to fetch, return None. |
| 104 ''' | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
105 return self.cursor.fetchone() |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
106 |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
107 def sql_fetchall(self): |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
108 ''' Fetch all rows. If there's nothing to fetch, return []. |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
109 ''' |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
110 return self.cursor.fetchall() |
| 1165 | 111 |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
112 def sql_stringquote(self, value): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
113 ''' Quote the string so it's safe to put in the 'sql quotes' |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
114 ''' |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
115 return re.sub("'", "''", str(value)) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
116 |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
117 def init_dbschema(self): |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
118 self.database_schema = { |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
119 'version': self.current_db_version, |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
120 'tables': {} |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
121 } |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
122 |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
123 def load_dbschema(self): |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
124 ''' Load the schema definition that the database currently implements |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
125 ''' |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
126 self.cursor.execute('select schema from schema') |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
127 schema = self.cursor.fetchone() |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
128 if schema: |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
129 self.database_schema = eval(schema[0]) |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
130 else: |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
131 self.database_schema = {} |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
132 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
133 def save_dbschema(self, schema): |
| 1165 | 134 ''' Save the schema definition that the database currently implements |
| 135 ''' | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
136 s = repr(self.database_schema) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
137 self.sql('insert into schema values (%s)', (s,)) |
| 1165 | 138 |
| 139 def post_init(self): | |
| 140 ''' Called once the schema initialisation has finished. | |
| 141 | |
| 142 We should now confirm that the schema defined by our "classes" | |
| 143 attribute actually matches the schema in the database. | |
| 144 ''' | |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
145 save = self.upgrade_db() |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
146 |
| 1165 | 147 # now detect changes in the schema |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
148 tables = self.database_schema['tables'] |
| 1165 | 149 for classname, spec in self.classes.items(): |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
150 if tables.has_key(classname): |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
151 dbspec = tables[classname] |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
152 if self.update_class(spec, dbspec): |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
153 tables[classname] = spec.schema() |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
154 save = 1 |
| 1165 | 155 else: |
| 156 self.create_class(spec) | |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
157 tables[classname] = spec.schema() |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
158 save = 1 |
| 1165 | 159 |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
160 for classname, spec in tables.items(): |
| 1165 | 161 if not self.classes.has_key(classname): |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
162 self.drop_class(classname, tables[classname]) |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
163 del tables[classname] |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
164 save = 1 |
| 1165 | 165 |
| 166 # update the database version of the schema | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
167 if save: |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
168 self.sql('delete from schema') |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
169 self.save_dbschema(self.database_schema) |
| 1165 | 170 |
| 171 # reindex the db if necessary | |
| 172 if self.indexer.should_reindex(): | |
| 173 self.reindex() | |
| 174 | |
| 175 # commit | |
| 176 self.conn.commit() | |
| 177 | |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
178 # update this number when we need to make changes to the SQL structure |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
179 # of the backen database |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
180 current_db_version = 2 |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
181 def upgrade_db(self): |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
182 ''' Update the SQL database to reflect changes in the backend code. |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
183 |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
184 Return boolean whether we need to save the schema. |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
185 ''' |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
186 version = self.database_schema.get('version', 1) |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
187 if version == 1: |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
188 # version 1 doesn't have the OTK, session and indexing in the |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
189 # database |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
190 self.create_version_2_tables() |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
191 # version 1 also didn't have the actor column |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
192 self.add_actor_column() |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
193 else: |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
194 return 0 |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
195 |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
196 self.database_schema['version'] = self.current_db_version |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
197 return 1 |
|
2073
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
198 |
|
261c2e6ceb1e
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
199 |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
200 def refresh_database(self): |
|
1951
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
201 self.post_init() |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
202 |
| 1165 | 203 def reindex(self): |
| 204 for klass in self.classes.values(): | |
| 205 for nodeid in klass.list(): | |
| 206 klass.index(nodeid) | |
| 207 self.indexer.save_index() | |
| 208 | |
| 209 def determine_columns(self, properties): | |
| 210 ''' Figure the column names and multilink properties from the spec | |
| 211 | |
| 212 "properties" is a list of (name, prop) where prop may be an | |
| 213 instance of a hyperdb "type" _or_ a string repr of that type. | |
| 214 ''' | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
215 cols = ['_actor', '_activity', '_creator', '_creation'] |
| 1165 | 216 mls = [] |
| 217 # add the multilinks separately | |
| 218 for col, prop in properties: | |
| 219 if isinstance(prop, Multilink): | |
| 220 mls.append(col) | |
| 221 elif isinstance(prop, type('')) and prop.find('Multilink') != -1: | |
| 222 mls.append(col) | |
| 223 else: | |
| 224 cols.append('_'+col) | |
| 225 cols.sort() | |
| 226 return cols, mls | |
| 227 | |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
228 def update_class(self, spec, old_spec, force=0): |
| 1165 | 229 ''' Determine the differences between the current spec and the |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
230 database version of the spec, and update where necessary. |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
231 |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
232 If 'force' is true, update the database anyway. |
| 1165 | 233 ''' |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
234 new_has = spec.properties.has_key |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
235 new_spec = spec.schema() |
|
1515
a516bbb9896b
fixed rdbms table update detection logic [SF#703297]
Richard Jones <richard@users.sourceforge.net>
parents:
1500
diff
changeset
|
236 new_spec[1].sort() |
|
a516bbb9896b
fixed rdbms table update detection logic [SF#703297]
Richard Jones <richard@users.sourceforge.net>
parents:
1500
diff
changeset
|
237 old_spec[1].sort() |
|
1840
91a4619b1a14
hyperdb grows a refresh_database() method.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1838
diff
changeset
|
238 if not force and new_spec == old_spec: |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
239 # no changes |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
240 return 0 |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
241 |
| 1165 | 242 if __debug__: |
| 243 print >>hyperdb.DEBUG, 'update_class FIRING' | |
| 244 | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
245 # detect key prop change for potential index change |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
246 keyprop_changes = 0 |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
247 if new_spec[0] != old_spec[0]: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
248 keyprop_changes = {'remove': old_spec[0], 'add': new_spec[0]} |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
249 |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
250 # detect multilinks that have been removed, and drop their table |
|
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
251 old_has = {} |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
252 for name, prop in old_spec[1]: |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
253 old_has[name] = 1 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
254 if new_has(name): |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
255 continue |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
256 |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
257 if isinstance(prop, Multilink): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
258 # first drop indexes. |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
259 self.drop_multilink_table_indexes(spec.classname, ml) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
260 |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
261 # now the multilink table itself |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
262 sql = 'drop table %s_%s'%(spec.classname, prop) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
263 else: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
264 # if this is the key prop, drop the index first |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
265 if old_spec[0] == prop: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
266 self.drop_class_table_key_index(spec.classname, prop) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
267 del keyprop_changes['remove'] |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
268 |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
269 # drop the column |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
270 sql = 'alter table _%s drop column _%s'%(spec.classname, prop) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
271 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
272 if __debug__: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
273 print >>hyperdb.DEBUG, 'update_class', (self, sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
274 self.cursor.execute(sql) |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
275 old_has = old_has.has_key |
|
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
276 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
277 # if we didn't remove the key prop just then, but the key prop has |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
278 # changed, we still need to remove the old index |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
279 if keyprop_changes.has_key('remove'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
280 self.drop_class_table_key_index(spec.classname, |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
281 keyprop_changes['remove']) |
| 1165 | 282 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
283 # add new columns |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
284 for propname, x in new_spec[1]: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
285 if old_has(propname): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
286 continue |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
287 sql = 'alter table _%s add column _%s varchar(255)'%( |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
288 spec.classname, propname) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
289 if __debug__: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
290 print >>hyperdb.DEBUG, 'update_class', (self, sql) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
291 self.cursor.execute(sql) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
292 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
293 # if the new column is a key prop, we need an index! |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
294 if new_spec[0] == propname: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
295 self.create_class_table_key_index(spec.classname, propname) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
296 del keyprop_changes['add'] |
| 1165 | 297 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
298 # if we didn't add the key prop just then, but the key prop has |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
299 # changed, we still need to add the new index |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
300 if keyprop_changes.has_key('add'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
301 self.create_class_table_key_index(spec.classname, |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
302 keyprop_changes['add']) |
|
1479
405e91b5be46
fixed rdbms mutation of properties
Richard Jones <richard@users.sourceforge.net>
parents:
1476
diff
changeset
|
303 |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
304 return 1 |
| 1165 | 305 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
306 def create_class_table(self, spec): |
| 1165 | 307 ''' create the class table for the given spec |
| 308 ''' | |
| 309 cols, mls = self.determine_columns(spec.properties.items()) | |
| 310 | |
| 311 # add on our special columns | |
| 312 cols.append('id') | |
| 313 cols.append('__retired__') | |
| 314 | |
| 315 # create the base table | |
| 316 scols = ','.join(['%s varchar'%x for x in cols]) | |
| 317 sql = 'create table _%s (%s)'%(spec.classname, scols) | |
| 318 if __debug__: | |
| 319 print >>hyperdb.DEBUG, 'create_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
320 self.cursor.execute(sql) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
321 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
322 self.create_class_table_indexes(spec) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
323 |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
324 return cols, mls |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
325 |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
326 def create_class_table_indexes(self, spec): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
327 ''' create the class table for the given spec |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
328 ''' |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
329 # create id index |
|
1836
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
330 index_sql1 = 'create index _%s_id_idx on _%s(id)'%( |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
331 spec.classname, spec.classname) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
332 if __debug__: |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
333 print >>hyperdb.DEBUG, 'create_index', (self, index_sql1) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
334 self.cursor.execute(index_sql1) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
335 |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
336 # create __retired__ index |
|
1836
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
337 index_sql2 = 'create index _%s_retired_idx on _%s(__retired__)'%( |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
338 spec.classname, spec.classname) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
339 if __debug__: |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
340 print >>hyperdb.DEBUG, 'create_index', (self, index_sql2) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
341 self.cursor.execute(index_sql2) |
| 1165 | 342 |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
343 # create index for key property |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
344 if spec.key: |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
345 if __debug__: |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
346 print >>hyperdb.DEBUG, 'update_class setting keyprop %r'% \ |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
347 spec.key |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
348 index_sql3 = 'create index _%s_%s_idx on _%s(_%s)'%( |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
349 spec.classname, spec.key, |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
350 spec.classname, spec.key) |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
351 if __debug__: |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
352 print >>hyperdb.DEBUG, 'create_index', (self, index_sql3) |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
353 self.cursor.execute(index_sql3) |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
354 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
355 def drop_class_table_indexes(self, cn, key): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
356 # drop the old table indexes first |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
357 l = ['_%s_id_idx'%cn, '_%s_retired_idx'%cn] |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
358 if key: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
359 l.append('_%s_%s_idx'%(cn, key)) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
360 |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
361 table_name = '_%s'%cn |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
362 for index_name in l: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
363 if not self.sql_index_exists(table_name, index_name): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
364 continue |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
365 index_sql = 'drop index '+index_name |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
366 if __debug__: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
367 print >>hyperdb.DEBUG, 'drop_index', (self, index_sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
368 self.cursor.execute(index_sql) |
| 1165 | 369 |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
370 def create_class_table_key_index(self, cn, key): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
371 ''' create the class table for the given spec |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
372 ''' |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
373 if __debug__: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
374 print >>hyperdb.DEBUG, 'update_class setting keyprop %r'% \ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
375 key |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
376 index_sql3 = 'create index _%s_%s_idx on _%s(_%s)'%(cn, key, |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
377 cn, key) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
378 if __debug__: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
379 print >>hyperdb.DEBUG, 'create_index', (self, index_sql3) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
380 self.cursor.execute(index_sql3) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
381 |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
382 def drop_class_table_key_index(self, cn, key): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
383 table_name = '_%s'%cn |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
384 index_name = '_%s_%s_idx'%(cn, key) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
385 if not self.sql_index_exists(table_name, index_name): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
386 return |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
387 sql = 'drop index '+index_name |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
388 if __debug__: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
389 print >>hyperdb.DEBUG, 'drop_index', (self, sql) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
390 self.cursor.execute(sql) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
391 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
392 def create_journal_table(self, spec): |
| 1165 | 393 ''' create the journal table for a class given the spec and |
| 394 already-determined cols | |
| 395 ''' | |
| 396 # journal table | |
| 397 cols = ','.join(['%s varchar'%x | |
| 398 for x in 'nodeid date tag action params'.split()]) | |
| 399 sql = 'create table %s__journal (%s)'%(spec.classname, cols) | |
| 400 if __debug__: | |
| 401 print >>hyperdb.DEBUG, 'create_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
402 self.cursor.execute(sql) |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
403 self.create_journal_table_indexes(spec) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
404 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
405 def create_journal_table_indexes(self, spec): |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
406 # index on nodeid |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
407 sql = 'create index %s_journ_idx on %s__journal(nodeid)'%( |
|
1836
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
408 spec.classname, spec.classname) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
409 if __debug__: |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
410 print >>hyperdb.DEBUG, 'create_index', (self, sql) |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
411 self.cursor.execute(sql) |
| 1165 | 412 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
413 def drop_journal_table_indexes(self, classname): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
414 index_name = '%s_journ_idx'%classname |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
415 if not self.sql_index_exists('%s__journal'%classname, index_name): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
416 return |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
417 index_sql = 'drop index '+index_name |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
418 if __debug__: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
419 print >>hyperdb.DEBUG, 'drop_index', (self, index_sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
420 self.cursor.execute(index_sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
421 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
422 def create_multilink_table(self, spec, ml): |
| 1165 | 423 ''' Create a multilink table for the "ml" property of the class |
| 424 given by the spec | |
| 425 ''' | |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
426 # create the table |
| 1165 | 427 sql = 'create table %s_%s (linkid varchar, nodeid varchar)'%( |
| 428 spec.classname, ml) | |
| 429 if __debug__: | |
| 430 print >>hyperdb.DEBUG, 'create_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
431 self.cursor.execute(sql) |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
432 self.create_multilink_table_indexes(spec, ml) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
433 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
434 def create_multilink_table_indexes(self, spec, ml): |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
435 # create index on linkid |
|
1836
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
436 index_sql = 'create index %s_%s_l_idx on %s_%s(linkid)'%( |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
437 spec.classname, ml, spec.classname, ml) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
438 if __debug__: |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
439 print >>hyperdb.DEBUG, 'create_index', (self, index_sql) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
440 self.cursor.execute(index_sql) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
441 |
|
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
442 # create index on nodeid |
|
1836
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
443 index_sql = 'create index %s_%s_n_idx on %s_%s(nodeid)'%( |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
444 spec.classname, ml, spec.classname, ml) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
445 if __debug__: |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
446 print >>hyperdb.DEBUG, 'create_index', (self, index_sql) |
|
94e430ad4fdb
make the RDBMS common backend and the SQLite and MYsql backend create...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1800
diff
changeset
|
447 self.cursor.execute(index_sql) |
| 1165 | 448 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
449 def drop_multilink_table_indexes(self, classname, ml): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
450 l = [ |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
451 '%s_%s_l_idx'%(classname, ml), |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
452 '%s_%s_n_idx'%(classname, ml) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
453 ] |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
454 table_name = '%s_%s'%(classname, ml) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
455 for index_name in l: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
456 if not self.sql_index_exists(table_name, index_name): |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
457 continue |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
458 index_sql = 'drop index %s'%index_name |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
459 if __debug__: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
460 print >>hyperdb.DEBUG, 'drop_index', (self, index_sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
461 self.cursor.execute(index_sql) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
462 |
| 1165 | 463 def create_class(self, spec): |
| 464 ''' Create a database table according to the given spec. | |
| 465 ''' | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
466 cols, mls = self.create_class_table(spec) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
467 self.create_journal_table(spec) |
| 1165 | 468 |
| 469 # now create the multilink tables | |
| 470 for ml in mls: | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
471 self.create_multilink_table(spec, ml) |
| 1165 | 472 |
| 473 # ID counter | |
| 474 sql = 'insert into ids (name, num) values (%s,%s)'%(self.arg, self.arg) | |
| 475 vals = (spec.classname, 1) | |
| 476 if __debug__: | |
| 477 print >>hyperdb.DEBUG, 'create_class', (self, sql, vals) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
478 self.cursor.execute(sql, vals) |
| 1165 | 479 |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
480 def drop_class(self, cn, spec): |
| 1165 | 481 ''' Drop the given table from the database. |
| 482 | |
| 483 Drop the journal and multilink tables too. | |
| 484 ''' | |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
485 properties = spec[1] |
| 1165 | 486 # figure the multilinks |
| 487 mls = [] | |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
488 for propanme, prop in properties: |
| 1165 | 489 if isinstance(prop, Multilink): |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
490 mls.append(propname) |
| 1165 | 491 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
492 # drop class table and indexes |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
493 self.drop_class_table_indexes(cn, spec[0]) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
494 sql = 'drop table _%s'%cn |
| 1165 | 495 if __debug__: |
| 496 print >>hyperdb.DEBUG, 'drop_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
497 self.cursor.execute(sql) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
498 |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
499 # drop journal table and indexes |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
500 self.drop_journal_table_indexes(cn) |
|
1873
f63aa57386b0
Backend improvements.
Richard Jones <richard@users.sourceforge.net>
parents:
1840
diff
changeset
|
501 sql = 'drop table %s__journal'%cn |
| 1165 | 502 if __debug__: |
| 503 print >>hyperdb.DEBUG, 'drop_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
504 self.cursor.execute(sql) |
| 1165 | 505 |
| 506 for ml in mls: | |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
507 # drop multilink table and indexes |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
508 self.drop_multilink_table_indexes(cn, ml) |
| 1165 | 509 sql = 'drop table %s_%s'%(spec.classname, ml) |
| 510 if __debug__: | |
| 511 print >>hyperdb.DEBUG, 'drop_class', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
512 self.cursor.execute(sql) |
| 1165 | 513 |
| 514 # | |
| 515 # Classes | |
| 516 # | |
| 517 def __getattr__(self, classname): | |
| 518 ''' A convenient way of calling self.getclass(classname). | |
| 519 ''' | |
| 520 if self.classes.has_key(classname): | |
| 521 if __debug__: | |
| 522 print >>hyperdb.DEBUG, '__getattr__', (self, classname) | |
| 523 return self.classes[classname] | |
| 524 raise AttributeError, classname | |
| 525 | |
| 526 def addclass(self, cl): | |
| 527 ''' Add a Class to the hyperdatabase. | |
| 528 ''' | |
| 529 if __debug__: | |
| 530 print >>hyperdb.DEBUG, 'addclass', (self, cl) | |
| 531 cn = cl.classname | |
| 532 if self.classes.has_key(cn): | |
| 533 raise ValueError, cn | |
| 534 self.classes[cn] = cl | |
| 535 | |
|
2076
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
536 # add default Edit and View permissions |
|
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
537 self.security.addPermission(name="Edit", klass=cn, |
|
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
538 description="User is allowed to edit "+cn) |
|
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
539 self.security.addPermission(name="View", klass=cn, |
|
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
540 description="User is allowed to access "+cn) |
|
2a4309450202
security fixes and doc updates
Richard Jones <richard@users.sourceforge.net>
parents:
2075
diff
changeset
|
541 |
| 1165 | 542 def getclasses(self): |
| 543 ''' Return a list of the names of all existing classes. | |
| 544 ''' | |
| 545 if __debug__: | |
| 546 print >>hyperdb.DEBUG, 'getclasses', (self,) | |
| 547 l = self.classes.keys() | |
| 548 l.sort() | |
| 549 return l | |
| 550 | |
| 551 def getclass(self, classname): | |
| 552 '''Get the Class object representing a particular class. | |
| 553 | |
| 554 If 'classname' is not a valid class name, a KeyError is raised. | |
| 555 ''' | |
| 556 if __debug__: | |
| 557 print >>hyperdb.DEBUG, 'getclass', (self, classname) | |
| 558 try: | |
| 559 return self.classes[classname] | |
| 560 except KeyError: | |
| 561 raise KeyError, 'There is no class called "%s"'%classname | |
| 562 | |
| 563 def clear(self): | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
564 '''Delete all database contents. |
| 1165 | 565 |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
566 Note: I don't commit here, which is different behaviour to the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
567 "nuke from orbit" behaviour in the dbs. |
| 1165 | 568 ''' |
| 569 if __debug__: | |
| 570 print >>hyperdb.DEBUG, 'clear', (self,) | |
| 571 for cn in self.classes.keys(): | |
| 572 sql = 'delete from _%s'%cn | |
| 573 if __debug__: | |
| 574 print >>hyperdb.DEBUG, 'clear', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
575 self.cursor.execute(sql) |
| 1165 | 576 |
| 577 # | |
| 578 # Node IDs | |
| 579 # | |
| 580 def newid(self, classname): | |
| 581 ''' Generate a new id for the given class | |
| 582 ''' | |
| 583 # get the next ID | |
| 584 sql = 'select num from ids where name=%s'%self.arg | |
| 585 if __debug__: | |
| 586 print >>hyperdb.DEBUG, 'newid', (self, sql, classname) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
587 self.cursor.execute(sql, (classname, )) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
588 newid = self.cursor.fetchone()[0] |
| 1165 | 589 |
| 590 # update the counter | |
| 591 sql = 'update ids set num=%s where name=%s'%(self.arg, self.arg) | |
| 592 vals = (int(newid)+1, classname) | |
| 593 if __debug__: | |
| 594 print >>hyperdb.DEBUG, 'newid', (self, sql, vals) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
595 self.cursor.execute(sql, vals) |
| 1165 | 596 |
| 597 # return as string | |
| 598 return str(newid) | |
| 599 | |
| 600 def setid(self, classname, setid): | |
| 601 ''' Set the id counter: used during import of database | |
| 602 ''' | |
| 603 sql = 'update ids set num=%s where name=%s'%(self.arg, self.arg) | |
|
1171
8784a11f8c2f
fix to setid
Richard Jones <richard@users.sourceforge.net>
parents:
1170
diff
changeset
|
604 vals = (setid, classname) |
| 1165 | 605 if __debug__: |
| 606 print >>hyperdb.DEBUG, 'setid', (self, sql, vals) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
607 self.cursor.execute(sql, vals) |
| 1165 | 608 |
| 609 # | |
| 610 # Nodes | |
| 611 # | |
| 612 def addnode(self, classname, nodeid, node): | |
| 613 ''' Add the specified node to its class's db. | |
| 614 ''' | |
| 615 if __debug__: | |
| 616 print >>hyperdb.DEBUG, 'addnode', (self, classname, nodeid, node) | |
|
1528
96cd422532ef
bye bye gadfly - you served your purpose well [SF#701127]
Richard Jones <richard@users.sourceforge.net>
parents:
1523
diff
changeset
|
617 |
|
96cd422532ef
bye bye gadfly - you served your purpose well [SF#701127]
Richard Jones <richard@users.sourceforge.net>
parents:
1523
diff
changeset
|
618 # determine the column definitions and multilink tables |
| 1165 | 619 cl = self.classes[classname] |
| 620 cols, mls = self.determine_columns(cl.properties.items()) | |
| 621 | |
|
1189
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
622 # we'll be supplied these props if we're doing an import |
|
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
623 if not node.has_key('creator'): |
|
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
624 # add in the "calculated" properties (dupe so we don't affect |
|
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
625 # calling code's node assumptions) |
|
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
626 node = node.copy() |
|
23b8d1e87fe3
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1187
diff
changeset
|
627 node['creation'] = node['activity'] = date.Date() |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
628 node['actor'] = node['creator'] = self.getuid() |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
629 |
| 1165 | 630 # default the non-multilink columns |
| 631 for col, prop in cl.properties.items(): | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
632 if not node.has_key(col): |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
633 if isinstance(prop, Multilink): |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
634 node[col] = [] |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
635 else: |
| 1165 | 636 node[col] = None |
| 637 | |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
638 # clear this node out of the cache if it's in there |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
639 key = (classname, nodeid) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
640 if self.cache.has_key(key): |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
641 del self.cache[key] |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
642 self.cache_lru.remove(key) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
643 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
644 # make the node data safe for the DB |
| 1165 | 645 node = self.serialise(classname, node) |
| 646 | |
| 647 # make sure the ordering is correct for column name -> column value | |
| 648 vals = tuple([node[col[1:]] for col in cols]) + (nodeid, 0) | |
| 649 s = ','.join([self.arg for x in cols]) + ',%s,%s'%(self.arg, self.arg) | |
| 650 cols = ','.join(cols) + ',id,__retired__' | |
| 651 | |
| 652 # perform the inserts | |
| 653 sql = 'insert into _%s (%s) values (%s)'%(classname, cols, s) | |
| 654 if __debug__: | |
| 655 print >>hyperdb.DEBUG, 'addnode', (self, sql, vals) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
656 self.cursor.execute(sql, vals) |
| 1165 | 657 |
| 658 # insert the multilink rows | |
| 659 for col in mls: | |
| 660 t = '%s_%s'%(classname, col) | |
| 661 for entry in node[col]: | |
| 662 sql = 'insert into %s (linkid, nodeid) values (%s,%s)'%(t, | |
| 663 self.arg, self.arg) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
664 self.sql(sql, (entry, nodeid)) |
| 1165 | 665 |
| 666 # make sure we do the commit-time extra stuff for this node | |
| 667 self.transactions.append((self.doSaveNode, (classname, nodeid, node))) | |
| 668 | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
669 def setnode(self, classname, nodeid, values, multilink_changes): |
| 1165 | 670 ''' Change the specified node. |
| 671 ''' | |
| 672 if __debug__: | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
673 print >>hyperdb.DEBUG, 'setnode', (self, classname, nodeid, values) |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
674 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
675 # clear this node out of the cache if it's in there |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
676 key = (classname, nodeid) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
677 if self.cache.has_key(key): |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
678 del self.cache[key] |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
679 self.cache_lru.remove(key) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
680 |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
681 # add the special props |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
682 values = values.copy() |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
683 values['activity'] = date.Date() |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
684 values['actor'] = self.getuid() |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
685 |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
686 # make db-friendly |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
687 values = self.serialise(classname, values) |
| 1165 | 688 |
| 689 cl = self.classes[classname] | |
| 690 cols = [] | |
| 691 mls = [] | |
| 692 # add the multilinks separately | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
693 props = cl.getprops() |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
694 for col in values.keys(): |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
695 prop = props[col] |
| 1165 | 696 if isinstance(prop, Multilink): |
| 697 mls.append(col) | |
| 698 else: | |
| 699 cols.append('_'+col) | |
| 700 cols.sort() | |
| 701 | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
702 # if there's any updates to regular columns, do them |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
703 if cols: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
704 # make sure the ordering is correct for column name -> column value |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
705 sqlvals = tuple([values[col[1:]] for col in cols]) + (nodeid,) |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
706 s = ','.join(['%s=%s'%(x, self.arg) for x in cols]) |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
707 cols = ','.join(cols) |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
708 |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
709 # perform the update |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
710 sql = 'update _%s set %s where id=%s'%(classname, s, self.arg) |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
711 if __debug__: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
712 print >>hyperdb.DEBUG, 'setnode', (self, sql, sqlvals) |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
713 self.cursor.execute(sql, sqlvals) |
| 1165 | 714 |
| 715 # now the fun bit, updating the multilinks ;) | |
| 716 for col, (add, remove) in multilink_changes.items(): | |
| 717 tn = '%s_%s'%(classname, col) | |
| 718 if add: | |
| 719 sql = 'insert into %s (nodeid, linkid) values (%s,%s)'%(tn, | |
| 720 self.arg, self.arg) | |
| 721 for addid in add: | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
722 self.sql(sql, (nodeid, addid)) |
| 1165 | 723 if remove: |
| 724 sql = 'delete from %s where nodeid=%s and linkid=%s'%(tn, | |
| 725 self.arg, self.arg) | |
| 726 for removeid in remove: | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
727 self.sql(sql, (nodeid, removeid)) |
| 1165 | 728 |
| 729 # make sure we do the commit-time extra stuff for this node | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
730 self.transactions.append((self.doSaveNode, (classname, nodeid, values))) |
| 1165 | 731 |
| 732 def getnode(self, classname, nodeid): | |
| 733 ''' Get a node from the database. | |
| 734 ''' | |
| 735 if __debug__: | |
| 736 print >>hyperdb.DEBUG, 'getnode', (self, classname, nodeid) | |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
737 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
738 # see if we have this node cached |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
739 key = (classname, nodeid) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
740 if self.cache.has_key(key): |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
741 # push us back to the top of the LRU |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
742 self.cache_lru.remove(key) |
|
1185
3b0735ef8207
fix to LRU cache
Richard Jones <richard@users.sourceforge.net>
parents:
1183
diff
changeset
|
743 self.cache_lru.insert(0, key) |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
744 # return the cached information |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
745 return self.cache[key] |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
746 |
| 1165 | 747 # figure the columns we're fetching |
| 748 cl = self.classes[classname] | |
| 749 cols, mls = self.determine_columns(cl.properties.items()) | |
| 750 scols = ','.join(cols) | |
| 751 | |
| 752 # perform the basic property fetch | |
| 753 sql = 'select %s from _%s where id=%s'%(scols, classname, self.arg) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
754 self.sql(sql, (nodeid,)) |
| 1165 | 755 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
756 values = self.sql_fetchone() |
| 1165 | 757 if values is None: |
| 758 raise IndexError, 'no such %s node %s'%(classname, nodeid) | |
| 759 | |
| 760 # make up the node | |
| 761 node = {} | |
| 762 for col in range(len(cols)): | |
| 763 node[cols[col][1:]] = values[col] | |
| 764 | |
| 765 # now the multilinks | |
| 766 for col in mls: | |
| 767 # get the link ids | |
| 768 sql = 'select linkid from %s_%s where nodeid=%s'%(classname, col, | |
| 769 self.arg) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
770 self.cursor.execute(sql, (nodeid,)) |
| 1165 | 771 # extract the first column from the result |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
772 node[col] = [x[0] for x in self.cursor.fetchall()] |
| 1165 | 773 |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
774 # un-dbificate the node data |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
775 node = self.unserialise(classname, node) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
776 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
777 # save off in the cache |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
778 key = (classname, nodeid) |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
779 self.cache[key] = node |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
780 # update the LRU |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
781 self.cache_lru.insert(0, key) |
|
1185
3b0735ef8207
fix to LRU cache
Richard Jones <richard@users.sourceforge.net>
parents:
1183
diff
changeset
|
782 if len(self.cache_lru) > ROW_CACHE_SIZE: |
|
3b0735ef8207
fix to LRU cache
Richard Jones <richard@users.sourceforge.net>
parents:
1183
diff
changeset
|
783 del self.cache[self.cache_lru.pop()] |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
784 |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
785 return node |
| 1165 | 786 |
| 787 def destroynode(self, classname, nodeid): | |
| 788 '''Remove a node from the database. Called exclusively by the | |
| 789 destroy() method on Class. | |
| 790 ''' | |
| 791 if __debug__: | |
| 792 print >>hyperdb.DEBUG, 'destroynode', (self, classname, nodeid) | |
| 793 | |
| 794 # make sure the node exists | |
| 795 if not self.hasnode(classname, nodeid): | |
| 796 raise IndexError, '%s has no node %s'%(classname, nodeid) | |
| 797 | |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
798 # see if we have this node cached |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
799 if self.cache.has_key((classname, nodeid)): |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
800 del self.cache[(classname, nodeid)] |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
801 |
| 1165 | 802 # see if there's any obvious commit actions that we should get rid of |
| 803 for entry in self.transactions[:]: | |
| 804 if entry[1][:2] == (classname, nodeid): | |
| 805 self.transactions.remove(entry) | |
| 806 | |
| 807 # now do the SQL | |
| 808 sql = 'delete from _%s where id=%s'%(classname, self.arg) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
809 self.sql(sql, (nodeid,)) |
| 1165 | 810 |
| 811 # remove from multilnks | |
| 812 cl = self.getclass(classname) | |
| 813 x, mls = self.determine_columns(cl.properties.items()) | |
| 814 for col in mls: | |
| 815 # get the link ids | |
| 816 sql = 'delete from %s_%s where nodeid=%s'%(classname, col, self.arg) | |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
817 self.sql(sql, (nodeid,)) |
| 1165 | 818 |
| 819 # remove journal entries | |
| 820 sql = 'delete from %s__journal where nodeid=%s'%(classname, self.arg) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
821 self.sql(sql, (nodeid,)) |
| 1165 | 822 |
| 823 def serialise(self, classname, node): | |
| 824 '''Copy the node contents, converting non-marshallable data into | |
| 825 marshallable data. | |
| 826 ''' | |
| 827 if __debug__: | |
| 828 print >>hyperdb.DEBUG, 'serialise', classname, node | |
| 829 properties = self.getclass(classname).getprops() | |
| 830 d = {} | |
| 831 for k, v in node.items(): | |
| 832 # if the property doesn't exist, or is the "retired" flag then | |
| 833 # it won't be in the properties dict | |
| 834 if not properties.has_key(k): | |
| 835 d[k] = v | |
| 836 continue | |
| 837 | |
| 838 # get the property spec | |
| 839 prop = properties[k] | |
| 840 | |
|
1252
209a47ede743
allow blank passwords again [SF#619714]
Richard Jones <richard@users.sourceforge.net>
parents:
1249
diff
changeset
|
841 if isinstance(prop, Password) and v is not None: |
| 1165 | 842 d[k] = str(v) |
| 843 elif isinstance(prop, Date) and v is not None: | |
| 844 d[k] = v.serialise() | |
| 845 elif isinstance(prop, Interval) and v is not None: | |
| 846 d[k] = v.serialise() | |
| 847 else: | |
| 848 d[k] = v | |
| 849 return d | |
| 850 | |
| 851 def unserialise(self, classname, node): | |
| 852 '''Decode the marshalled node data | |
| 853 ''' | |
| 854 if __debug__: | |
| 855 print >>hyperdb.DEBUG, 'unserialise', classname, node | |
| 856 properties = self.getclass(classname).getprops() | |
| 857 d = {} | |
| 858 for k, v in node.items(): | |
| 859 # if the property doesn't exist, or is the "retired" flag then | |
| 860 # it won't be in the properties dict | |
| 861 if not properties.has_key(k): | |
| 862 d[k] = v | |
| 863 continue | |
| 864 | |
| 865 # get the property spec | |
| 866 prop = properties[k] | |
| 867 | |
| 868 if isinstance(prop, Date) and v is not None: | |
| 869 d[k] = date.Date(v) | |
| 870 elif isinstance(prop, Interval) and v is not None: | |
| 871 d[k] = date.Interval(v) | |
|
1252
209a47ede743
allow blank passwords again [SF#619714]
Richard Jones <richard@users.sourceforge.net>
parents:
1249
diff
changeset
|
872 elif isinstance(prop, Password) and v is not None: |
| 1165 | 873 p = password.Password() |
| 874 p.unpack(v) | |
| 875 d[k] = p | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
876 elif isinstance(prop, Boolean) and v is not None: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
877 d[k] = int(v) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
878 elif isinstance(prop, Number) and v is not None: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
879 # try int first, then assume it's a float |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
880 try: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
881 d[k] = int(v) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
882 except ValueError: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
883 d[k] = float(v) |
| 1165 | 884 else: |
| 885 d[k] = v | |
| 886 return d | |
| 887 | |
| 888 def hasnode(self, classname, nodeid): | |
| 889 ''' Determine if the database has a given node. | |
| 890 ''' | |
| 891 sql = 'select count(*) from _%s where id=%s'%(classname, self.arg) | |
| 892 if __debug__: | |
| 893 print >>hyperdb.DEBUG, 'hasnode', (self, sql, nodeid) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
894 self.cursor.execute(sql, (nodeid,)) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
895 return int(self.cursor.fetchone()[0]) |
| 1165 | 896 |
| 897 def countnodes(self, classname): | |
| 898 ''' Count the number of nodes that exist for a particular Class. | |
| 899 ''' | |
| 900 sql = 'select count(*) from _%s'%classname | |
| 901 if __debug__: | |
| 902 print >>hyperdb.DEBUG, 'countnodes', (self, sql) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
903 self.cursor.execute(sql) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
904 return self.cursor.fetchone()[0] |
| 1165 | 905 |
| 906 def addjournal(self, classname, nodeid, action, params, creator=None, | |
| 907 creation=None): | |
| 908 ''' Journal the Action | |
| 909 'action' may be: | |
| 910 | |
| 911 'create' or 'set' -- 'params' is a dictionary of property values | |
| 912 'link' or 'unlink' -- 'params' is (classname, nodeid, propname) | |
| 913 'retire' -- 'params' is None | |
| 914 ''' | |
| 915 # serialise the parameters now if necessary | |
| 916 if isinstance(params, type({})): | |
| 917 if action in ('set', 'create'): | |
| 918 params = self.serialise(classname, params) | |
| 919 | |
| 920 # handle supply of the special journalling parameters (usually | |
| 921 # supplied on importing an existing database) | |
| 922 if creator: | |
| 923 journaltag = creator | |
| 924 else: | |
|
1800
a3b1b1dcf639
Use getuid(), not figure_curuserid()
Johannes Gijsbers <jlgijsbers@users.sourceforge.net>
parents:
1794
diff
changeset
|
925 journaltag = self.getuid() |
| 1165 | 926 if creation: |
| 927 journaldate = creation.serialise() | |
| 928 else: | |
| 929 journaldate = date.Date().serialise() | |
| 930 | |
| 931 # create the journal entry | |
| 932 cols = ','.join('nodeid date tag action params'.split()) | |
| 933 | |
| 934 if __debug__: | |
| 935 print >>hyperdb.DEBUG, 'addjournal', (nodeid, journaldate, | |
| 936 journaltag, action, params) | |
| 937 | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
938 self.save_journal(classname, cols, nodeid, journaldate, |
| 1165 | 939 journaltag, action, params) |
| 940 | |
| 941 def getjournal(self, classname, nodeid): | |
| 942 ''' get the journal for id | |
| 943 ''' | |
| 944 # make sure the node exists | |
| 945 if not self.hasnode(classname, nodeid): | |
| 946 raise IndexError, '%s has no node %s'%(classname, nodeid) | |
| 947 | |
| 948 cols = ','.join('nodeid date tag action params'.split()) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
949 return self.load_journal(classname, cols, nodeid) |
| 1165 | 950 |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
951 def save_journal(self, classname, cols, nodeid, journaldate, |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
952 journaltag, action, params): |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
953 ''' Save the journal entry to the database |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
954 ''' |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
955 # make the params db-friendly |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
956 params = repr(params) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
957 entry = (nodeid, journaldate, journaltag, action, params) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
958 |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
959 # do the insert |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
960 a = self.arg |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
961 sql = 'insert into %s__journal (%s) values (%s,%s,%s,%s,%s)'%(classname, |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
962 cols, a, a, a, a, a) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
963 if __debug__: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
964 print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
965 self.cursor.execute(sql, entry) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
966 |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
967 def load_journal(self, classname, cols, nodeid): |
| 1165 | 968 ''' Load the journal from the database |
| 969 ''' | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
970 # now get the journal entries |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
971 sql = 'select %s from %s__journal where nodeid=%s'%(cols, classname, |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
972 self.arg) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
973 if __debug__: |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
974 print >>hyperdb.DEBUG, 'load_journal', (self, sql, nodeid) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
975 self.cursor.execute(sql, (nodeid,)) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
976 res = [] |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
977 for nodeid, date_stamp, user, action, params in self.cursor.fetchall(): |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
978 params = eval(params) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
979 res.append((nodeid, date.Date(date_stamp), user, action, params)) |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
980 return res |
| 1165 | 981 |
| 982 def pack(self, pack_before): | |
| 983 ''' Delete all journal entries except "create" before 'pack_before'. | |
| 984 ''' | |
| 985 # get a 'yyyymmddhhmmss' version of the date | |
| 986 date_stamp = pack_before.serialise() | |
| 987 | |
| 988 # do the delete | |
| 989 for classname in self.classes.keys(): | |
| 990 sql = "delete from %s__journal where date<%s and "\ | |
| 991 "action<>'create'"%(classname, self.arg) | |
| 992 if __debug__: | |
| 993 print >>hyperdb.DEBUG, 'pack', (self, sql, date_stamp) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
994 self.cursor.execute(sql, (date_stamp,)) |
| 1165 | 995 |
| 996 def sql_commit(self): | |
| 997 ''' Actually commit to the database. | |
| 998 ''' | |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
999 if __debug__: |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
1000 print >>hyperdb.DEBUG, '+++ commit database connection +++' |
| 1165 | 1001 self.conn.commit() |
| 1002 | |
| 1003 def commit(self): | |
| 1004 ''' Commit the current transactions. | |
| 1005 | |
| 1006 Save all data changed since the database was opened or since the | |
| 1007 last commit() or rollback(). | |
| 1008 ''' | |
| 1009 if __debug__: | |
| 1010 print >>hyperdb.DEBUG, 'commit', (self,) | |
| 1011 | |
| 1012 # commit the database | |
| 1013 self.sql_commit() | |
| 1014 | |
| 1015 # now, do all the other transaction stuff | |
| 1016 reindex = {} | |
| 1017 for method, args in self.transactions: | |
| 1018 reindex[method(*args)] = 1 | |
| 1019 | |
| 1020 # reindex the nodes that request it | |
| 1021 for classname, nodeid in filter(None, reindex.keys()): | |
| 1022 print >>hyperdb.DEBUG, 'commit.reindex', (classname, nodeid) | |
| 1023 self.getclass(classname).index(nodeid) | |
| 1024 | |
| 1025 # save the indexer state | |
| 1026 self.indexer.save_index() | |
| 1027 | |
| 1028 # clear out the transactions | |
| 1029 self.transactions = [] | |
| 1030 | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1031 def sql_rollback(self): |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1032 self.conn.rollback() |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1033 |
| 1165 | 1034 def rollback(self): |
| 1035 ''' Reverse all actions from the current transaction. | |
| 1036 | |
| 1037 Undo all the changes made since the database was opened or the last | |
| 1038 commit() or rollback() was performed. | |
| 1039 ''' | |
| 1040 if __debug__: | |
| 1041 print >>hyperdb.DEBUG, 'rollback', (self,) | |
| 1042 | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1043 self.sql_rollback() |
| 1165 | 1044 |
| 1045 # roll back "other" transaction stuff | |
| 1046 for method, args in self.transactions: | |
| 1047 # delete temporary files | |
| 1048 if method == self.doStoreFile: | |
| 1049 self.rollbackStoreFile(*args) | |
| 1050 self.transactions = [] | |
| 1051 | |
|
1492
2fc7d4a8c9e7
fixed sqlite rollback/caching bug [SF#689383]
Richard Jones <richard@users.sourceforge.net>
parents:
1484
diff
changeset
|
1052 # clear the cache |
|
2fc7d4a8c9e7
fixed sqlite rollback/caching bug [SF#689383]
Richard Jones <richard@users.sourceforge.net>
parents:
1484
diff
changeset
|
1053 self.clearCache() |
|
2fc7d4a8c9e7
fixed sqlite rollback/caching bug [SF#689383]
Richard Jones <richard@users.sourceforge.net>
parents:
1484
diff
changeset
|
1054 |
| 1165 | 1055 def doSaveNode(self, classname, nodeid, node): |
| 1056 ''' dummy that just generates a reindex event | |
| 1057 ''' | |
| 1058 # return the classname, nodeid so we reindex this content | |
| 1059 return (classname, nodeid) | |
| 1060 | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1061 def sql_close(self): |
|
2075
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
1062 if __debug__: |
|
b1704ba7be41
make mysql / postgresql work again. beginnings of otk/session store in rdbmses
Richard Jones <richard@users.sourceforge.net>
parents:
2073
diff
changeset
|
1063 print >>hyperdb.DEBUG, '+++ close database connection +++' |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1064 self.conn.close() |
|
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1065 |
| 1165 | 1066 def close(self): |
| 1067 ''' Close off the connection. | |
| 1068 ''' | |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1069 self.sql_close() |
|
1333
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
1070 if self.lockfile is not None: |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
1071 locking.release_lock(self.lockfile) |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
1072 if self.lockfile is not None: |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
1073 self.lockfile.close() |
|
80d27b7d6db5
implemented whole-database locking
Richard Jones <richard@users.sourceforge.net>
parents:
1304
diff
changeset
|
1074 self.lockfile = None |
| 1165 | 1075 |
| 1076 # | |
| 1077 # The base Class class | |
| 1078 # | |
| 1079 class Class(hyperdb.Class): | |
| 1080 ''' The handle to a particular class of nodes in a hyperdatabase. | |
| 1081 | |
| 1082 All methods except __repr__ and getnode must be implemented by a | |
| 1083 concrete backend Class. | |
| 1084 ''' | |
| 1085 | |
| 1086 def __init__(self, db, classname, **properties): | |
| 1087 '''Create a new class with a given name and property specification. | |
| 1088 | |
| 1089 'classname' must not collide with the name of an existing class, | |
| 1090 or a ValueError is raised. The keyword arguments in 'properties' | |
| 1091 must map names to property objects, or a TypeError is raised. | |
| 1092 ''' | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1093 for name in 'creation activity creator actor'.split(): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1094 if properties.has_key(name): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1095 raise ValueError, '"creation", "activity", "creator" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1096 '"actor" are reserved' |
| 1165 | 1097 |
| 1098 self.classname = classname | |
| 1099 self.properties = properties | |
| 1100 self.db = weakref.proxy(db) # use a weak ref to avoid circularity | |
| 1101 self.key = '' | |
| 1102 | |
| 1103 # should we journal changes (default yes) | |
| 1104 self.do_journal = 1 | |
| 1105 | |
| 1106 # do the db-related init stuff | |
| 1107 db.addclass(self) | |
| 1108 | |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1109 self.auditors = {'create': [], 'set': [], 'retire': [], 'restore': []} |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1110 self.reactors = {'create': [], 'set': [], 'retire': [], 'restore': []} |
| 1165 | 1111 |
| 1112 def schema(self): | |
| 1113 ''' A dumpable version of the schema that we can store in the | |
| 1114 database | |
| 1115 ''' | |
| 1116 return (self.key, [(x, repr(y)) for x,y in self.properties.items()]) | |
| 1117 | |
| 1118 def enableJournalling(self): | |
| 1119 '''Turn journalling on for this class | |
| 1120 ''' | |
| 1121 self.do_journal = 1 | |
| 1122 | |
| 1123 def disableJournalling(self): | |
| 1124 '''Turn journalling off for this class | |
| 1125 ''' | |
| 1126 self.do_journal = 0 | |
| 1127 | |
| 1128 # Editing nodes: | |
| 1129 def create(self, **propvalues): | |
| 1130 ''' Create a new node of this class and return its id. | |
| 1131 | |
| 1132 The keyword arguments in 'propvalues' map property names to values. | |
| 1133 | |
| 1134 The values of arguments must be acceptable for the types of their | |
| 1135 corresponding properties or a TypeError is raised. | |
| 1136 | |
| 1137 If this class has a key property, it must be present and its value | |
| 1138 must not collide with other key strings or a ValueError is raised. | |
| 1139 | |
| 1140 Any other properties on this class that are missing from the | |
| 1141 'propvalues' dictionary are set to None. | |
| 1142 | |
| 1143 If an id in a link or multilink property does not refer to a valid | |
| 1144 node, an IndexError is raised. | |
| 1145 ''' | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1146 self.fireAuditors('create', None, propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1147 newid = self.create_inner(**propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1148 self.fireReactors('create', newid, None) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1149 return newid |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1150 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1151 def create_inner(self, **propvalues): |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1152 ''' Called by create, in-between the audit and react calls. |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1153 ''' |
| 1165 | 1154 if propvalues.has_key('id'): |
| 1155 raise KeyError, '"id" is reserved' | |
| 1156 | |
| 1157 if self.db.journaltag is None: | |
| 1158 raise DatabaseError, 'Database open read-only' | |
| 1159 | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1160 if propvalues.has_key('creator') or propvalues.has_key('actor') or \ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1161 propvalues.has_key('creation') or propvalues.has_key('activity'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1162 raise KeyError, '"creator", "actor", "creation" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1163 '"activity" are reserved' |
| 1165 | 1164 |
| 1165 # new node's id | |
| 1166 newid = self.db.newid(self.classname) | |
| 1167 | |
| 1168 # validate propvalues | |
| 1169 num_re = re.compile('^\d+$') | |
| 1170 for key, value in propvalues.items(): | |
| 1171 if key == self.key: | |
| 1172 try: | |
| 1173 self.lookup(value) | |
| 1174 except KeyError: | |
| 1175 pass | |
| 1176 else: | |
| 1177 raise ValueError, 'node with key "%s" exists'%value | |
| 1178 | |
| 1179 # try to handle this property | |
| 1180 try: | |
| 1181 prop = self.properties[key] | |
| 1182 except KeyError: | |
| 1183 raise KeyError, '"%s" has no property "%s"'%(self.classname, | |
| 1184 key) | |
| 1185 | |
| 1186 if value is not None and isinstance(prop, Link): | |
| 1187 if type(value) != type(''): | |
| 1188 raise ValueError, 'link value must be String' | |
| 1189 link_class = self.properties[key].classname | |
| 1190 # if it isn't a number, it's a key | |
| 1191 if not num_re.match(value): | |
| 1192 try: | |
| 1193 value = self.db.classes[link_class].lookup(value) | |
| 1194 except (TypeError, KeyError): | |
| 1195 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1196 key, value, link_class) | |
| 1197 elif not self.db.getclass(link_class).hasnode(value): | |
| 1198 raise IndexError, '%s has no node %s'%(link_class, value) | |
| 1199 | |
| 1200 # save off the value | |
| 1201 propvalues[key] = value | |
| 1202 | |
| 1203 # register the link with the newly linked node | |
| 1204 if self.do_journal and self.properties[key].do_journal: | |
| 1205 self.db.addjournal(link_class, value, 'link', | |
| 1206 (self.classname, newid, key)) | |
| 1207 | |
| 1208 elif isinstance(prop, Multilink): | |
| 1209 if type(value) != type([]): | |
| 1210 raise TypeError, 'new property "%s" not a list of ids'%key | |
| 1211 | |
| 1212 # clean up and validate the list of links | |
| 1213 link_class = self.properties[key].classname | |
| 1214 l = [] | |
| 1215 for entry in value: | |
| 1216 if type(entry) != type(''): | |
| 1217 raise ValueError, '"%s" multilink value (%r) '\ | |
| 1218 'must contain Strings'%(key, value) | |
| 1219 # if it isn't a number, it's a key | |
| 1220 if not num_re.match(entry): | |
| 1221 try: | |
| 1222 entry = self.db.classes[link_class].lookup(entry) | |
| 1223 except (TypeError, KeyError): | |
| 1224 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1225 key, entry, self.properties[key].classname) | |
| 1226 l.append(entry) | |
| 1227 value = l | |
| 1228 propvalues[key] = value | |
| 1229 | |
| 1230 # handle additions | |
| 1231 for nodeid in value: | |
| 1232 if not self.db.getclass(link_class).hasnode(nodeid): | |
| 1233 raise IndexError, '%s has no node %s'%(link_class, | |
| 1234 nodeid) | |
| 1235 # register the link with the newly linked node | |
| 1236 if self.do_journal and self.properties[key].do_journal: | |
| 1237 self.db.addjournal(link_class, nodeid, 'link', | |
| 1238 (self.classname, newid, key)) | |
| 1239 | |
| 1240 elif isinstance(prop, String): | |
|
1383
f19dde90e473
applied unicode patch
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1365
diff
changeset
|
1241 if type(value) != type('') and type(value) != type(u''): |
| 1165 | 1242 raise TypeError, 'new property "%s" not a string'%key |
| 1243 | |
| 1244 elif isinstance(prop, Password): | |
| 1245 if not isinstance(value, password.Password): | |
| 1246 raise TypeError, 'new property "%s" not a Password'%key | |
| 1247 | |
| 1248 elif isinstance(prop, Date): | |
| 1249 if value is not None and not isinstance(value, date.Date): | |
| 1250 raise TypeError, 'new property "%s" not a Date'%key | |
| 1251 | |
| 1252 elif isinstance(prop, Interval): | |
| 1253 if value is not None and not isinstance(value, date.Interval): | |
| 1254 raise TypeError, 'new property "%s" not an Interval'%key | |
| 1255 | |
| 1256 elif value is not None and isinstance(prop, Number): | |
| 1257 try: | |
| 1258 float(value) | |
| 1259 except ValueError: | |
| 1260 raise TypeError, 'new property "%s" not numeric'%key | |
| 1261 | |
| 1262 elif value is not None and isinstance(prop, Boolean): | |
| 1263 try: | |
| 1264 int(value) | |
| 1265 except ValueError: | |
| 1266 raise TypeError, 'new property "%s" not boolean'%key | |
| 1267 | |
| 1268 # make sure there's data where there needs to be | |
| 1269 for key, prop in self.properties.items(): | |
| 1270 if propvalues.has_key(key): | |
| 1271 continue | |
| 1272 if key == self.key: | |
| 1273 raise ValueError, 'key property "%s" is required'%key | |
| 1274 if isinstance(prop, Multilink): | |
| 1275 propvalues[key] = [] | |
| 1276 else: | |
| 1277 propvalues[key] = None | |
| 1278 | |
| 1279 # done | |
| 1280 self.db.addnode(self.classname, newid, propvalues) | |
| 1281 if self.do_journal: | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1282 self.db.addjournal(self.classname, newid, 'create', {}) |
| 1165 | 1283 |
| 1284 return newid | |
| 1285 | |
| 1286 def export_list(self, propnames, nodeid): | |
| 1287 ''' Export a node - generate a list of CSV-able data in the order | |
| 1288 specified by propnames for the given node. | |
| 1289 ''' | |
| 1290 properties = self.getprops() | |
| 1291 l = [] | |
| 1292 for prop in propnames: | |
| 1293 proptype = properties[prop] | |
| 1294 value = self.get(nodeid, prop) | |
| 1295 # "marshal" data where needed | |
| 1296 if value is None: | |
| 1297 pass | |
| 1298 elif isinstance(proptype, hyperdb.Date): | |
| 1299 value = value.get_tuple() | |
| 1300 elif isinstance(proptype, hyperdb.Interval): | |
| 1301 value = value.get_tuple() | |
| 1302 elif isinstance(proptype, hyperdb.Password): | |
| 1303 value = str(value) | |
| 1304 l.append(repr(value)) | |
|
1920
f9316d2cd5ba
Fixed retirement of items in rdbms imports [SF#841355]
Richard Jones <richard@users.sourceforge.net>
parents:
1912
diff
changeset
|
1305 l.append(repr(self.is_retired(nodeid))) |
| 1165 | 1306 return l |
| 1307 | |
| 1308 def import_list(self, propnames, proplist): | |
| 1309 ''' Import a node - all information including "id" is present and | |
| 1310 should not be sanity checked. Triggers are not triggered. The | |
| 1311 journal should be initialised using the "creator" and "created" | |
| 1312 information. | |
| 1313 | |
| 1314 Return the nodeid of the node imported. | |
| 1315 ''' | |
| 1316 if self.db.journaltag is None: | |
| 1317 raise DatabaseError, 'Database open read-only' | |
| 1318 properties = self.getprops() | |
| 1319 | |
| 1320 # make the new node's property map | |
| 1321 d = {} | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1322 retire = 0 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1323 newid = None |
| 1165 | 1324 for i in range(len(propnames)): |
| 1325 # Use eval to reverse the repr() used to output the CSV | |
| 1326 value = eval(proplist[i]) | |
| 1327 | |
| 1328 # Figure the property for this column | |
| 1329 propname = propnames[i] | |
| 1330 | |
| 1331 # "unmarshal" where necessary | |
| 1332 if propname == 'id': | |
| 1333 newid = value | |
| 1334 continue | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1335 elif propname == 'is retired': |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1336 # is the item retired? |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1337 if int(value): |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1338 retire = 1 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1339 continue |
|
1751
ab7760caf6ff
Importing wasn't setting None values explicitly when it should have been
Richard Jones <richard@users.sourceforge.net>
parents:
1740
diff
changeset
|
1340 elif value is None: |
|
ab7760caf6ff
Importing wasn't setting None values explicitly when it should have been
Richard Jones <richard@users.sourceforge.net>
parents:
1740
diff
changeset
|
1341 d[propname] = None |
|
ab7760caf6ff
Importing wasn't setting None values explicitly when it should have been
Richard Jones <richard@users.sourceforge.net>
parents:
1740
diff
changeset
|
1342 continue |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1343 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1344 prop = properties[propname] |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1345 if value is None: |
| 1165 | 1346 # don't set Nones |
| 1347 continue | |
| 1348 elif isinstance(prop, hyperdb.Date): | |
| 1349 value = date.Date(value) | |
| 1350 elif isinstance(prop, hyperdb.Interval): | |
| 1351 value = date.Interval(value) | |
| 1352 elif isinstance(prop, hyperdb.Password): | |
| 1353 pwd = password.Password() | |
| 1354 pwd.unpack(value) | |
| 1355 value = pwd | |
| 1356 d[propname] = value | |
| 1357 | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1358 # get a new id if necessary |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1359 if newid is None: |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1360 newid = self.db.newid(self.classname) |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1361 |
|
1920
f9316d2cd5ba
Fixed retirement of items in rdbms imports [SF#841355]
Richard Jones <richard@users.sourceforge.net>
parents:
1912
diff
changeset
|
1362 # add the node and journal |
|
f9316d2cd5ba
Fixed retirement of items in rdbms imports [SF#841355]
Richard Jones <richard@users.sourceforge.net>
parents:
1912
diff
changeset
|
1363 self.db.addnode(self.classname, newid, d) |
|
f9316d2cd5ba
Fixed retirement of items in rdbms imports [SF#841355]
Richard Jones <richard@users.sourceforge.net>
parents:
1912
diff
changeset
|
1364 |
|
1476
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1365 # retire? |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1366 if retire: |
|
1476
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1367 # use the arg for __retired__ to cope with any odd database type |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1368 # conversion (hello, sqlite) |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1369 sql = 'update _%s set __retired__=%s where id=%s'%(self.classname, |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1370 self.db.arg, self.db.arg) |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1371 if __debug__: |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1372 print >>hyperdb.DEBUG, 'retire', (self, sql, newid) |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1373 self.db.cursor.execute(sql, (1, newid)) |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1374 |
| 1165 | 1375 # extract the extraneous journalling gumpf and nuke it |
| 1376 if d.has_key('creator'): | |
| 1377 creator = d['creator'] | |
| 1378 del d['creator'] | |
|
1187
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1379 else: |
|
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1380 creator = None |
| 1165 | 1381 if d.has_key('creation'): |
| 1382 creation = d['creation'] | |
| 1383 del d['creation'] | |
|
1187
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1384 else: |
|
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1385 creation = None |
| 1165 | 1386 if d.has_key('activity'): |
| 1387 del d['activity'] | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1388 if d.has_key('actor'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1389 del d['actor'] |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1390 self.db.addjournal(self.classname, newid, 'create', {}, creator, |
| 1165 | 1391 creation) |
| 1392 return newid | |
| 1393 | |
| 1394 _marker = [] | |
| 1395 def get(self, nodeid, propname, default=_marker, cache=1): | |
| 1396 '''Get the value of a property on an existing node of this class. | |
| 1397 | |
| 1398 'nodeid' must be the id of an existing node of this class or an | |
| 1399 IndexError is raised. 'propname' must be the name of a property | |
| 1400 of this class or a KeyError is raised. | |
| 1401 | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
1402 'cache' exists for backwards compatibility, and is not used. |
| 1165 | 1403 ''' |
| 1404 if propname == 'id': | |
| 1405 return nodeid | |
| 1406 | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1407 # get the node's dict |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1408 d = self.db.getnode(self.classname, nodeid) |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1409 |
| 1165 | 1410 if propname == 'creation': |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1411 if d.has_key('creation'): |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1412 return d['creation'] |
| 1165 | 1413 else: |
| 1414 return date.Date() | |
| 1415 if propname == 'activity': | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1416 if d.has_key('activity'): |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1417 return d['activity'] |
| 1165 | 1418 else: |
| 1419 return date.Date() | |
| 1420 if propname == 'creator': | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1421 if d.has_key('creator'): |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1422 return d['creator'] |
| 1165 | 1423 else: |
|
1800
a3b1b1dcf639
Use getuid(), not figure_curuserid()
Johannes Gijsbers <jlgijsbers@users.sourceforge.net>
parents:
1794
diff
changeset
|
1424 return self.db.getuid() |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1425 if propname == 'actor': |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1426 if d.has_key('actor'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1427 return d['actor'] |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1428 else: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1429 return self.db.getuid() |
| 1165 | 1430 |
| 1431 # get the property (raises KeyErorr if invalid) | |
| 1432 prop = self.properties[propname] | |
| 1433 | |
| 1434 if not d.has_key(propname): | |
| 1435 if default is self._marker: | |
| 1436 if isinstance(prop, Multilink): | |
| 1437 return [] | |
| 1438 else: | |
| 1439 return None | |
| 1440 else: | |
| 1441 return default | |
| 1442 | |
| 1443 # don't pass our list to other code | |
| 1444 if isinstance(prop, Multilink): | |
| 1445 return d[propname][:] | |
| 1446 | |
| 1447 return d[propname] | |
| 1448 | |
| 1449 def set(self, nodeid, **propvalues): | |
| 1450 '''Modify a property on an existing node of this class. | |
| 1451 | |
| 1452 'nodeid' must be the id of an existing node of this class or an | |
| 1453 IndexError is raised. | |
| 1454 | |
| 1455 Each key in 'propvalues' must be the name of a property of this | |
| 1456 class or a KeyError is raised. | |
| 1457 | |
| 1458 All values in 'propvalues' must be acceptable types for their | |
| 1459 corresponding properties or a TypeError is raised. | |
| 1460 | |
| 1461 If the value of the key property is set, it must not collide with | |
| 1462 other key strings or a ValueError is raised. | |
| 1463 | |
| 1464 If the value of a Link or Multilink property contains an invalid | |
| 1465 node id, a ValueError is raised. | |
| 1466 ''' | |
| 1467 if not propvalues: | |
| 1468 return propvalues | |
| 1469 | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1470 if propvalues.has_key('creation') or propvalues.has_key('creator') or \ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1471 propvalues.has_key('actor') or propvalues.has_key('activity'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1472 raise KeyError, '"creation", "creator", "actor" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1473 '"activity" are reserved' |
| 1165 | 1474 |
| 1475 if propvalues.has_key('id'): | |
| 1476 raise KeyError, '"id" is reserved' | |
| 1477 | |
| 1478 if self.db.journaltag is None: | |
| 1479 raise DatabaseError, 'Database open read-only' | |
| 1480 | |
| 1481 self.fireAuditors('set', nodeid, propvalues) | |
| 1482 # Take a copy of the node dict so that the subsequent set | |
| 1483 # operation doesn't modify the oldvalues structure. | |
| 1484 # XXX used to try the cache here first | |
| 1485 oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid)) | |
| 1486 | |
| 1487 node = self.db.getnode(self.classname, nodeid) | |
| 1488 if self.is_retired(nodeid): | |
| 1489 raise IndexError, 'Requested item is retired' | |
| 1490 num_re = re.compile('^\d+$') | |
| 1491 | |
| 1492 # if the journal value is to be different, store it in here | |
| 1493 journalvalues = {} | |
| 1494 | |
| 1495 # remember the add/remove stuff for multilinks, making it easier | |
| 1496 # for the Database layer to do its stuff | |
| 1497 multilink_changes = {} | |
| 1498 | |
| 1499 for propname, value in propvalues.items(): | |
| 1500 # check to make sure we're not duplicating an existing key | |
| 1501 if propname == self.key and node[propname] != value: | |
| 1502 try: | |
| 1503 self.lookup(value) | |
| 1504 except KeyError: | |
| 1505 pass | |
| 1506 else: | |
| 1507 raise ValueError, 'node with key "%s" exists'%value | |
| 1508 | |
| 1509 # this will raise the KeyError if the property isn't valid | |
| 1510 # ... we don't use getprops() here because we only care about | |
| 1511 # the writeable properties. | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1512 try: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1513 prop = self.properties[propname] |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1514 except KeyError: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1515 raise KeyError, '"%s" has no property named "%s"'%( |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1516 self.classname, propname) |
| 1165 | 1517 |
| 1518 # if the value's the same as the existing value, no sense in | |
| 1519 # doing anything | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1520 current = node.get(propname, None) |
|
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1521 if value == current: |
| 1165 | 1522 del propvalues[propname] |
| 1523 continue | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1524 journalvalues[propname] = current |
| 1165 | 1525 |
| 1526 # do stuff based on the prop type | |
| 1527 if isinstance(prop, Link): | |
| 1528 link_class = prop.classname | |
| 1529 # if it isn't a number, it's a key | |
| 1530 if value is not None and not isinstance(value, type('')): | |
| 1531 raise ValueError, 'property "%s" link value be a string'%( | |
| 1532 propname) | |
| 1533 if isinstance(value, type('')) and not num_re.match(value): | |
| 1534 try: | |
| 1535 value = self.db.classes[link_class].lookup(value) | |
| 1536 except (TypeError, KeyError): | |
| 1537 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1538 propname, value, prop.classname) | |
| 1539 | |
| 1540 if (value is not None and | |
| 1541 not self.db.getclass(link_class).hasnode(value)): | |
| 1542 raise IndexError, '%s has no node %s'%(link_class, value) | |
| 1543 | |
| 1544 if self.do_journal and prop.do_journal: | |
| 1545 # register the unlink with the old linked node | |
| 1546 if node[propname] is not None: | |
| 1547 self.db.addjournal(link_class, node[propname], 'unlink', | |
| 1548 (self.classname, nodeid, propname)) | |
| 1549 | |
| 1550 # register the link with the newly linked node | |
| 1551 if value is not None: | |
| 1552 self.db.addjournal(link_class, value, 'link', | |
| 1553 (self.classname, nodeid, propname)) | |
| 1554 | |
| 1555 elif isinstance(prop, Multilink): | |
| 1556 if type(value) != type([]): | |
| 1557 raise TypeError, 'new property "%s" not a list of'\ | |
| 1558 ' ids'%propname | |
| 1559 link_class = self.properties[propname].classname | |
| 1560 l = [] | |
| 1561 for entry in value: | |
| 1562 # if it isn't a number, it's a key | |
| 1563 if type(entry) != type(''): | |
| 1564 raise ValueError, 'new property "%s" link value ' \ | |
| 1565 'must be a string'%propname | |
| 1566 if not num_re.match(entry): | |
| 1567 try: | |
| 1568 entry = self.db.classes[link_class].lookup(entry) | |
| 1569 except (TypeError, KeyError): | |
| 1570 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1571 propname, entry, | |
| 1572 self.properties[propname].classname) | |
| 1573 l.append(entry) | |
| 1574 value = l | |
| 1575 propvalues[propname] = value | |
| 1576 | |
| 1577 # figure the journal entry for this property | |
| 1578 add = [] | |
| 1579 remove = [] | |
| 1580 | |
| 1581 # handle removals | |
| 1582 if node.has_key(propname): | |
| 1583 l = node[propname] | |
| 1584 else: | |
| 1585 l = [] | |
| 1586 for id in l[:]: | |
| 1587 if id in value: | |
| 1588 continue | |
| 1589 # register the unlink with the old linked node | |
| 1590 if self.do_journal and self.properties[propname].do_journal: | |
| 1591 self.db.addjournal(link_class, id, 'unlink', | |
| 1592 (self.classname, nodeid, propname)) | |
| 1593 l.remove(id) | |
| 1594 remove.append(id) | |
| 1595 | |
| 1596 # handle additions | |
| 1597 for id in value: | |
| 1598 if not self.db.getclass(link_class).hasnode(id): | |
| 1599 raise IndexError, '%s has no node %s'%(link_class, id) | |
| 1600 if id in l: | |
| 1601 continue | |
| 1602 # register the link with the newly linked node | |
| 1603 if self.do_journal and self.properties[propname].do_journal: | |
| 1604 self.db.addjournal(link_class, id, 'link', | |
| 1605 (self.classname, nodeid, propname)) | |
| 1606 l.append(id) | |
| 1607 add.append(id) | |
| 1608 | |
| 1609 # figure the journal entry | |
| 1610 l = [] | |
| 1611 if add: | |
| 1612 l.append(('+', add)) | |
| 1613 if remove: | |
| 1614 l.append(('-', remove)) | |
| 1615 multilink_changes[propname] = (add, remove) | |
| 1616 if l: | |
| 1617 journalvalues[propname] = tuple(l) | |
| 1618 | |
| 1619 elif isinstance(prop, String): | |
|
1383
f19dde90e473
applied unicode patch
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1365
diff
changeset
|
1620 if value is not None and type(value) != type('') and type(value) != type(u''): |
| 1165 | 1621 raise TypeError, 'new property "%s" not a string'%propname |
| 1622 | |
| 1623 elif isinstance(prop, Password): | |
| 1624 if not isinstance(value, password.Password): | |
| 1625 raise TypeError, 'new property "%s" not a Password'%propname | |
| 1626 propvalues[propname] = value | |
| 1627 | |
| 1628 elif value is not None and isinstance(prop, Date): | |
| 1629 if not isinstance(value, date.Date): | |
| 1630 raise TypeError, 'new property "%s" not a Date'% propname | |
| 1631 propvalues[propname] = value | |
| 1632 | |
| 1633 elif value is not None and isinstance(prop, Interval): | |
| 1634 if not isinstance(value, date.Interval): | |
| 1635 raise TypeError, 'new property "%s" not an '\ | |
| 1636 'Interval'%propname | |
| 1637 propvalues[propname] = value | |
| 1638 | |
| 1639 elif value is not None and isinstance(prop, Number): | |
| 1640 try: | |
| 1641 float(value) | |
| 1642 except ValueError: | |
| 1643 raise TypeError, 'new property "%s" not numeric'%propname | |
| 1644 | |
| 1645 elif value is not None and isinstance(prop, Boolean): | |
| 1646 try: | |
| 1647 int(value) | |
| 1648 except ValueError: | |
| 1649 raise TypeError, 'new property "%s" not boolean'%propname | |
| 1650 | |
| 1651 # nothing to do? | |
| 1652 if not propvalues: | |
| 1653 return propvalues | |
| 1654 | |
| 1655 # do the set, and journal it | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1656 self.db.setnode(self.classname, nodeid, propvalues, multilink_changes) |
| 1165 | 1657 |
| 1658 if self.do_journal: | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1659 self.db.addjournal(self.classname, nodeid, 'set', journalvalues) |
| 1165 | 1660 |
| 1661 self.fireReactors('set', nodeid, oldvalues) | |
| 1662 | |
| 1663 return propvalues | |
| 1664 | |
| 1665 def retire(self, nodeid): | |
| 1666 '''Retire a node. | |
| 1667 | |
| 1668 The properties on the node remain available from the get() method, | |
| 1669 and the node's id is never reused. | |
| 1670 | |
| 1671 Retired nodes are not returned by the find(), list(), or lookup() | |
| 1672 methods, and other nodes may reuse the values of their key properties. | |
| 1673 ''' | |
| 1674 if self.db.journaltag is None: | |
| 1675 raise DatabaseError, 'Database open read-only' | |
| 1676 | |
|
1345
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1677 self.fireAuditors('retire', nodeid, None) |
|
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1678 |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1679 # use the arg for __retired__ to cope with any odd database type |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1680 # conversion (hello, sqlite) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1681 sql = 'update _%s set __retired__=%s where id=%s'%(self.classname, |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1682 self.db.arg, self.db.arg) |
| 1165 | 1683 if __debug__: |
| 1684 print >>hyperdb.DEBUG, 'retire', (self, sql, nodeid) | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1685 self.db.cursor.execute(sql, (1, nodeid)) |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1686 if self.do_journal: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1687 self.db.addjournal(self.classname, nodeid, 'retired', None) |
| 1165 | 1688 |
|
1345
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1689 self.fireReactors('retire', nodeid, None) |
|
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1690 |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1691 def restore(self, nodeid): |
|
1740
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
1692 '''Restore a retired node. |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1693 |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1694 Make node available for all operations like it was before retirement. |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1695 ''' |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1696 if self.db.journaltag is None: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1697 raise DatabaseError, 'Database open read-only' |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1698 |
|
1523
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1699 node = self.db.getnode(self.classname, nodeid) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1700 # check if key property was overrided |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1701 key = self.getkey() |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1702 try: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1703 id = self.lookup(node[key]) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1704 except KeyError: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1705 pass |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1706 else: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1707 raise KeyError, "Key property (%s) of retired node clashes with \ |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1708 existing one (%s)" % (key, node[key]) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1709 |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1710 self.fireAuditors('restore', nodeid, None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1711 # use the arg for __retired__ to cope with any odd database type |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1712 # conversion (hello, sqlite) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1713 sql = 'update _%s set __retired__=%s where id=%s'%(self.classname, |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1714 self.db.arg, self.db.arg) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1715 if __debug__: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1716 print >>hyperdb.DEBUG, 'restore', (self, sql, nodeid) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1717 self.db.cursor.execute(sql, (0, nodeid)) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1718 if self.do_journal: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1719 self.db.addjournal(self.classname, nodeid, 'restored', None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1720 |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1721 self.fireReactors('restore', nodeid, None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1722 |
| 1165 | 1723 def is_retired(self, nodeid): |
| 1724 '''Return true if the node is rerired | |
| 1725 ''' | |
| 1726 sql = 'select __retired__ from _%s where id=%s'%(self.classname, | |
| 1727 self.db.arg) | |
| 1728 if __debug__: | |
| 1729 print >>hyperdb.DEBUG, 'is_retired', (self, sql, nodeid) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1730 self.db.cursor.execute(sql, (nodeid,)) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1731 return int(self.db.sql_fetchone()[0]) |
| 1165 | 1732 |
| 1733 def destroy(self, nodeid): | |
| 1734 '''Destroy a node. | |
| 1735 | |
| 1736 WARNING: this method should never be used except in extremely rare | |
| 1737 situations where there could never be links to the node being | |
| 1738 deleted | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1739 |
| 1165 | 1740 WARNING: use retire() instead |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1741 |
| 1165 | 1742 WARNING: the properties of this node will not be available ever again |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1743 |
| 1165 | 1744 WARNING: really, use retire() instead |
| 1745 | |
| 1746 Well, I think that's enough warnings. This method exists mostly to | |
| 1747 support the session storage of the cgi interface. | |
| 1748 | |
| 1749 The node is completely removed from the hyperdb, including all journal | |
| 1750 entries. It will no longer be available, and will generally break code | |
| 1751 if there are any references to the node. | |
| 1752 ''' | |
| 1753 if self.db.journaltag is None: | |
| 1754 raise DatabaseError, 'Database open read-only' | |
| 1755 self.db.destroynode(self.classname, nodeid) | |
| 1756 | |
| 1757 def history(self, nodeid): | |
| 1758 '''Retrieve the journal of edits on a particular node. | |
| 1759 | |
| 1760 'nodeid' must be the id of an existing node of this class or an | |
| 1761 IndexError is raised. | |
| 1762 | |
| 1763 The returned list contains tuples of the form | |
| 1764 | |
|
1409
8dc60d87ab42
Fixed a backlog of bug reports, and worked on python 2.3 compatibility:
Richard Jones <richard@users.sourceforge.net>
parents:
1383
diff
changeset
|
1765 (nodeid, date, tag, action, params) |
| 1165 | 1766 |
| 1767 'date' is a Timestamp object specifying the time of the change and | |
| 1768 'tag' is the journaltag specified when the database was opened. | |
| 1769 ''' | |
| 1770 if not self.do_journal: | |
| 1771 raise ValueError, 'Journalling is disabled for this class' | |
| 1772 return self.db.getjournal(self.classname, nodeid) | |
| 1773 | |
| 1774 # Locating nodes: | |
| 1775 def hasnode(self, nodeid): | |
| 1776 '''Determine if the given nodeid actually exists | |
| 1777 ''' | |
| 1778 return self.db.hasnode(self.classname, nodeid) | |
| 1779 | |
| 1780 def setkey(self, propname): | |
| 1781 '''Select a String property of this class to be the key property. | |
| 1782 | |
| 1783 'propname' must be the name of a String property of this class or | |
| 1784 None, or a TypeError is raised. The values of the key property on | |
| 1785 all existing nodes must be unique or a ValueError is raised. | |
| 1786 ''' | |
|
1838
532f51a2c741
expand an XXX comment
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1836
diff
changeset
|
1787 # XXX create an index on the key prop column. We should also |
|
532f51a2c741
expand an XXX comment
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1836
diff
changeset
|
1788 # record that we've created this index in the schema somewhere. |
| 1165 | 1789 prop = self.getprops()[propname] |
| 1790 if not isinstance(prop, String): | |
| 1791 raise TypeError, 'key properties must be String' | |
| 1792 self.key = propname | |
| 1793 | |
| 1794 def getkey(self): | |
| 1795 '''Return the name of the key property for this class or None.''' | |
| 1796 return self.key | |
| 1797 | |
| 1798 def labelprop(self, default_to_id=0): | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1799 '''Return the property name for a label for the given node. |
| 1165 | 1800 |
| 1801 This method attempts to generate a consistent label for the node. | |
| 1802 It tries the following in order: | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1803 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1804 1. key property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1805 2. "name" property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1806 3. "title" property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1807 4. first property from the sorted property name list |
| 1165 | 1808 ''' |
| 1809 k = self.getkey() | |
| 1810 if k: | |
| 1811 return k | |
| 1812 props = self.getprops() | |
| 1813 if props.has_key('name'): | |
| 1814 return 'name' | |
| 1815 elif props.has_key('title'): | |
| 1816 return 'title' | |
| 1817 if default_to_id: | |
| 1818 return 'id' | |
| 1819 props = props.keys() | |
| 1820 props.sort() | |
| 1821 return props[0] | |
| 1822 | |
| 1823 def lookup(self, keyvalue): | |
| 1824 '''Locate a particular node by its key property and return its id. | |
| 1825 | |
| 1826 If this class has no key property, a TypeError is raised. If the | |
| 1827 'keyvalue' matches one of the values for the key property among | |
| 1828 the nodes in this class, the matching node's id is returned; | |
| 1829 otherwise a KeyError is raised. | |
| 1830 ''' | |
| 1831 if not self.key: | |
| 1832 raise TypeError, 'No key property set for class %s'%self.classname | |
| 1833 | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1834 # use the arg to handle any odd database type conversion (hello, |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1835 # sqlite) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1836 sql = "select id from _%s where _%s=%s and __retired__ <> %s"%( |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1837 self.classname, self.key, self.db.arg, self.db.arg) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1838 self.db.sql(sql, (keyvalue, 1)) |
| 1165 | 1839 |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1840 # see if there was a result that's not retired |
|
1203
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1841 row = self.db.sql_fetchone() |
|
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1842 if not row: |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1843 raise KeyError, 'No key (%s) value "%s" for "%s"'%(self.key, |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1844 keyvalue, self.classname) |
| 1165 | 1845 |
| 1846 # return the id | |
|
1203
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1847 return row[0] |
| 1165 | 1848 |
| 1849 def find(self, **propspec): | |
| 1850 '''Get the ids of nodes in this class which link to the given nodes. | |
| 1851 | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1852 'propspec' consists of keyword args propname=nodeid or |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1853 propname={nodeid:1, } |
| 1165 | 1854 'propname' must be the name of a property in this class, or a |
|
1912
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1855 KeyError is raised. That property must be a Link or |
|
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1856 Multilink property, or a TypeError is raised. |
| 1165 | 1857 |
| 1858 Any node in this class whose 'propname' property links to any of the | |
| 1859 nodeids will be returned. Used by the full text indexing, which knows | |
| 1860 that "foo" occurs in msg1, msg3 and file7, so we have hits on these | |
| 1861 issues: | |
| 1862 | |
| 1863 db.issue.find(messages={'1':1,'3':1}, files={'7':1}) | |
| 1864 ''' | |
| 1865 if __debug__: | |
| 1866 print >>hyperdb.DEBUG, 'find', (self, propspec) | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1867 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1868 # shortcut |
| 1165 | 1869 if not propspec: |
| 1870 return [] | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1871 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1872 # validate the args |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1873 props = self.getprops() |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1874 propspec = propspec.items() |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1875 for propname, nodeids in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1876 # check the prop is OK |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1877 prop = props[propname] |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1878 if not isinstance(prop, Link) and not isinstance(prop, Multilink): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1879 raise TypeError, "'%s' not a Link/Multilink property"%propname |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1880 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1881 # first, links |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1882 a = self.db.arg |
|
1986
910b39f8c5b8
use the upload-supplied content-type if there is one
Richard Jones <richard@users.sourceforge.net>
parents:
1951
diff
changeset
|
1883 allvalues = (1,) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1884 o = [] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1885 where = [] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1886 for prop, values in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1887 if not isinstance(props[prop], hyperdb.Link): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1888 continue |
|
1912
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1889 if type(values) is type({}) and len(values) == 1: |
|
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1890 values = values.keys()[0] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1891 if type(values) is type(''): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1892 allvalues += (values,) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1893 where.append('_%s = %s'%(prop, a)) |
|
1563
e2a8ce4d2317
Class.find() may now find unset Links [SF#700620]
Richard Jones <richard@users.sourceforge.net>
parents:
1557
diff
changeset
|
1894 elif values is None: |
|
e2a8ce4d2317
Class.find() may now find unset Links [SF#700620]
Richard Jones <richard@users.sourceforge.net>
parents:
1557
diff
changeset
|
1895 where.append('_%s is NULL'%prop) |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1896 else: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1897 allvalues += tuple(values.keys()) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1898 where.append('_%s in (%s)'%(prop, ','.join([a]*len(values)))) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1899 tables = ['_%s'%self.classname] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1900 if where: |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1901 o.append('(' + ' and '.join(where) + ')') |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1902 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1903 # now multilinks |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1904 for prop, values in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1905 if not isinstance(props[prop], hyperdb.Multilink): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1906 continue |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1907 if not values: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1908 continue |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1909 if type(values) is type(''): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1910 allvalues += (values,) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1911 s = a |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1912 else: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1913 allvalues += tuple(values.keys()) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1914 s = ','.join([a]*len(values)) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1915 tn = '%s_%s'%(self.classname, prop) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1916 tables.append(tn) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1917 o.append('(id=%s.nodeid and %s.linkid in (%s))'%(tn, tn, s)) |
|
1986
910b39f8c5b8
use the upload-supplied content-type if there is one
Richard Jones <richard@users.sourceforge.net>
parents:
1951
diff
changeset
|
1918 |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1919 if not o: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1920 return [] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1921 elif len(o) > 1: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1922 o = '(' + ' or '.join(['(%s)'%i for i in o]) + ')' |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1923 else: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1924 o = o[0] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1925 t = ', '.join(tables) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1926 sql = 'select distinct(id) from %s where __retired__ <> %s and %s'%(t, a, o) |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1927 self.db.sql(sql, allvalues) |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1928 l = [x[0] for x in self.db.sql_fetchall()] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1929 if __debug__: |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1930 print >>hyperdb.DEBUG, 'find ... ', l |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1931 return l |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1932 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1933 def stringFind(self, **requirements): |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1934 '''Locate a particular node by matching a set of its String |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1935 properties in a caseless search. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1936 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1937 If the property is not a String property, a TypeError is raised. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1938 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1939 The return is a list of the id of all nodes that match. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1940 ''' |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1941 where = [] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1942 args = [] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1943 for propname in requirements.keys(): |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1944 prop = self.properties[propname] |
|
1951
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1945 if not isinstance(prop, String): |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1946 raise TypeError, "'%s' not a String property"%propname |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1947 where.append(propname) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1948 args.append(requirements[propname].lower()) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1949 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1950 # generate the where clause |
|
1549
a53a7e197360
fixed rdbms email address lookup (case insensitivity)
Richard Jones <richard@users.sourceforge.net>
parents:
1539
diff
changeset
|
1951 s = ' and '.join(['lower(_%s)=%s'%(col, self.db.arg) for col in where]) |
|
1951
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1952 sql = 'select id from _%s where %s and __retired__=%s'%(self.classname, |
|
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1953 s, self.db.arg) |
|
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1954 args.append(0) |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1955 self.db.sql(sql, tuple(args)) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1956 l = [x[0] for x in self.db.sql_fetchall()] |
| 1165 | 1957 if __debug__: |
| 1958 print >>hyperdb.DEBUG, 'find ... ', l | |
| 1959 return l | |
| 1960 | |
| 1961 def list(self): | |
| 1962 ''' Return a list of the ids of the active nodes in this class. | |
| 1963 ''' | |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1964 return self.getnodeids(retired=0) |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1965 |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1966 def getnodeids(self, retired=None): |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1967 ''' Retrieve all the ids of the nodes for a particular Class. |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1968 |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1969 Set retired=None to get all nodes. Otherwise it'll get all the |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1970 retired or non-retired nodes, depending on the flag. |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1971 ''' |
|
1707
3d627e34f18e
sqlite backend now passes all tests under 2.3.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1599
diff
changeset
|
1972 # flip the sense of the 'retired' flag if we don't want all of them |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1973 if retired is not None: |
|
1719
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1974 if retired: |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1975 args = (0, ) |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1976 else: |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1977 args = (1, ) |
|
1539
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1978 sql = 'select id from _%s where __retired__ <> %s'%(self.classname, |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1979 self.db.arg) |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1980 else: |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1981 args = () |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1982 sql = 'select id from _%s'%self.classname |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1983 if __debug__: |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1984 print >>hyperdb.DEBUG, 'getnodeids', (self, sql, retired) |
|
1539
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1985 self.db.cursor.execute(sql, args) |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1986 ids = [x[0] for x in self.db.cursor.fetchall()] |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1987 return ids |
| 1165 | 1988 |
|
1249
6c24a86a12ae
Fixes for SourceForge tracker bugs.
Richard Jones <richard@users.sourceforge.net>
parents:
1244
diff
changeset
|
1989 def filter(self, search_matches, filterspec, sort=(None,None), |
|
6c24a86a12ae
Fixes for SourceForge tracker bugs.
Richard Jones <richard@users.sourceforge.net>
parents:
1244
diff
changeset
|
1990 group=(None,None)): |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1991 '''Return a list of the ids of the active nodes in this class that |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1992 match the 'filter' spec, sorted by the group spec and then the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1993 sort spec |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1994 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1995 "filterspec" is {propname: value(s)} |
| 1165 | 1996 |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1997 "sort" and "group" are (dir, prop) where dir is '+', '-' or None |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1998 and prop is a prop name or None |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
1999 |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2000 "search_matches" is {nodeid: marker} |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2001 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2002 The filter must match all properties specificed - but if the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2003 property value to match is a list, any one of the values in the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2004 list may match for that property to match. |
| 1165 | 2005 ''' |
|
1205
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2006 # just don't bother if the full-text search matched diddly |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2007 if search_matches == {}: |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2008 return [] |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2009 |
| 1165 | 2010 cn = self.classname |
| 2011 | |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2012 timezone = self.db.getUserTimezone() |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2013 |
| 1165 | 2014 # figure the WHERE clause from the filterspec |
| 2015 props = self.getprops() | |
| 2016 frum = ['_'+cn] | |
| 2017 where = [] | |
| 2018 args = [] | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2019 a = self.db.arg |
| 1165 | 2020 for k, v in filterspec.items(): |
| 2021 propclass = props[k] | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2022 # now do other where clause stuff |
| 1165 | 2023 if isinstance(propclass, Multilink): |
| 2024 tn = '%s_%s'%(cn, k) | |
|
1556
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2025 if v in ('-1', ['-1']): |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2026 # only match rows that have count(linkid)=0 in the |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2027 # corresponding multilink table) |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2028 where.append('id not in (select nodeid from %s)'%tn) |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2029 elif isinstance(v, type([])): |
|
1555
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2030 frum.append(tn) |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2031 s = ','.join([a for x in v]) |
| 1165 | 2032 where.append('id=%s.nodeid and %s.linkid in (%s)'%(tn,tn,s)) |
| 2033 args = args + v | |
| 2034 else: | |
|
1555
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2035 frum.append(tn) |
|
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2036 where.append('id=%s.nodeid and %s.linkid=%s'%(tn, tn, a)) |
| 1165 | 2037 args.append(v) |
|
1365
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2038 elif k == 'id': |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2039 if isinstance(v, type([])): |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2040 s = ','.join([a for x in v]) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2041 where.append('%s in (%s)'%(k, s)) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2042 args = args + v |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2043 else: |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2044 where.append('%s=%s'%(k, a)) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2045 args.append(v) |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2046 elif isinstance(propclass, String): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2047 if not isinstance(v, type([])): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2048 v = [v] |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2049 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2050 # Quote the bits in the string that need it and then embed |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2051 # in a "substring" search. Note - need to quote the '%' so |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2052 # they make it through the python layer happily |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2053 v = ['%%'+self.db.sql_stringquote(s)+'%%' for s in v] |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2054 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2055 # now add to the where clause |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2056 where.append(' or '.join(["_%s LIKE '%s'"%(k, s) for s in v])) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2057 # note: args are embedded in the query string now |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2058 elif isinstance(propclass, Link): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2059 if isinstance(v, type([])): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2060 if '-1' in v: |
|
1578
ba13c04814f0
don't modify filterspec passed in (bad Richard)
Richard Jones <richard@users.sourceforge.net>
parents:
1563
diff
changeset
|
2061 v = v[:] |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2062 v.remove('-1') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2063 xtra = ' or _%s is NULL'%k |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
2064 else: |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
2065 xtra = '' |
|
1295
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2066 if v: |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2067 s = ','.join([a for x in v]) |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2068 where.append('(_%s in (%s)%s)'%(k, s, xtra)) |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2069 args = args + v |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2070 else: |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2071 where.append('_%s is NULL'%k) |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2072 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2073 if v == '-1': |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2074 v = None |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2075 where.append('_%s is NULL'%k) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2076 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2077 where.append('_%s=%s'%(k, a)) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2078 args.append(v) |
|
1351
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2079 elif isinstance(propclass, Date): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2080 if isinstance(v, type([])): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2081 s = ','.join([a for x in v]) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2082 where.append('_%s in (%s)'%(k, s)) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2083 args = args + [date.Date(x).serialise() for x in v] |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2084 else: |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2085 try: |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2086 # Try to filter on range of dates |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2087 date_rng = Range(v, date.Date, offset=timezone) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2088 if (date_rng.from_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2089 where.append('_%s >= %s'%(k, a)) |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2090 args.append(date_rng.from_value.serialise()) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2091 if (date_rng.to_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2092 where.append('_%s <= %s'%(k, a)) |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2093 args.append(date_rng.to_value.serialise()) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2094 except ValueError: |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2095 # If range creation fails - ignore that search parameter |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2096 pass |
|
1351
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2097 elif isinstance(propclass, Interval): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2098 if isinstance(v, type([])): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2099 s = ','.join([a for x in v]) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2100 where.append('_%s in (%s)'%(k, s)) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2101 args = args + [date.Interval(x).serialise() for x in v] |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2102 else: |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2103 try: |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2104 # Try to filter on range of intervals |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2105 date_rng = Range(v, date.Interval) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2106 if (date_rng.from_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2107 where.append('_%s >= %s'%(k, a)) |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2108 args.append(date_rng.from_value.serialise()) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2109 if (date_rng.to_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2110 where.append('_%s <= %s'%(k, a)) |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2111 args.append(date_rng.to_value.serialise()) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2112 except ValueError: |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2113 # If range creation fails - ignore that search parameter |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2114 pass |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2115 #where.append('_%s=%s'%(k, a)) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2116 #args.append(date.Interval(v).serialise()) |
| 1165 | 2117 else: |
| 2118 if isinstance(v, type([])): | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2119 s = ','.join([a for x in v]) |
| 1165 | 2120 where.append('_%s in (%s)'%(k, s)) |
| 2121 args = args + v | |
| 2122 else: | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2123 where.append('_%s=%s'%(k, a)) |
| 1165 | 2124 args.append(v) |
| 2125 | |
|
1740
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2126 # don't match retired nodes |
|
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2127 where.append('__retired__ <> 1') |
|
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2128 |
| 1165 | 2129 # add results of full text search |
| 2130 if search_matches is not None: | |
| 2131 v = search_matches.keys() | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2132 s = ','.join([a for x in v]) |
| 1165 | 2133 where.append('id in (%s)'%s) |
| 2134 args = args + v | |
| 2135 | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2136 # "grouping" is just the first-order sorting in the SQL fetch |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2137 # can modify it...) |
| 1165 | 2138 orderby = [] |
| 2139 ordercols = [] | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2140 if group[0] is not None and group[1] is not None: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2141 if group[0] != '-': |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2142 orderby.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2143 ordercols.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2144 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2145 orderby.append('_'+group[1]+' desc') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2146 ordercols.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2147 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2148 # now add in the sorting |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2149 group = '' |
| 1165 | 2150 if sort[0] is not None and sort[1] is not None: |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2151 direction, colname = sort |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2152 if direction != '-': |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2153 if colname == 'id': |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2154 orderby.append(colname) |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2155 else: |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2156 orderby.append('_'+colname) |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2157 ordercols.append('_'+colname) |
| 1165 | 2158 else: |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2159 if colname == 'id': |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2160 orderby.append(colname+' desc') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2161 ordercols.append(colname) |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2162 else: |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2163 orderby.append('_'+colname+' desc') |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2164 ordercols.append('_'+colname) |
| 1165 | 2165 |
| 2166 # construct the SQL | |
| 2167 frum = ','.join(frum) | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2168 if where: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2169 where = ' where ' + (' and '.join(where)) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2170 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2171 where = '' |
| 1165 | 2172 cols = ['id'] |
| 2173 if orderby: | |
| 2174 cols = cols + ordercols | |
| 2175 order = ' order by %s'%(','.join(orderby)) | |
| 2176 else: | |
| 2177 order = '' | |
| 2178 cols = ','.join(cols) | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2179 sql = 'select %s from %s %s%s%s'%(cols, frum, where, group, order) |
| 1165 | 2180 args = tuple(args) |
| 2181 if __debug__: | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2182 print >>hyperdb.DEBUG, 'filter', (self, sql, args) |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2183 if args: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2184 self.db.cursor.execute(sql, args) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2185 else: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2186 # psycopg doesn't like empty args |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2187 self.db.cursor.execute(sql) |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
2188 l = self.db.sql_fetchall() |
| 1165 | 2189 |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2190 # return the IDs (the first column) |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
2191 return [row[0] for row in l] |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2192 |
| 1165 | 2193 def count(self): |
| 2194 '''Get the number of nodes in this class. | |
| 2195 | |
| 2196 If the returned integer is 'numnodes', the ids of all the nodes | |
| 2197 in this class run from 1 to numnodes, and numnodes+1 will be the | |
| 2198 id of the next node to be created in this class. | |
| 2199 ''' | |
| 2200 return self.db.countnodes(self.classname) | |
| 2201 | |
| 2202 # Manipulating properties: | |
| 2203 def getprops(self, protected=1): | |
| 2204 '''Return a dictionary mapping property names to property objects. | |
| 2205 If the "protected" flag is true, we include protected properties - | |
| 2206 those which may not be modified. | |
| 2207 ''' | |
| 2208 d = self.properties.copy() | |
| 2209 if protected: | |
| 2210 d['id'] = String() | |
| 2211 d['creation'] = hyperdb.Date() | |
| 2212 d['activity'] = hyperdb.Date() | |
|
1176
bd3b57859c37
On second thought, that last checkin was dumb.
Richard Jones <richard@users.sourceforge.net>
parents:
1175
diff
changeset
|
2213 d['creator'] = hyperdb.Link('user') |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
2214 d['actor'] = hyperdb.Link('user') |
| 1165 | 2215 return d |
| 2216 | |
| 2217 def addprop(self, **properties): | |
| 2218 '''Add properties to this class. | |
| 2219 | |
| 2220 The keyword arguments in 'properties' must map names to property | |
| 2221 objects, or a TypeError is raised. None of the keys in 'properties' | |
| 2222 may collide with the names of existing properties, or a ValueError | |
| 2223 is raised before any properties have been added. | |
| 2224 ''' | |
| 2225 for key in properties.keys(): | |
| 2226 if self.properties.has_key(key): | |
| 2227 raise ValueError, key | |
| 2228 self.properties.update(properties) | |
| 2229 | |
| 2230 def index(self, nodeid): | |
| 2231 '''Add (or refresh) the node to search indexes | |
| 2232 ''' | |
| 2233 # find all the String properties that have indexme | |
| 2234 for prop, propclass in self.getprops().items(): | |
| 2235 if isinstance(propclass, String) and propclass.indexme: | |
| 2236 try: | |
| 2237 value = str(self.get(nodeid, prop)) | |
| 2238 except IndexError: | |
| 2239 # node no longer exists - entry should be removed | |
| 2240 self.db.indexer.purge_entry((self.classname, nodeid, prop)) | |
| 2241 else: | |
| 2242 # and index them under (classname, nodeid, property) | |
| 2243 self.db.indexer.add_text((self.classname, nodeid, prop), | |
| 2244 value) | |
| 2245 | |
| 2246 | |
| 2247 # | |
| 2248 # Detector interface | |
| 2249 # | |
| 2250 def audit(self, event, detector): | |
| 2251 '''Register a detector | |
| 2252 ''' | |
| 2253 l = self.auditors[event] | |
| 2254 if detector not in l: | |
| 2255 self.auditors[event].append(detector) | |
| 2256 | |
| 2257 def fireAuditors(self, action, nodeid, newvalues): | |
| 2258 '''Fire all registered auditors. | |
| 2259 ''' | |
| 2260 for audit in self.auditors[action]: | |
| 2261 audit(self.db, self, nodeid, newvalues) | |
| 2262 | |
| 2263 def react(self, event, detector): | |
| 2264 '''Register a detector | |
| 2265 ''' | |
| 2266 l = self.reactors[event] | |
| 2267 if detector not in l: | |
| 2268 self.reactors[event].append(detector) | |
| 2269 | |
| 2270 def fireReactors(self, action, nodeid, oldvalues): | |
| 2271 '''Fire all registered reactors. | |
| 2272 ''' | |
| 2273 for react in self.reactors[action]: | |
| 2274 react(self.db, self, nodeid, oldvalues) | |
| 2275 | |
|
1442
b42fa71754c9
don't attempt to create FileClass items if no content is supplied
Richard Jones <richard@users.sourceforge.net>
parents:
1431
diff
changeset
|
2276 class FileClass(Class, hyperdb.FileClass): |
| 1165 | 2277 '''This class defines a large chunk of data. To support this, it has a |
| 2278 mandatory String property "content" which is typically saved off | |
| 2279 externally to the hyperdb. | |
| 2280 | |
| 2281 The default MIME type of this data is defined by the | |
| 2282 "default_mime_type" class attribute, which may be overridden by each | |
| 2283 node if the class defines a "type" String property. | |
| 2284 ''' | |
| 2285 default_mime_type = 'text/plain' | |
| 2286 | |
| 2287 def create(self, **propvalues): | |
| 2288 ''' snaffle the file propvalue and store in a file | |
| 2289 ''' | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2290 # we need to fire the auditors now, or the content property won't |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2291 # be in propvalues for the auditors to play with |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2292 self.fireAuditors('create', None, propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2293 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2294 # now remove the content property so it's not stored in the db |
| 1165 | 2295 content = propvalues['content'] |
| 2296 del propvalues['content'] | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2297 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2298 # do the database create |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2299 newid = Class.create_inner(self, **propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2300 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2301 # fire reactors |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2302 self.fireReactors('create', newid, None) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2303 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2304 # store off the content as a file |
| 1165 | 2305 self.db.storefile(self.classname, newid, None, content) |
| 2306 return newid | |
| 2307 | |
| 2308 def import_list(self, propnames, proplist): | |
| 2309 ''' Trap the "content" property... | |
| 2310 ''' | |
| 2311 # dupe this list so we don't affect others | |
| 2312 propnames = propnames[:] | |
| 2313 | |
| 2314 # extract the "content" property from the proplist | |
| 2315 i = propnames.index('content') | |
| 2316 content = eval(proplist[i]) | |
| 2317 del propnames[i] | |
| 2318 del proplist[i] | |
| 2319 | |
| 2320 # do the normal import | |
| 2321 newid = Class.import_list(self, propnames, proplist) | |
| 2322 | |
| 2323 # save off the "content" file | |
| 2324 self.db.storefile(self.classname, newid, None, content) | |
| 2325 return newid | |
| 2326 | |
| 2327 _marker = [] | |
| 2328 def get(self, nodeid, propname, default=_marker, cache=1): | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2329 ''' Trap the content propname and get it from the file |
|
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2330 |
|
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2331 'cache' exists for backwards compatibility, and is not used. |
| 1165 | 2332 ''' |
| 2333 poss_msg = 'Possibly a access right configuration problem.' | |
| 2334 if propname == 'content': | |
| 2335 try: | |
| 2336 return self.db.getfile(self.classname, nodeid, None) | |
| 2337 except IOError, (strerror): | |
| 2338 # BUG: by catching this we donot see an error in the log. | |
| 2339 return 'ERROR reading file: %s%s\n%s\n%s'%( | |
| 2340 self.classname, nodeid, poss_msg, strerror) | |
| 2341 if default is not self._marker: | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2342 return Class.get(self, nodeid, propname, default) |
| 1165 | 2343 else: |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2344 return Class.get(self, nodeid, propname) |
| 1165 | 2345 |
| 2346 def getprops(self, protected=1): | |
| 2347 ''' In addition to the actual properties on the node, these methods | |
| 2348 provide the "content" property. If the "protected" flag is true, | |
| 2349 we include protected properties - those which may not be | |
| 2350 modified. | |
| 2351 ''' | |
| 2352 d = Class.getprops(self, protected=protected).copy() | |
| 2353 d['content'] = hyperdb.String() | |
| 2354 return d | |
| 2355 | |
| 2356 def index(self, nodeid): | |
| 2357 ''' Index the node in the search index. | |
| 2358 | |
| 2359 We want to index the content in addition to the normal String | |
| 2360 property indexing. | |
| 2361 ''' | |
| 2362 # perform normal indexing | |
| 2363 Class.index(self, nodeid) | |
| 2364 | |
| 2365 # get the content to index | |
| 2366 content = self.get(nodeid, 'content') | |
| 2367 | |
| 2368 # figure the mime type | |
| 2369 if self.properties.has_key('type'): | |
| 2370 mime_type = self.get(nodeid, 'type') | |
| 2371 else: | |
| 2372 mime_type = self.default_mime_type | |
| 2373 | |
| 2374 # and index! | |
| 2375 self.db.indexer.add_text((self.classname, nodeid, 'content'), content, | |
| 2376 mime_type) | |
| 2377 | |
| 2378 # XXX deviation from spec - was called ItemClass | |
| 2379 class IssueClass(Class, roundupdb.IssueClass): | |
| 2380 # Overridden methods: | |
| 2381 def __init__(self, db, classname, **properties): | |
| 2382 '''The newly-created class automatically includes the "messages", | |
| 2383 "files", "nosy", and "superseder" properties. If the 'properties' | |
| 2384 dictionary attempts to specify any of these properties or a | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
2385 "creation", "creator", "activity" or "actor" property, a ValueError |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
2386 is raised. |
| 1165 | 2387 ''' |
| 2388 if not properties.has_key('title'): | |
| 2389 properties['title'] = hyperdb.String(indexme='yes') | |
| 2390 if not properties.has_key('messages'): | |
| 2391 properties['messages'] = hyperdb.Multilink("msg") | |
| 2392 if not properties.has_key('files'): | |
| 2393 properties['files'] = hyperdb.Multilink("file") | |
| 2394 if not properties.has_key('nosy'): | |
| 2395 # note: journalling is turned off as it really just wastes | |
| 2396 # space. this behaviour may be overridden in an instance | |
| 2397 properties['nosy'] = hyperdb.Multilink("user", do_journal="no") | |
| 2398 if not properties.has_key('superseder'): | |
| 2399 properties['superseder'] = hyperdb.Multilink(classname) | |
| 2400 Class.__init__(self, db, classname, **properties) | |
| 2401 |
