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