Mercurial > p > roundup > code
annotate roundup/backends/rdbms_common.py @ 2093:3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Note that the code currently has some unit testing issues:
- Metakit needs some attention in a couple of areas
- RDBMS backends are having trouble ordering their journal entries
correctly. I'm going to be migrating them to use TIMESTAMP for the date
column, but that's not necessarily going to fix things as mysql and
postgresql both appear to have second granularity. Sqlite will ignore
the data type as usual ;)
Next up is the datatype-ification of the RDBMS backends. Part of that will
involve the migration to numeric IDs, which will also be done in the *dbm
backends (already done in metakit). The ID exposed *above* the hyperdb
will be String, since so many things assume a string ID now.
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Sun, 21 Mar 2004 23:39:08 +0000 |
| parents | 93f03c6714d8 |
| children | 18addf2a8596 |
| rev | line source |
|---|---|
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
1 # $Id: rdbms_common.py,v 1.83 2004-03-21 23:39:08 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 | |
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
42 from indexer_rdbms 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 = {} | |
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
62 self.indexer = Indexer(self) |
| 1165 | 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 | |
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
180 self.sql_commit() |
| 1165 | 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, )) |
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
594 newid = int(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 ''' | |
|
2093
3f6024ab2c7a
That's the last of the RDBMS migration steps done! Yay!
Richard Jones <richard@users.sourceforge.net>
parents:
2089
diff
changeset
|
1069 self.indexer.close() |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
1070 self.sql_close() |
| 1165 | 1071 |
| 1072 # | |
| 1073 # The base Class class | |
| 1074 # | |
| 1075 class Class(hyperdb.Class): | |
| 1076 ''' The handle to a particular class of nodes in a hyperdatabase. | |
| 1077 | |
| 1078 All methods except __repr__ and getnode must be implemented by a | |
| 1079 concrete backend Class. | |
| 1080 ''' | |
| 1081 | |
| 1082 def __init__(self, db, classname, **properties): | |
| 1083 '''Create a new class with a given name and property specification. | |
| 1084 | |
| 1085 'classname' must not collide with the name of an existing class, | |
| 1086 or a ValueError is raised. The keyword arguments in 'properties' | |
| 1087 must map names to property objects, or a TypeError is raised. | |
| 1088 ''' | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1089 for name in 'creation activity creator actor'.split(): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1090 if properties.has_key(name): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1091 raise ValueError, '"creation", "activity", "creator" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1092 '"actor" are reserved' |
| 1165 | 1093 |
| 1094 self.classname = classname | |
| 1095 self.properties = properties | |
| 1096 self.db = weakref.proxy(db) # use a weak ref to avoid circularity | |
| 1097 self.key = '' | |
| 1098 | |
| 1099 # should we journal changes (default yes) | |
| 1100 self.do_journal = 1 | |
| 1101 | |
| 1102 # do the db-related init stuff | |
| 1103 db.addclass(self) | |
| 1104 | |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1105 self.auditors = {'create': [], 'set': [], 'retire': [], 'restore': []} |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1106 self.reactors = {'create': [], 'set': [], 'retire': [], 'restore': []} |
| 1165 | 1107 |
| 1108 def schema(self): | |
| 1109 ''' A dumpable version of the schema that we can store in the | |
| 1110 database | |
| 1111 ''' | |
| 1112 return (self.key, [(x, repr(y)) for x,y in self.properties.items()]) | |
| 1113 | |
| 1114 def enableJournalling(self): | |
| 1115 '''Turn journalling on for this class | |
| 1116 ''' | |
| 1117 self.do_journal = 1 | |
| 1118 | |
| 1119 def disableJournalling(self): | |
| 1120 '''Turn journalling off for this class | |
| 1121 ''' | |
| 1122 self.do_journal = 0 | |
| 1123 | |
| 1124 # Editing nodes: | |
| 1125 def create(self, **propvalues): | |
| 1126 ''' Create a new node of this class and return its id. | |
| 1127 | |
| 1128 The keyword arguments in 'propvalues' map property names to values. | |
| 1129 | |
| 1130 The values of arguments must be acceptable for the types of their | |
| 1131 corresponding properties or a TypeError is raised. | |
| 1132 | |
| 1133 If this class has a key property, it must be present and its value | |
| 1134 must not collide with other key strings or a ValueError is raised. | |
| 1135 | |
| 1136 Any other properties on this class that are missing from the | |
| 1137 'propvalues' dictionary are set to None. | |
| 1138 | |
| 1139 If an id in a link or multilink property does not refer to a valid | |
| 1140 node, an IndexError is raised. | |
| 1141 ''' | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1142 self.fireAuditors('create', None, propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1143 newid = self.create_inner(**propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1144 self.fireReactors('create', newid, None) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1145 return newid |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1146 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1147 def create_inner(self, **propvalues): |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
1148 ''' 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
|
1149 ''' |
| 1165 | 1150 if propvalues.has_key('id'): |
| 1151 raise KeyError, '"id" is reserved' | |
| 1152 | |
| 1153 if self.db.journaltag is None: | |
| 1154 raise DatabaseError, 'Database open read-only' | |
| 1155 | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1156 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
|
1157 propvalues.has_key('creation') or propvalues.has_key('activity'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1158 raise KeyError, '"creator", "actor", "creation" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1159 '"activity" are reserved' |
| 1165 | 1160 |
| 1161 # new node's id | |
| 1162 newid = self.db.newid(self.classname) | |
| 1163 | |
| 1164 # validate propvalues | |
| 1165 num_re = re.compile('^\d+$') | |
| 1166 for key, value in propvalues.items(): | |
| 1167 if key == self.key: | |
| 1168 try: | |
| 1169 self.lookup(value) | |
| 1170 except KeyError: | |
| 1171 pass | |
| 1172 else: | |
| 1173 raise ValueError, 'node with key "%s" exists'%value | |
| 1174 | |
| 1175 # try to handle this property | |
| 1176 try: | |
| 1177 prop = self.properties[key] | |
| 1178 except KeyError: | |
| 1179 raise KeyError, '"%s" has no property "%s"'%(self.classname, | |
| 1180 key) | |
| 1181 | |
| 1182 if value is not None and isinstance(prop, Link): | |
| 1183 if type(value) != type(''): | |
| 1184 raise ValueError, 'link value must be String' | |
| 1185 link_class = self.properties[key].classname | |
| 1186 # if it isn't a number, it's a key | |
| 1187 if not num_re.match(value): | |
| 1188 try: | |
| 1189 value = self.db.classes[link_class].lookup(value) | |
| 1190 except (TypeError, KeyError): | |
| 1191 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1192 key, value, link_class) | |
| 1193 elif not self.db.getclass(link_class).hasnode(value): | |
| 1194 raise IndexError, '%s has no node %s'%(link_class, value) | |
| 1195 | |
| 1196 # save off the value | |
| 1197 propvalues[key] = value | |
| 1198 | |
| 1199 # register the link with the newly linked node | |
| 1200 if self.do_journal and self.properties[key].do_journal: | |
| 1201 self.db.addjournal(link_class, value, 'link', | |
| 1202 (self.classname, newid, key)) | |
| 1203 | |
| 1204 elif isinstance(prop, Multilink): | |
| 1205 if type(value) != type([]): | |
| 1206 raise TypeError, 'new property "%s" not a list of ids'%key | |
| 1207 | |
| 1208 # clean up and validate the list of links | |
| 1209 link_class = self.properties[key].classname | |
| 1210 l = [] | |
| 1211 for entry in value: | |
| 1212 if type(entry) != type(''): | |
| 1213 raise ValueError, '"%s" multilink value (%r) '\ | |
| 1214 'must contain Strings'%(key, value) | |
| 1215 # if it isn't a number, it's a key | |
| 1216 if not num_re.match(entry): | |
| 1217 try: | |
| 1218 entry = self.db.classes[link_class].lookup(entry) | |
| 1219 except (TypeError, KeyError): | |
| 1220 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1221 key, entry, self.properties[key].classname) | |
| 1222 l.append(entry) | |
| 1223 value = l | |
| 1224 propvalues[key] = value | |
| 1225 | |
| 1226 # handle additions | |
| 1227 for nodeid in value: | |
| 1228 if not self.db.getclass(link_class).hasnode(nodeid): | |
| 1229 raise IndexError, '%s has no node %s'%(link_class, | |
| 1230 nodeid) | |
| 1231 # register the link with the newly linked node | |
| 1232 if self.do_journal and self.properties[key].do_journal: | |
| 1233 self.db.addjournal(link_class, nodeid, 'link', | |
| 1234 (self.classname, newid, key)) | |
| 1235 | |
| 1236 elif isinstance(prop, String): | |
|
1383
f19dde90e473
applied unicode patch
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1365
diff
changeset
|
1237 if type(value) != type('') and type(value) != type(u''): |
| 1165 | 1238 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
|
1239 self.db.indexer.add_text((self.classname, newid, key), value) |
| 1165 | 1240 |
| 1241 elif isinstance(prop, Password): | |
| 1242 if not isinstance(value, password.Password): | |
| 1243 raise TypeError, 'new property "%s" not a Password'%key | |
| 1244 | |
| 1245 elif isinstance(prop, Date): | |
| 1246 if value is not None and not isinstance(value, date.Date): | |
| 1247 raise TypeError, 'new property "%s" not a Date'%key | |
| 1248 | |
| 1249 elif isinstance(prop, Interval): | |
| 1250 if value is not None and not isinstance(value, date.Interval): | |
| 1251 raise TypeError, 'new property "%s" not an Interval'%key | |
| 1252 | |
| 1253 elif value is not None and isinstance(prop, Number): | |
| 1254 try: | |
| 1255 float(value) | |
| 1256 except ValueError: | |
| 1257 raise TypeError, 'new property "%s" not numeric'%key | |
| 1258 | |
| 1259 elif value is not None and isinstance(prop, Boolean): | |
| 1260 try: | |
| 1261 int(value) | |
| 1262 except ValueError: | |
| 1263 raise TypeError, 'new property "%s" not boolean'%key | |
| 1264 | |
| 1265 # make sure there's data where there needs to be | |
| 1266 for key, prop in self.properties.items(): | |
| 1267 if propvalues.has_key(key): | |
| 1268 continue | |
| 1269 if key == self.key: | |
| 1270 raise ValueError, 'key property "%s" is required'%key | |
| 1271 if isinstance(prop, Multilink): | |
| 1272 propvalues[key] = [] | |
| 1273 else: | |
| 1274 propvalues[key] = None | |
| 1275 | |
| 1276 # done | |
| 1277 self.db.addnode(self.classname, newid, propvalues) | |
| 1278 if self.do_journal: | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1279 self.db.addjournal(self.classname, newid, 'create', {}) |
| 1165 | 1280 |
| 1281 return newid | |
| 1282 | |
| 1283 def export_list(self, propnames, nodeid): | |
| 1284 ''' Export a node - generate a list of CSV-able data in the order | |
| 1285 specified by propnames for the given node. | |
| 1286 ''' | |
| 1287 properties = self.getprops() | |
| 1288 l = [] | |
| 1289 for prop in propnames: | |
| 1290 proptype = properties[prop] | |
| 1291 value = self.get(nodeid, prop) | |
| 1292 # "marshal" data where needed | |
| 1293 if value is None: | |
| 1294 pass | |
| 1295 elif isinstance(proptype, hyperdb.Date): | |
| 1296 value = value.get_tuple() | |
| 1297 elif isinstance(proptype, hyperdb.Interval): | |
| 1298 value = value.get_tuple() | |
| 1299 elif isinstance(proptype, hyperdb.Password): | |
| 1300 value = str(value) | |
| 1301 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
|
1302 l.append(repr(self.is_retired(nodeid))) |
| 1165 | 1303 return l |
| 1304 | |
| 1305 def import_list(self, propnames, proplist): | |
| 1306 ''' Import a node - all information including "id" is present and | |
| 1307 should not be sanity checked. Triggers are not triggered. The | |
| 1308 journal should be initialised using the "creator" and "created" | |
| 1309 information. | |
| 1310 | |
| 1311 Return the nodeid of the node imported. | |
| 1312 ''' | |
| 1313 if self.db.journaltag is None: | |
| 1314 raise DatabaseError, 'Database open read-only' | |
| 1315 properties = self.getprops() | |
| 1316 | |
| 1317 # make the new node's property map | |
| 1318 d = {} | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1319 retire = 0 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1320 newid = None |
| 1165 | 1321 for i in range(len(propnames)): |
| 1322 # Use eval to reverse the repr() used to output the CSV | |
| 1323 value = eval(proplist[i]) | |
| 1324 | |
| 1325 # Figure the property for this column | |
| 1326 propname = propnames[i] | |
| 1327 | |
| 1328 # "unmarshal" where necessary | |
| 1329 if propname == 'id': | |
| 1330 newid = value | |
| 1331 continue | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1332 elif propname == 'is retired': |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1333 # is the item retired? |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1334 if int(value): |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1335 retire = 1 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1336 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
|
1337 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
|
1338 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
|
1339 continue |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1340 |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1341 prop = properties[propname] |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1342 if value is None: |
| 1165 | 1343 # don't set Nones |
| 1344 continue | |
| 1345 elif isinstance(prop, hyperdb.Date): | |
| 1346 value = date.Date(value) | |
| 1347 elif isinstance(prop, hyperdb.Interval): | |
| 1348 value = date.Interval(value) | |
| 1349 elif isinstance(prop, hyperdb.Password): | |
| 1350 pwd = password.Password() | |
| 1351 pwd.unpack(value) | |
| 1352 value = pwd | |
| 1353 d[propname] = value | |
| 1354 | |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1355 # get a new id if necessary |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1356 if newid is None: |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1357 newid = self.db.newid(self.classname) |
|
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1358 |
|
1920
f9316d2cd5ba
Fixed retirement of items in rdbms imports [SF#841355]
Richard Jones <richard@users.sourceforge.net>
parents:
1912
diff
changeset
|
1359 # 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
|
1360 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
|
1361 |
|
1476
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1362 # retire? |
|
1496
e6ac4e074acb
relaxed CVS importing (feature [SF#693277])
Richard Jones <richard@users.sourceforge.net>
parents:
1492
diff
changeset
|
1363 if retire: |
|
1476
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1364 # 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
|
1365 # conversion (hello, sqlite) |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1366 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
|
1367 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
|
1368 if __debug__: |
|
5a01e90b7dc9
fixed export/import of retired nodes [SF#685273]
Richard Jones <richard@users.sourceforge.net>
parents:
1467
diff
changeset
|
1369 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
|
1370 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
|
1371 |
| 1165 | 1372 # extract the extraneous journalling gumpf and nuke it |
| 1373 if d.has_key('creator'): | |
| 1374 creator = d['creator'] | |
| 1375 del d['creator'] | |
|
1187
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1376 else: |
|
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1377 creator = None |
| 1165 | 1378 if d.has_key('creation'): |
| 1379 creation = d['creation'] | |
| 1380 del d['creation'] | |
|
1187
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1381 else: |
|
84e40c9bcd99
import fixes
Richard Jones <richard@users.sourceforge.net>
parents:
1185
diff
changeset
|
1382 creation = None |
| 1165 | 1383 if d.has_key('activity'): |
| 1384 del d['activity'] | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1385 if d.has_key('actor'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1386 del d['actor'] |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1387 self.db.addjournal(self.classname, newid, 'create', {}, creator, |
| 1165 | 1388 creation) |
| 1389 return newid | |
| 1390 | |
| 1391 _marker = [] | |
| 1392 def get(self, nodeid, propname, default=_marker, cache=1): | |
| 1393 '''Get the value of a property on an existing node of this class. | |
| 1394 | |
| 1395 'nodeid' must be the id of an existing node of this class or an | |
| 1396 IndexError is raised. 'propname' must be the name of a property | |
| 1397 of this class or a KeyError is raised. | |
| 1398 | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
1399 'cache' exists for backwards compatibility, and is not used. |
| 1165 | 1400 ''' |
| 1401 if propname == 'id': | |
| 1402 return nodeid | |
| 1403 | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1404 # 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
|
1405 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
|
1406 |
| 1165 | 1407 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
|
1408 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
|
1409 return d['creation'] |
| 1165 | 1410 else: |
| 1411 return date.Date() | |
| 1412 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
|
1413 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
|
1414 return d['activity'] |
| 1165 | 1415 else: |
| 1416 return date.Date() | |
| 1417 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
|
1418 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
|
1419 return d['creator'] |
| 1165 | 1420 else: |
|
1800
a3b1b1dcf639
Use getuid(), not figure_curuserid()
Johannes Gijsbers <jlgijsbers@users.sourceforge.net>
parents:
1794
diff
changeset
|
1421 return self.db.getuid() |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1422 if propname == 'actor': |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1423 if d.has_key('actor'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1424 return d['actor'] |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1425 else: |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1426 return self.db.getuid() |
| 1165 | 1427 |
| 1428 # get the property (raises KeyErorr if invalid) | |
| 1429 prop = self.properties[propname] | |
| 1430 | |
| 1431 if not d.has_key(propname): | |
| 1432 if default is self._marker: | |
| 1433 if isinstance(prop, Multilink): | |
| 1434 return [] | |
| 1435 else: | |
| 1436 return None | |
| 1437 else: | |
| 1438 return default | |
| 1439 | |
| 1440 # don't pass our list to other code | |
| 1441 if isinstance(prop, Multilink): | |
| 1442 return d[propname][:] | |
| 1443 | |
| 1444 return d[propname] | |
| 1445 | |
| 1446 def set(self, nodeid, **propvalues): | |
| 1447 '''Modify a property on an existing node of this class. | |
| 1448 | |
| 1449 'nodeid' must be the id of an existing node of this class or an | |
| 1450 IndexError is raised. | |
| 1451 | |
| 1452 Each key in 'propvalues' must be the name of a property of this | |
| 1453 class or a KeyError is raised. | |
| 1454 | |
| 1455 All values in 'propvalues' must be acceptable types for their | |
| 1456 corresponding properties or a TypeError is raised. | |
| 1457 | |
| 1458 If the value of the key property is set, it must not collide with | |
| 1459 other key strings or a ValueError is raised. | |
| 1460 | |
| 1461 If the value of a Link or Multilink property contains an invalid | |
| 1462 node id, a ValueError is raised. | |
| 1463 ''' | |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1464 self.fireAuditors('set', nodeid, propvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1465 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
|
1466 propvalues = self.set_inner(nodeid, **propvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1467 self.fireReactors('set', nodeid, oldvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1468 return propvalues |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1469 |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1470 def set_inner(self, nodeid, **propvalues): |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1471 ''' 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
|
1472 ''' |
| 1165 | 1473 if not propvalues: |
| 1474 return propvalues | |
| 1475 | |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1476 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
|
1477 propvalues.has_key('actor') or propvalues.has_key('activity'): |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1478 raise KeyError, '"creation", "creator", "actor" and '\ |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
1479 '"activity" are reserved' |
| 1165 | 1480 |
| 1481 if propvalues.has_key('id'): | |
| 1482 raise KeyError, '"id" is reserved' | |
| 1483 | |
| 1484 if self.db.journaltag is None: | |
| 1485 raise DatabaseError, 'Database open read-only' | |
| 1486 | |
| 1487 node = self.db.getnode(self.classname, nodeid) | |
| 1488 if self.is_retired(nodeid): | |
| 1489 raise IndexError, 'Requested item is retired' | |
| 1490 num_re = re.compile('^\d+$') | |
| 1491 | |
| 1492 # if the journal value is to be different, store it in here | |
| 1493 journalvalues = {} | |
| 1494 | |
| 1495 # remember the add/remove stuff for multilinks, making it easier | |
| 1496 # for the Database layer to do its stuff | |
| 1497 multilink_changes = {} | |
| 1498 | |
| 1499 for propname, value in propvalues.items(): | |
| 1500 # check to make sure we're not duplicating an existing key | |
| 1501 if propname == self.key and node[propname] != value: | |
| 1502 try: | |
| 1503 self.lookup(value) | |
| 1504 except KeyError: | |
| 1505 pass | |
| 1506 else: | |
| 1507 raise ValueError, 'node with key "%s" exists'%value | |
| 1508 | |
| 1509 # this will raise the KeyError if the property isn't valid | |
| 1510 # ... we don't use getprops() here because we only care about | |
| 1511 # the writeable properties. | |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1512 try: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1513 prop = self.properties[propname] |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1514 except KeyError: |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1515 raise KeyError, '"%s" has no property named "%s"'%( |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1516 self.classname, propname) |
| 1165 | 1517 |
| 1518 # if the value's the same as the existing value, no sense in | |
| 1519 # doing anything | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1520 current = node.get(propname, None) |
|
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1521 if value == current: |
| 1165 | 1522 del propvalues[propname] |
| 1523 continue | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1524 journalvalues[propname] = current |
| 1165 | 1525 |
| 1526 # do stuff based on the prop type | |
| 1527 if isinstance(prop, Link): | |
| 1528 link_class = prop.classname | |
| 1529 # if it isn't a number, it's a key | |
| 1530 if value is not None and not isinstance(value, type('')): | |
| 1531 raise ValueError, 'property "%s" link value be a string'%( | |
| 1532 propname) | |
| 1533 if isinstance(value, type('')) and not num_re.match(value): | |
| 1534 try: | |
| 1535 value = self.db.classes[link_class].lookup(value) | |
| 1536 except (TypeError, KeyError): | |
| 1537 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1538 propname, value, prop.classname) | |
| 1539 | |
| 1540 if (value is not None and | |
| 1541 not self.db.getclass(link_class).hasnode(value)): | |
| 1542 raise IndexError, '%s has no node %s'%(link_class, value) | |
| 1543 | |
| 1544 if self.do_journal and prop.do_journal: | |
| 1545 # register the unlink with the old linked node | |
| 1546 if node[propname] is not None: | |
| 1547 self.db.addjournal(link_class, node[propname], 'unlink', | |
| 1548 (self.classname, nodeid, propname)) | |
| 1549 | |
| 1550 # register the link with the newly linked node | |
| 1551 if value is not None: | |
| 1552 self.db.addjournal(link_class, value, 'link', | |
| 1553 (self.classname, nodeid, propname)) | |
| 1554 | |
| 1555 elif isinstance(prop, Multilink): | |
| 1556 if type(value) != type([]): | |
| 1557 raise TypeError, 'new property "%s" not a list of'\ | |
| 1558 ' ids'%propname | |
| 1559 link_class = self.properties[propname].classname | |
| 1560 l = [] | |
| 1561 for entry in value: | |
| 1562 # if it isn't a number, it's a key | |
| 1563 if type(entry) != type(''): | |
| 1564 raise ValueError, 'new property "%s" link value ' \ | |
| 1565 'must be a string'%propname | |
| 1566 if not num_re.match(entry): | |
| 1567 try: | |
| 1568 entry = self.db.classes[link_class].lookup(entry) | |
| 1569 except (TypeError, KeyError): | |
| 1570 raise IndexError, 'new property "%s": %s not a %s'%( | |
| 1571 propname, entry, | |
| 1572 self.properties[propname].classname) | |
| 1573 l.append(entry) | |
| 1574 value = l | |
| 1575 propvalues[propname] = value | |
| 1576 | |
| 1577 # figure the journal entry for this property | |
| 1578 add = [] | |
| 1579 remove = [] | |
| 1580 | |
| 1581 # handle removals | |
| 1582 if node.has_key(propname): | |
| 1583 l = node[propname] | |
| 1584 else: | |
| 1585 l = [] | |
| 1586 for id in l[:]: | |
| 1587 if id in value: | |
| 1588 continue | |
| 1589 # register the unlink with the old linked node | |
| 1590 if self.do_journal and self.properties[propname].do_journal: | |
| 1591 self.db.addjournal(link_class, id, 'unlink', | |
| 1592 (self.classname, nodeid, propname)) | |
| 1593 l.remove(id) | |
| 1594 remove.append(id) | |
| 1595 | |
| 1596 # handle additions | |
| 1597 for id in value: | |
| 1598 if not self.db.getclass(link_class).hasnode(id): | |
| 1599 raise IndexError, '%s has no node %s'%(link_class, id) | |
| 1600 if id in l: | |
| 1601 continue | |
| 1602 # register the link with the newly linked node | |
| 1603 if self.do_journal and self.properties[propname].do_journal: | |
| 1604 self.db.addjournal(link_class, id, 'link', | |
| 1605 (self.classname, nodeid, propname)) | |
| 1606 l.append(id) | |
| 1607 add.append(id) | |
| 1608 | |
| 1609 # figure the journal entry | |
| 1610 l = [] | |
| 1611 if add: | |
| 1612 l.append(('+', add)) | |
| 1613 if remove: | |
| 1614 l.append(('-', remove)) | |
| 1615 multilink_changes[propname] = (add, remove) | |
| 1616 if l: | |
| 1617 journalvalues[propname] = tuple(l) | |
| 1618 | |
| 1619 elif isinstance(prop, String): | |
|
1383
f19dde90e473
applied unicode patch
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1365
diff
changeset
|
1620 if value is not None and type(value) != type('') and type(value) != type(u''): |
| 1165 | 1621 raise TypeError, 'new property "%s" not a string'%propname |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
1622 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
|
1623 value) |
| 1165 | 1624 |
| 1625 elif isinstance(prop, Password): | |
| 1626 if not isinstance(value, password.Password): | |
| 1627 raise TypeError, 'new property "%s" not a Password'%propname | |
| 1628 propvalues[propname] = value | |
| 1629 | |
| 1630 elif value is not None and isinstance(prop, Date): | |
| 1631 if not isinstance(value, date.Date): | |
| 1632 raise TypeError, 'new property "%s" not a Date'% propname | |
| 1633 propvalues[propname] = value | |
| 1634 | |
| 1635 elif value is not None and isinstance(prop, Interval): | |
| 1636 if not isinstance(value, date.Interval): | |
| 1637 raise TypeError, 'new property "%s" not an '\ | |
| 1638 'Interval'%propname | |
| 1639 propvalues[propname] = value | |
| 1640 | |
| 1641 elif value is not None and isinstance(prop, Number): | |
| 1642 try: | |
| 1643 float(value) | |
| 1644 except ValueError: | |
| 1645 raise TypeError, 'new property "%s" not numeric'%propname | |
| 1646 | |
| 1647 elif value is not None and isinstance(prop, Boolean): | |
| 1648 try: | |
| 1649 int(value) | |
| 1650 except ValueError: | |
| 1651 raise TypeError, 'new property "%s" not boolean'%propname | |
| 1652 | |
| 1653 # nothing to do? | |
| 1654 if not propvalues: | |
| 1655 return propvalues | |
| 1656 | |
| 1657 # 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
|
1658 self.db.setnode(self.classname, nodeid, propvalues, multilink_changes) |
| 1165 | 1659 |
| 1660 if self.do_journal: | |
|
1304
61ad556cfc8d
working toward 0.5.2 release
Richard Jones <richard@users.sourceforge.net>
parents:
1295
diff
changeset
|
1661 self.db.addjournal(self.classname, nodeid, 'set', journalvalues) |
| 1165 | 1662 |
| 1663 return propvalues | |
| 1664 | |
| 1665 def retire(self, nodeid): | |
| 1666 '''Retire a node. | |
| 1667 | |
| 1668 The properties on the node remain available from the get() method, | |
| 1669 and the node's id is never reused. | |
| 1670 | |
| 1671 Retired nodes are not returned by the find(), list(), or lookup() | |
| 1672 methods, and other nodes may reuse the values of their key properties. | |
| 1673 ''' | |
| 1674 if self.db.journaltag is None: | |
| 1675 raise DatabaseError, 'Database open read-only' | |
| 1676 | |
|
1345
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1677 self.fireAuditors('retire', nodeid, None) |
|
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1678 |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1679 # use the arg for __retired__ to cope with any odd database type |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1680 # conversion (hello, sqlite) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1681 sql = 'update _%s set __retired__=%s where id=%s'%(self.classname, |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1682 self.db.arg, self.db.arg) |
| 1165 | 1683 if __debug__: |
| 1684 print >>hyperdb.DEBUG, 'retire', (self, sql, nodeid) | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1685 self.db.cursor.execute(sql, (1, nodeid)) |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1686 if self.do_journal: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1687 self.db.addjournal(self.classname, nodeid, 'retired', None) |
| 1165 | 1688 |
|
1345
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1689 self.fireReactors('retire', nodeid, None) |
|
618aa9c37d65
fire auditors and reactors in rdbms retire (thanks Sheila King)
Richard Jones <richard@users.sourceforge.net>
parents:
1333
diff
changeset
|
1690 |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1691 def restore(self, nodeid): |
|
1740
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
1692 '''Restore a retired node. |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1693 |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1694 Make node available for all operations like it was before retirement. |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1695 ''' |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1696 if self.db.journaltag is None: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1697 raise DatabaseError, 'Database open read-only' |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1698 |
|
1523
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1699 node = self.db.getnode(self.classname, nodeid) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1700 # check if key property was overrided |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1701 key = self.getkey() |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1702 try: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1703 id = self.lookup(node[key]) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1704 except KeyError: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1705 pass |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1706 else: |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1707 raise KeyError, "Key property (%s) of retired node clashes with \ |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1708 existing one (%s)" % (key, node[key]) |
|
63aa7be52d2c
checked to make sure that the restored item doesn't clash...
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1519
diff
changeset
|
1709 |
|
1519
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1710 self.fireAuditors('restore', nodeid, None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1711 # use the arg for __retired__ to cope with any odd database type |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1712 # conversion (hello, sqlite) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1713 sql = 'update _%s set __retired__=%s where id=%s'%(self.classname, |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1714 self.db.arg, self.db.arg) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1715 if __debug__: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1716 print >>hyperdb.DEBUG, 'restore', (self, sql, nodeid) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1717 self.db.cursor.execute(sql, (0, nodeid)) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1718 if self.do_journal: |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1719 self.db.addjournal(self.classname, nodeid, 'restored', None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1720 |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1721 self.fireReactors('restore', nodeid, None) |
|
6fede2aa6a12
added ability to restore retired nodes
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1515
diff
changeset
|
1722 |
| 1165 | 1723 def is_retired(self, nodeid): |
| 1724 '''Return true if the node is rerired | |
| 1725 ''' | |
| 1726 sql = 'select __retired__ from _%s where id=%s'%(self.classname, | |
| 1727 self.db.arg) | |
| 1728 if __debug__: | |
| 1729 print >>hyperdb.DEBUG, 'is_retired', (self, sql, nodeid) | |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1730 self.db.cursor.execute(sql, (nodeid,)) |
|
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1731 return int(self.db.sql_fetchone()[0]) |
| 1165 | 1732 |
| 1733 def destroy(self, nodeid): | |
| 1734 '''Destroy a node. | |
| 1735 | |
| 1736 WARNING: this method should never be used except in extremely rare | |
| 1737 situations where there could never be links to the node being | |
| 1738 deleted | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1739 |
| 1165 | 1740 WARNING: use retire() instead |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1741 |
| 1165 | 1742 WARNING: the properties of this node will not be available ever again |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1743 |
| 1165 | 1744 WARNING: really, use retire() instead |
| 1745 | |
| 1746 Well, I think that's enough warnings. This method exists mostly to | |
| 1747 support the session storage of the cgi interface. | |
| 1748 | |
| 1749 The node is completely removed from the hyperdb, including all journal | |
| 1750 entries. It will no longer be available, and will generally break code | |
| 1751 if there are any references to the node. | |
| 1752 ''' | |
| 1753 if self.db.journaltag is None: | |
| 1754 raise DatabaseError, 'Database open read-only' | |
| 1755 self.db.destroynode(self.classname, nodeid) | |
| 1756 | |
| 1757 def history(self, nodeid): | |
| 1758 '''Retrieve the journal of edits on a particular node. | |
| 1759 | |
| 1760 'nodeid' must be the id of an existing node of this class or an | |
| 1761 IndexError is raised. | |
| 1762 | |
| 1763 The returned list contains tuples of the form | |
| 1764 | |
|
1409
8dc60d87ab42
Fixed a backlog of bug reports, and worked on python 2.3 compatibility:
Richard Jones <richard@users.sourceforge.net>
parents:
1383
diff
changeset
|
1765 (nodeid, date, tag, action, params) |
| 1165 | 1766 |
| 1767 'date' is a Timestamp object specifying the time of the change and | |
| 1768 'tag' is the journaltag specified when the database was opened. | |
| 1769 ''' | |
| 1770 if not self.do_journal: | |
| 1771 raise ValueError, 'Journalling is disabled for this class' | |
| 1772 return self.db.getjournal(self.classname, nodeid) | |
| 1773 | |
| 1774 # Locating nodes: | |
| 1775 def hasnode(self, nodeid): | |
| 1776 '''Determine if the given nodeid actually exists | |
| 1777 ''' | |
| 1778 return self.db.hasnode(self.classname, nodeid) | |
| 1779 | |
| 1780 def setkey(self, propname): | |
| 1781 '''Select a String property of this class to be the key property. | |
| 1782 | |
| 1783 'propname' must be the name of a String property of this class or | |
| 1784 None, or a TypeError is raised. The values of the key property on | |
| 1785 all existing nodes must be unique or a ValueError is raised. | |
| 1786 ''' | |
|
1838
532f51a2c741
expand an XXX comment
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1836
diff
changeset
|
1787 # XXX create an index on the key prop column. We should also |
|
532f51a2c741
expand an XXX comment
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1836
diff
changeset
|
1788 # record that we've created this index in the schema somewhere. |
| 1165 | 1789 prop = self.getprops()[propname] |
| 1790 if not isinstance(prop, String): | |
| 1791 raise TypeError, 'key properties must be String' | |
| 1792 self.key = propname | |
| 1793 | |
| 1794 def getkey(self): | |
| 1795 '''Return the name of the key property for this class or None.''' | |
| 1796 return self.key | |
| 1797 | |
| 1798 def labelprop(self, default_to_id=0): | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1799 '''Return the property name for a label for the given node. |
| 1165 | 1800 |
| 1801 This method attempts to generate a consistent label for the node. | |
| 1802 It tries the following in order: | |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1803 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1804 1. key property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1805 2. "name" property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1806 3. "title" property |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1807 4. first property from the sorted property name list |
| 1165 | 1808 ''' |
| 1809 k = self.getkey() | |
| 1810 if k: | |
| 1811 return k | |
| 1812 props = self.getprops() | |
| 1813 if props.has_key('name'): | |
| 1814 return 'name' | |
| 1815 elif props.has_key('title'): | |
| 1816 return 'title' | |
| 1817 if default_to_id: | |
| 1818 return 'id' | |
| 1819 props = props.keys() | |
| 1820 props.sort() | |
| 1821 return props[0] | |
| 1822 | |
| 1823 def lookup(self, keyvalue): | |
| 1824 '''Locate a particular node by its key property and return its id. | |
| 1825 | |
| 1826 If this class has no key property, a TypeError is raised. If the | |
| 1827 'keyvalue' matches one of the values for the key property among | |
| 1828 the nodes in this class, the matching node's id is returned; | |
| 1829 otherwise a KeyError is raised. | |
| 1830 ''' | |
| 1831 if not self.key: | |
| 1832 raise TypeError, 'No key property set for class %s'%self.classname | |
| 1833 | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1834 # use the arg to handle any odd database type conversion (hello, |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1835 # sqlite) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1836 sql = "select id from _%s where _%s=%s and __retired__ <> %s"%( |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1837 self.classname, self.key, self.db.arg, self.db.arg) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1838 self.db.sql(sql, (keyvalue, 1)) |
| 1165 | 1839 |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1840 # see if there was a result that's not retired |
|
1203
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1841 row = self.db.sql_fetchone() |
|
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1842 if not row: |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1843 raise KeyError, 'No key (%s) value "%s" for "%s"'%(self.key, |
|
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
1844 keyvalue, self.classname) |
| 1165 | 1845 |
| 1846 # return the id | |
|
1203
735adcbfc665
fix to SQL lookup() and retirement
Richard Jones <richard@users.sourceforge.net>
parents:
1195
diff
changeset
|
1847 return row[0] |
| 1165 | 1848 |
| 1849 def find(self, **propspec): | |
| 1850 '''Get the ids of nodes in this class which link to the given nodes. | |
| 1851 | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1852 'propspec' consists of keyword args propname=nodeid or |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1853 propname={nodeid:1, } |
| 1165 | 1854 'propname' must be the name of a property in this class, or a |
|
1912
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1855 KeyError is raised. That property must be a Link or |
|
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1856 Multilink property, or a TypeError is raised. |
| 1165 | 1857 |
| 1858 Any node in this class whose 'propname' property links to any of the | |
| 1859 nodeids will be returned. Used by the full text indexing, which knows | |
| 1860 that "foo" occurs in msg1, msg3 and file7, so we have hits on these | |
| 1861 issues: | |
| 1862 | |
| 1863 db.issue.find(messages={'1':1,'3':1}, files={'7':1}) | |
| 1864 ''' | |
| 1865 if __debug__: | |
| 1866 print >>hyperdb.DEBUG, 'find', (self, propspec) | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1867 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1868 # shortcut |
| 1165 | 1869 if not propspec: |
| 1870 return [] | |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1871 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1872 # validate the args |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1873 props = self.getprops() |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1874 propspec = propspec.items() |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1875 for propname, nodeids in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1876 # check the prop is OK |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1877 prop = props[propname] |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1878 if not isinstance(prop, Link) and not isinstance(prop, Multilink): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1879 raise TypeError, "'%s' not a Link/Multilink property"%propname |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1880 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1881 # first, links |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1882 a = self.db.arg |
|
1986
910b39f8c5b8
use the upload-supplied content-type if there is one
Richard Jones <richard@users.sourceforge.net>
parents:
1951
diff
changeset
|
1883 allvalues = (1,) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1884 o = [] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1885 where = [] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1886 for prop, values in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1887 if not isinstance(props[prop], hyperdb.Link): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1888 continue |
|
1912
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1889 if type(values) is type({}) and len(values) == 1: |
|
2b0ab61db194
fixes for [SF#818339]
Richard Jones <richard@users.sourceforge.net>
parents:
1911
diff
changeset
|
1890 values = values.keys()[0] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1891 if type(values) is type(''): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1892 allvalues += (values,) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1893 where.append('_%s = %s'%(prop, a)) |
|
1563
e2a8ce4d2317
Class.find() may now find unset Links [SF#700620]
Richard Jones <richard@users.sourceforge.net>
parents:
1557
diff
changeset
|
1894 elif values is None: |
|
e2a8ce4d2317
Class.find() may now find unset Links [SF#700620]
Richard Jones <richard@users.sourceforge.net>
parents:
1557
diff
changeset
|
1895 where.append('_%s is NULL'%prop) |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1896 else: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1897 allvalues += tuple(values.keys()) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1898 where.append('_%s in (%s)'%(prop, ','.join([a]*len(values)))) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1899 tables = ['_%s'%self.classname] |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1900 if where: |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1901 o.append('(' + ' and '.join(where) + ')') |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1902 |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1903 # now multilinks |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1904 for prop, values in propspec: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1905 if not isinstance(props[prop], hyperdb.Multilink): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1906 continue |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1907 if not values: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1908 continue |
|
1222
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1909 if type(values) is type(''): |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1910 allvalues += (values,) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1911 s = a |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1912 else: |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1913 allvalues += tuple(values.keys()) |
|
bc3bc3248dd1
added Class.find() unit test, fixed implementations
Richard Jones <richard@users.sourceforge.net>
parents:
1212
diff
changeset
|
1914 s = ','.join([a]*len(values)) |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1915 tn = '%s_%s'%(self.classname, prop) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1916 tables.append(tn) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1917 o.append('(id=%s.nodeid and %s.linkid in (%s))'%(tn, tn, s)) |
|
1986
910b39f8c5b8
use the upload-supplied content-type if there is one
Richard Jones <richard@users.sourceforge.net>
parents:
1951
diff
changeset
|
1918 |
|
1988
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1919 if not o: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1920 return [] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1921 elif len(o) > 1: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1922 o = '(' + ' or '.join(['(%s)'%i for i in o]) + ')' |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1923 else: |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1924 o = o[0] |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1925 t = ', '.join(tables) |
|
5660b89f8903
more compliance testing, this time for find()
Richard Jones <richard@users.sourceforge.net>
parents:
1986
diff
changeset
|
1926 sql = 'select distinct(id) from %s where __retired__ <> %s and %s'%(t, a, o) |
|
1183
08a13a84ed43
Some speedups - both of the SQL backends can handle using only one cursor.
Richard Jones <richard@users.sourceforge.net>
parents:
1181
diff
changeset
|
1927 self.db.sql(sql, allvalues) |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1928 l = [x[0] for x in self.db.sql_fetchall()] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1929 if __debug__: |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1930 print >>hyperdb.DEBUG, 'find ... ', l |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1931 return l |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1932 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1933 def stringFind(self, **requirements): |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1934 '''Locate a particular node by matching a set of its String |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1935 properties in a caseless search. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1936 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1937 If the property is not a String property, a TypeError is raised. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1938 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1939 The return is a list of the id of all nodes that match. |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1940 ''' |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1941 where = [] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1942 args = [] |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1943 for propname in requirements.keys(): |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1944 prop = self.properties[propname] |
|
1951
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1945 if not isinstance(prop, String): |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1946 raise TypeError, "'%s' not a String property"%propname |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1947 where.append(propname) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1948 args.append(requirements[propname].lower()) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1949 |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1950 # generate the where clause |
|
1549
a53a7e197360
fixed rdbms email address lookup (case insensitivity)
Richard Jones <richard@users.sourceforge.net>
parents:
1539
diff
changeset
|
1951 s = ' and '.join(['lower(_%s)=%s'%(col, self.db.arg) for col in where]) |
|
1951
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1952 sql = 'select id from _%s where %s and __retired__=%s'%(self.classname, |
|
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1953 s, self.db.arg) |
|
767ff2a03eee
more unit tests to improve coverage (up from 85% to 88% for anydbm! :)
Richard Jones <richard@users.sourceforge.net>
parents:
1926
diff
changeset
|
1954 args.append(0) |
|
1195
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1955 self.db.sql(sql, tuple(args)) |
|
e0032f4ab334
added missing stringFind to sql backends
Richard Jones <richard@users.sourceforge.net>
parents:
1189
diff
changeset
|
1956 l = [x[0] for x in self.db.sql_fetchall()] |
| 1165 | 1957 if __debug__: |
| 1958 print >>hyperdb.DEBUG, 'find ... ', l | |
| 1959 return l | |
| 1960 | |
| 1961 def list(self): | |
| 1962 ''' Return a list of the ids of the active nodes in this class. | |
| 1963 ''' | |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1964 return self.getnodeids(retired=0) |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1965 |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1966 def getnodeids(self, retired=None): |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1967 ''' Retrieve all the ids of the nodes for a particular Class. |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1968 |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1969 Set retired=None to get all nodes. Otherwise it'll get all the |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1970 retired or non-retired nodes, depending on the flag. |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1971 ''' |
|
1707
3d627e34f18e
sqlite backend now passes all tests under 2.3.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
1599
diff
changeset
|
1972 # flip the sense of the 'retired' flag if we don't want all of them |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1973 if retired is not None: |
|
1719
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1974 if retired: |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1975 args = (0, ) |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1976 else: |
|
eeb167fb8faf
*** empty log message ***
Richard Jones <richard@users.sourceforge.net>
parents:
1707
diff
changeset
|
1977 args = (1, ) |
|
1539
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1978 sql = 'select id from _%s where __retired__ <> %s'%(self.classname, |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1979 self.db.arg) |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1980 else: |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1981 args = () |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1982 sql = 'select id from _%s'%self.classname |
|
1484
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1983 if __debug__: |
|
b3f2484babce
fixes to import/export
Richard Jones <richard@users.sourceforge.net>
parents:
1479
diff
changeset
|
1984 print >>hyperdb.DEBUG, 'getnodeids', (self, sql, retired) |
|
1539
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1985 self.db.cursor.execute(sql, args) |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1986 ids = [x[0] for x in self.db.cursor.fetchall()] |
|
800b5896e14a
fixed rdbms export - getnodeids in particular with NULL values
Richard Jones <richard@users.sourceforge.net>
parents:
1528
diff
changeset
|
1987 return ids |
| 1165 | 1988 |
|
1249
6c24a86a12ae
Fixes for SourceForge tracker bugs.
Richard Jones <richard@users.sourceforge.net>
parents:
1244
diff
changeset
|
1989 def filter(self, search_matches, filterspec, sort=(None,None), |
|
6c24a86a12ae
Fixes for SourceForge tracker bugs.
Richard Jones <richard@users.sourceforge.net>
parents:
1244
diff
changeset
|
1990 group=(None,None)): |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1991 '''Return a list of the ids of the active nodes in this class that |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1992 match the 'filter' spec, sorted by the group spec and then the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1993 sort spec |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1994 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1995 "filterspec" is {propname: value(s)} |
| 1165 | 1996 |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1997 "sort" and "group" are (dir, prop) where dir is '+', '-' or None |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
1998 and prop is a prop name or None |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
1999 |
|
2005
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2000 "search_matches" is {nodeid: marker} |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2001 |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2002 The filter must match all properties specificed - but if the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2003 property value to match is a list, any one of the values in the |
|
fc52d57c6c3e
documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents:
1988
diff
changeset
|
2004 list may match for that property to match. |
| 1165 | 2005 ''' |
|
1205
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2006 # just don't bother if the full-text search matched diddly |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2007 if search_matches == {}: |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2008 return [] |
|
0df08772f166
fix to SQL filtering
Richard Jones <richard@users.sourceforge.net>
parents:
1203
diff
changeset
|
2009 |
| 1165 | 2010 cn = self.classname |
| 2011 | |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2012 timezone = self.db.getUserTimezone() |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2013 |
| 1165 | 2014 # figure the WHERE clause from the filterspec |
| 2015 props = self.getprops() | |
| 2016 frum = ['_'+cn] | |
| 2017 where = [] | |
| 2018 args = [] | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2019 a = self.db.arg |
| 1165 | 2020 for k, v in filterspec.items(): |
| 2021 propclass = props[k] | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2022 # now do other where clause stuff |
| 1165 | 2023 if isinstance(propclass, Multilink): |
| 2024 tn = '%s_%s'%(cn, k) | |
|
1556
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2025 if v in ('-1', ['-1']): |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2026 # only match rows that have count(linkid)=0 in the |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2027 # corresponding multilink table) |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2028 where.append('id not in (select nodeid from %s)'%tn) |
|
9e89f5394f6c
handle myriad of argument types to filter()
Richard Jones <richard@users.sourceforge.net>
parents:
1555
diff
changeset
|
2029 elif isinstance(v, type([])): |
|
1555
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2030 frum.append(tn) |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2031 s = ','.join([a for x in v]) |
| 1165 | 2032 where.append('id=%s.nodeid and %s.linkid in (%s)'%(tn,tn,s)) |
| 2033 args = args + v | |
| 2034 else: | |
|
1555
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2035 frum.append(tn) |
|
948c7764d46c
implemented ability to search for multilink properties with no value (not in mk)
Richard Jones <richard@users.sourceforge.net>
parents:
1549
diff
changeset
|
2036 where.append('id=%s.nodeid and %s.linkid=%s'%(tn, tn, a)) |
| 1165 | 2037 args.append(v) |
|
1365
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2038 elif k == 'id': |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2039 if isinstance(v, type([])): |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2040 s = ','.join([a for x in v]) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2041 where.append('%s in (%s)'%(k, s)) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2042 args = args + v |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2043 else: |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2044 where.append('%s=%s'%(k, a)) |
|
4884fb0860f9
fixed rdbms searching by ID [SF#666615]
Richard Jones <richard@users.sourceforge.net>
parents:
1351
diff
changeset
|
2045 args.append(v) |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2046 elif isinstance(propclass, String): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2047 if not isinstance(v, type([])): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2048 v = [v] |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2049 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2050 # Quote the bits in the string that need it and then embed |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2051 # in a "substring" search. Note - need to quote the '%' so |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2052 # they make it through the python layer happily |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2053 v = ['%%'+self.db.sql_stringquote(s)+'%%' for s in v] |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2054 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2055 # now add to the where clause |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2056 where.append(' or '.join(["_%s LIKE '%s'"%(k, s) for s in v])) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2057 # note: args are embedded in the query string now |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2058 elif isinstance(propclass, Link): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2059 if isinstance(v, type([])): |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2060 if '-1' in v: |
|
1578
ba13c04814f0
don't modify filterspec passed in (bad Richard)
Richard Jones <richard@users.sourceforge.net>
parents:
1563
diff
changeset
|
2061 v = v[:] |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2062 v.remove('-1') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2063 xtra = ' or _%s is NULL'%k |
|
1173
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
2064 else: |
|
58f1a2c174ed
simple LRU cache for SQL databases
Richard Jones <richard@users.sourceforge.net>
parents:
1172
diff
changeset
|
2065 xtra = '' |
|
1295
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2066 if v: |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2067 s = ','.join([a for x in v]) |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2068 where.append('(_%s in (%s)%s)'%(k, s, xtra)) |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2069 args = args + v |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2070 else: |
|
9c3459cb8ab6
work-around for sqlite bug
Richard Jones <richard@users.sourceforge.net>
parents:
1252
diff
changeset
|
2071 where.append('_%s is NULL'%k) |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2072 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2073 if v == '-1': |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2074 v = None |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2075 where.append('_%s is NULL'%k) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2076 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2077 where.append('_%s=%s'%(k, a)) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2078 args.append(v) |
|
1351
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2079 elif isinstance(propclass, Date): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2080 if isinstance(v, type([])): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2081 s = ','.join([a for x in v]) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2082 where.append('_%s in (%s)'%(k, s)) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2083 args = args + [date.Date(x).serialise() for x in v] |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2084 else: |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2085 try: |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2086 # Try to filter on range of dates |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2087 date_rng = Range(v, date.Date, offset=timezone) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2088 if (date_rng.from_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2089 where.append('_%s >= %s'%(k, a)) |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2090 args.append(date_rng.from_value.serialise()) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2091 if (date_rng.to_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2092 where.append('_%s <= %s'%(k, a)) |
|
1499
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2093 args.append(date_rng.to_value.serialise()) |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2094 except ValueError: |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2095 # If range creation fails - ignore that search parameter |
|
8ee69708da0c
added support for searching on ranges of dates
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1496
diff
changeset
|
2096 pass |
|
1351
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2097 elif isinstance(propclass, Interval): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2098 if isinstance(v, type([])): |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2099 s = ','.join([a for x in v]) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2100 where.append('_%s in (%s)'%(k, s)) |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2101 args = args + [date.Interval(x).serialise() for x in v] |
|
d1bfb479e527
fixed searching on date / interval fields [SF#658157]
Richard Jones <richard@users.sourceforge.net>
parents:
1345
diff
changeset
|
2102 else: |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2103 try: |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2104 # Try to filter on range of intervals |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2105 date_rng = Range(v, date.Interval) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2106 if (date_rng.from_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2107 where.append('_%s >= %s'%(k, a)) |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2108 args.append(date_rng.from_value.serialise()) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2109 if (date_rng.to_value): |
|
1599
cc96bf971b33
extended date syntax to make range searches even more useful
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1596
diff
changeset
|
2110 where.append('_%s <= %s'%(k, a)) |
|
1596
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2111 args.append(date_rng.to_value.serialise()) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2112 except ValueError: |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2113 # If range creation fails - ignore that search parameter |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2114 pass |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2115 #where.append('_%s=%s'%(k, a)) |
|
33a0d94c7658
searching on ranges of intervals is implemented
Andrey Lebedev <kedder@users.sourceforge.net>
parents:
1578
diff
changeset
|
2116 #args.append(date.Interval(v).serialise()) |
| 1165 | 2117 else: |
| 2118 if isinstance(v, type([])): | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2119 s = ','.join([a for x in v]) |
| 1165 | 2120 where.append('_%s in (%s)'%(k, s)) |
| 2121 args = args + v | |
| 2122 else: | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2123 where.append('_%s=%s'%(k, a)) |
| 1165 | 2124 args.append(v) |
| 2125 | |
|
1740
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2126 # don't match retired nodes |
|
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2127 where.append('__retired__ <> 1') |
|
5ca448ff8052
don't have RDBMS backends list retired nodes [SF#767319]
Richard Jones <richard@users.sourceforge.net>
parents:
1719
diff
changeset
|
2128 |
| 1165 | 2129 # add results of full text search |
| 2130 if search_matches is not None: | |
| 2131 v = search_matches.keys() | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2132 s = ','.join([a for x in v]) |
| 1165 | 2133 where.append('id in (%s)'%s) |
| 2134 args = args + v | |
| 2135 | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2136 # "grouping" is just the first-order sorting in the SQL fetch |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2137 # can modify it...) |
| 1165 | 2138 orderby = [] |
| 2139 ordercols = [] | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2140 if group[0] is not None and group[1] is not None: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2141 if group[0] != '-': |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2142 orderby.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2143 ordercols.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2144 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2145 orderby.append('_'+group[1]+' desc') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2146 ordercols.append('_'+group[1]) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2147 |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2148 # now add in the sorting |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2149 group = '' |
| 1165 | 2150 if sort[0] is not None and sort[1] is not None: |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2151 direction, colname = sort |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2152 if direction != '-': |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2153 if colname == 'id': |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2154 orderby.append(colname) |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2155 else: |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2156 orderby.append('_'+colname) |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2157 ordercols.append('_'+colname) |
| 1165 | 2158 else: |
|
1174
8e318dfaf479
Verify contents of tracker module when the tracker is opened
Richard Jones <richard@users.sourceforge.net>
parents:
1173
diff
changeset
|
2159 if colname == 'id': |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2160 orderby.append(colname+' desc') |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2161 ordercols.append(colname) |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2162 else: |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2163 orderby.append('_'+colname+' desc') |
|
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2164 ordercols.append('_'+colname) |
| 1165 | 2165 |
| 2166 # construct the SQL | |
| 2167 frum = ','.join(frum) | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2168 if where: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2169 where = ' where ' + (' and '.join(where)) |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2170 else: |
|
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2171 where = '' |
| 1165 | 2172 cols = ['id'] |
| 2173 if orderby: | |
| 2174 cols = cols + ordercols | |
| 2175 order = ' order by %s'%(','.join(orderby)) | |
| 2176 else: | |
| 2177 order = '' | |
| 2178 cols = ','.join(cols) | |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2179 sql = 'select %s from %s %s%s%s'%(cols, frum, where, group, order) |
| 1165 | 2180 args = tuple(args) |
| 2181 if __debug__: | |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2182 print >>hyperdb.DEBUG, 'filter', (self, sql, args) |
|
1906
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2183 if args: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2184 self.db.cursor.execute(sql, args) |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2185 else: |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2186 # psycopg doesn't like empty args |
|
f255363e6d97
PostgreSQL backend lands.
Richard Jones <richard@users.sourceforge.net>
parents:
1873
diff
changeset
|
2187 self.db.cursor.execute(sql) |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
2188 l = self.db.sql_fetchall() |
| 1165 | 2189 |
|
1170
af104fa52746
Added some words to the installation doc about choosing backends.
Richard Jones <richard@users.sourceforge.net>
parents:
1168
diff
changeset
|
2190 # return the IDs (the first column) |
|
1911
f5c804379c85
fixed ZRoundup - mostly changes to classic template
Richard Jones <richard@users.sourceforge.net>
parents:
1906
diff
changeset
|
2191 return [row[0] for row in l] |
|
1168
94620e088e3a
fixes to the rdbms backends
Richard Jones <richard@users.sourceforge.net>
parents:
1165
diff
changeset
|
2192 |
| 1165 | 2193 def count(self): |
| 2194 '''Get the number of nodes in this class. | |
| 2195 | |
| 2196 If the returned integer is 'numnodes', the ids of all the nodes | |
| 2197 in this class run from 1 to numnodes, and numnodes+1 will be the | |
| 2198 id of the next node to be created in this class. | |
| 2199 ''' | |
| 2200 return self.db.countnodes(self.classname) | |
| 2201 | |
| 2202 # Manipulating properties: | |
| 2203 def getprops(self, protected=1): | |
| 2204 '''Return a dictionary mapping property names to property objects. | |
| 2205 If the "protected" flag is true, we include protected properties - | |
| 2206 those which may not be modified. | |
| 2207 ''' | |
| 2208 d = self.properties.copy() | |
| 2209 if protected: | |
| 2210 d['id'] = String() | |
| 2211 d['creation'] = hyperdb.Date() | |
| 2212 d['activity'] = hyperdb.Date() | |
|
1176
bd3b57859c37
On second thought, that last checkin was dumb.
Richard Jones <richard@users.sourceforge.net>
parents:
1175
diff
changeset
|
2213 d['creator'] = hyperdb.Link('user') |
|
2077
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
2214 d['actor'] = hyperdb.Link('user') |
| 1165 | 2215 return d |
| 2216 | |
| 2217 def addprop(self, **properties): | |
| 2218 '''Add properties to this class. | |
| 2219 | |
| 2220 The keyword arguments in 'properties' must map names to property | |
| 2221 objects, or a TypeError is raised. None of the keys in 'properties' | |
| 2222 may collide with the names of existing properties, or a ValueError | |
| 2223 is raised before any properties have been added. | |
| 2224 ''' | |
| 2225 for key in properties.keys(): | |
| 2226 if self.properties.has_key(key): | |
| 2227 raise ValueError, key | |
| 2228 self.properties.update(properties) | |
| 2229 | |
| 2230 def index(self, nodeid): | |
| 2231 '''Add (or refresh) the node to search indexes | |
| 2232 ''' | |
| 2233 # find all the String properties that have indexme | |
| 2234 for prop, propclass in self.getprops().items(): | |
| 2235 if isinstance(propclass, String) and propclass.indexme: | |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2236 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
|
2237 str(self.get(nodeid, prop))) |
| 1165 | 2238 |
| 2239 | |
| 2240 # | |
| 2241 # Detector interface | |
| 2242 # | |
| 2243 def audit(self, event, detector): | |
| 2244 '''Register a detector | |
| 2245 ''' | |
| 2246 l = self.auditors[event] | |
| 2247 if detector not in l: | |
| 2248 self.auditors[event].append(detector) | |
| 2249 | |
| 2250 def fireAuditors(self, action, nodeid, newvalues): | |
| 2251 '''Fire all registered auditors. | |
| 2252 ''' | |
| 2253 for audit in self.auditors[action]: | |
| 2254 audit(self.db, self, nodeid, newvalues) | |
| 2255 | |
| 2256 def react(self, event, detector): | |
| 2257 '''Register a detector | |
| 2258 ''' | |
| 2259 l = self.reactors[event] | |
| 2260 if detector not in l: | |
| 2261 self.reactors[event].append(detector) | |
| 2262 | |
| 2263 def fireReactors(self, action, nodeid, oldvalues): | |
| 2264 '''Fire all registered reactors. | |
| 2265 ''' | |
| 2266 for react in self.reactors[action]: | |
| 2267 react(self.db, self, nodeid, oldvalues) | |
| 2268 | |
|
1442
b42fa71754c9
don't attempt to create FileClass items if no content is supplied
Richard Jones <richard@users.sourceforge.net>
parents:
1431
diff
changeset
|
2269 class FileClass(Class, hyperdb.FileClass): |
| 1165 | 2270 '''This class defines a large chunk of data. To support this, it has a |
| 2271 mandatory String property "content" which is typically saved off | |
| 2272 externally to the hyperdb. | |
| 2273 | |
| 2274 The default MIME type of this data is defined by the | |
| 2275 "default_mime_type" class attribute, which may be overridden by each | |
| 2276 node if the class defines a "type" String property. | |
| 2277 ''' | |
| 2278 default_mime_type = 'text/plain' | |
| 2279 | |
| 2280 def create(self, **propvalues): | |
| 2281 ''' snaffle the file propvalue and store in a file | |
| 2282 ''' | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2283 # 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
|
2284 # 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
|
2285 self.fireAuditors('create', None, propvalues) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2286 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2287 # now remove the content property so it's not stored in the db |
| 1165 | 2288 content = propvalues['content'] |
| 2289 del propvalues['content'] | |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2290 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2291 # do the database create |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2292 newid = self.create_inner(**propvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2293 |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2294 # figure the mime type |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2295 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
|
2296 |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2297 # and index! |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2298 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
|
2299 mime_type) |
|
1431
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2300 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2301 # fire reactors |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2302 self.fireReactors('create', newid, None) |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2303 |
|
c70068162e64
Altered Class.create() and FileClass.create() methods...
Richard Jones <richard@users.sourceforge.net>
parents:
1417
diff
changeset
|
2304 # store off the content as a file |
| 1165 | 2305 self.db.storefile(self.classname, newid, None, content) |
| 2306 return newid | |
| 2307 | |
| 2308 def import_list(self, propnames, proplist): | |
| 2309 ''' Trap the "content" property... | |
| 2310 ''' | |
| 2311 # dupe this list so we don't affect others | |
| 2312 propnames = propnames[:] | |
| 2313 | |
| 2314 # extract the "content" property from the proplist | |
| 2315 i = propnames.index('content') | |
| 2316 content = eval(proplist[i]) | |
| 2317 del propnames[i] | |
| 2318 del proplist[i] | |
| 2319 | |
| 2320 # do the normal import | |
| 2321 newid = Class.import_list(self, propnames, proplist) | |
| 2322 | |
| 2323 # save off the "content" file | |
| 2324 self.db.storefile(self.classname, newid, None, content) | |
| 2325 return newid | |
| 2326 | |
| 2327 _marker = [] | |
| 2328 def get(self, nodeid, propname, default=_marker, cache=1): | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2329 ''' Trap the content propname and get it from the file |
|
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2330 |
|
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2331 'cache' exists for backwards compatibility, and is not used. |
| 1165 | 2332 ''' |
| 2333 poss_msg = 'Possibly a access right configuration problem.' | |
| 2334 if propname == 'content': | |
| 2335 try: | |
| 2336 return self.db.getfile(self.classname, nodeid, None) | |
| 2337 except IOError, (strerror): | |
| 2338 # BUG: by catching this we donot see an error in the log. | |
| 2339 return 'ERROR reading file: %s%s\n%s\n%s'%( | |
| 2340 self.classname, nodeid, poss_msg, strerror) | |
| 2341 if default is not self._marker: | |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2342 return Class.get(self, nodeid, propname, default) |
| 1165 | 2343 else: |
|
1780
d2801a2b0a77
Initial implementation (half-baked) at new Tracker instance.
Richard Jones <richard@users.sourceforge.net>
parents:
1751
diff
changeset
|
2344 return Class.get(self, nodeid, propname) |
| 1165 | 2345 |
| 2346 def getprops(self, protected=1): | |
| 2347 ''' In addition to the actual properties on the node, these methods | |
| 2348 provide the "content" property. If the "protected" flag is true, | |
| 2349 we include protected properties - those which may not be | |
| 2350 modified. | |
| 2351 ''' | |
| 2352 d = Class.getprops(self, protected=protected).copy() | |
| 2353 d['content'] = hyperdb.String() | |
| 2354 return d | |
| 2355 | |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2356 def set(self, itemid, **propvalues): |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2357 ''' 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
|
2358 ''' |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2359 self.fireAuditors('set', itemid, propvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2360 oldvalues = copy.deepcopy(self.db.getnode(self.classname, itemid)) |
| 1165 | 2361 |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2362 # 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
|
2363 content = None |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2364 if propvalues.has_key('content'): |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2365 content = propvalues['content'] |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2366 del propvalues['content'] |
| 1165 | 2367 |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2368 # do the database create |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2369 propvalues = self.set_inner(itemid, **propvalues) |
| 1165 | 2370 |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2371 # do content? |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2372 if content: |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2373 # store and index |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2374 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
|
2375 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
|
2376 if not mime_type: |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2377 mime_type = self.default_mime_type |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2378 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
|
2379 content, mime_type) |
| 1165 | 2380 |
|
2089
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2381 # fire reactors |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2382 self.fireReactors('set', itemid, oldvalues) |
|
93f03c6714d8
A few big changes in this commit:
Richard Jones <richard@users.sourceforge.net>
parents:
2082
diff
changeset
|
2383 return propvalues |
| 1165 | 2384 |
| 2385 # XXX deviation from spec - was called ItemClass | |
| 2386 class IssueClass(Class, roundupdb.IssueClass): | |
| 2387 # Overridden methods: | |
| 2388 def __init__(self, db, classname, **properties): | |
| 2389 '''The newly-created class automatically includes the "messages", | |
| 2390 "files", "nosy", and "superseder" properties. If the 'properties' | |
| 2391 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
|
2392 "creation", "creator", "activity" or "actor" property, a ValueError |
|
3e0961d6d44d
Added the "actor" property.
Richard Jones <richard@users.sourceforge.net>
parents:
2076
diff
changeset
|
2393 is raised. |
| 1165 | 2394 ''' |
| 2395 if not properties.has_key('title'): | |
| 2396 properties['title'] = hyperdb.String(indexme='yes') | |
| 2397 if not properties.has_key('messages'): | |
| 2398 properties['messages'] = hyperdb.Multilink("msg") | |
| 2399 if not properties.has_key('files'): | |
| 2400 properties['files'] = hyperdb.Multilink("file") | |
| 2401 if not properties.has_key('nosy'): | |
| 2402 # note: journalling is turned off as it really just wastes | |
| 2403 # space. this behaviour may be overridden in an instance | |
| 2404 properties['nosy'] = hyperdb.Multilink("user", do_journal="no") | |
| 2405 if not properties.has_key('superseder'): | |
| 2406 properties['superseder'] = hyperdb.Multilink(classname) | |
| 2407 Class.__init__(self, db, classname, **properties) | |
| 2408 |
