Changeset 232
- Timestamp:
- 07/20/06 22:31:17
- Files:
-
- trunk/storage/storemysql.py (modified) (10 diffs)
- trunk/storage/storesqlite.py (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/storage/storemysql.py
r231 r232 137 137 else: 138 138 typename = "INTEGER" 139 if isinstance(cls.sequencer, dejavu.UnitSequencerInteger):140 if key in cls.identifiers:141 typename += " AUTO_INCREMENT"142 139 return typename 143 140 … … 157 154 158 155 indexsetclass = MySQLIndexSet 156 157 def __setitem__(self, key, column): 158 t = self.table 159 160 dbtype = column.dbtype 161 if column.autoincrement: 162 dbtype += " AUTO_INCREMENT" 163 else: 164 default = column.default or "" 165 if default: 166 default = self.adaptertosql.coerce(default) 167 dbtype = "%s DEFAULT %s" % (dbtype, default) 168 169 t.db.execute("ALTER TABLE %s ADD COLUMN %s %s;" % 170 (t.qname, column.qname, dbtype)) 171 dict.__setitem__(self, key, column) 159 172 160 173 def _rename(self, oldcol, newcol): … … 203 216 204 217 fields = [] 218 incr_fields = [] 205 219 pk = [] 206 220 for colname, col in table.columns.iteritems(): … … 208 222 dbtype = col.dbtype 209 223 210 default = col.default or "" 211 if default: 212 default = " DEFAULT %s" % self.adaptertosql.coerce(default) 213 214 f = '%s %s%s' % (qname, dbtype, default) 215 fields.append(f) 224 if col.autoincrement: 225 dbtype += " AUTO_INCREMENT" 226 # INSERT INTO t (c) VALUES(0) doesn't work for some reason 227 if col.default > 1: 228 incr_fields.append(col) 229 else: 230 default = col.default or "" 231 if default: 232 default = self.adaptertosql.coerce(default) 233 dbtype = "%s DEFAULT %s" % (dbtype, default) 234 235 fields.append('%s %s' % (qname, dbtype)) 216 236 217 237 # See create_storage for the other half of this hack. 218 if col name in table.mysql_identifiers:238 if col.name in table.mysql_identifiers: 219 239 if dbtype.endswith('BLOB') or dbtype == 'TEXT': 220 # MySQL won't allow indexes on a BLOB field 221 # without a specific length.240 # MySQL won't allow indexes on a BLOB field without a 241 # specific index prefix length. We choose 255 just for fun. 222 242 qname = "%s(255)" % qname 223 243 pk.append(qname) 224 244 225 pk = ", ".join(pk)226 245 if pk: 227 pk = ", PRIMARY KEY (%s)" % pk246 pk = ", PRIMARY KEY (%s)" % ", ".join(pk) 228 247 229 248 self.execute('CREATE TABLE %s (%s%s);' % 230 249 (table.qname, ", ".join(fields), pk)) 231 250 232 seq = getattr(table, "mysql_sequencer", None) 233 if seq: 234 # Wow, what a hack. We have to INSERT a dummy row 235 # to set the autoincrement initial value, and we 236 # can't delete it until after the CREATE INDEX 237 # statements (or the counter will revert). 238 colname, initial = seq 251 if incr_fields: 252 # Wow, what a hack. We have to INSERT a dummy row to set the 253 # autoincrement initial value(s), and we can't delete it until 254 # after the CREATE INDEX statements (or the counter will revert). 255 fields = ", ".join([col.qname for col in incr_fields]) 256 values = ", ".join([str(col.default - 1) for col in incr_fields]) 239 257 self.execute("INSERT INTO %s (%s) VALUES (%s);" 240 % (table.qname, q(colname), initial - 1))258 % (table.qname, fields, values)) 241 259 242 260 for k, index in table.columns.indices.iteritems(): 243 261 dbtype = table.columns[k].dbtype 244 262 if dbtype.endswith('BLOB') or dbtype == 'TEXT': 245 # MySQL won't allow indexes on a BLOB field 246 # without a specific length.263 # MySQL won't allow indexes on a BLOB field without a 264 # specific index prefix length. We choose 255 just for fun. 247 265 self.execute('CREATE INDEX %s ON %s (%s(255));' % 248 266 (index.qname, table.qname, q(index.colname))) … … 251 269 (index.qname, table.qname, q(index.colname))) 252 270 253 if seq:271 if incr_fields: 254 272 self.execute("DELETE FROM %s" % table.qname) 255 273 … … 295 313 c.default = self.python_type(dbtype)(row[4]) 296 314 297 if row[5]:298 # Usually auto_increment299 dbtype += " " + row[5]315 if "auto_increment" in row[5].lower(): 316 c.autoincrement = True 317 300 318 c.dbtype = dbtype 301 319 … … 324 342 """Return a Python type which can store values of the given dbtype.""" 325 343 dbtype = dbtype.upper() 326 dbtype = dbtype.replace(" AUTO_INCREMENT", "")327 344 parenpos = dbtype.find("(") 328 345 if parenpos > -1: … … 435 452 for key in cls.properties: 436 453 col = t.columns[key] 437 if col. dbtype.endswith("AUTO_INCREMENT"):454 if col.autoincrement: 438 455 # Skip this field, since we're using a sequencer 439 456 continue … … 462 479 fields = [] 463 480 for key in cls.properties: 464 dbtype = self.typeAdapter.coerce(cls, key)465 466 col = self.db.make_column(cls.__name__, key, dbtype)467 468 prop = cls.property(key)469 col.default = prop.default470 col.hints = prop.hints.copy()471 472 481 # Use the superclass call to avoid ALTER TABLE. 473 dict.__setitem__(t.columns, key, col)482 dict.__setitem__(t.columns, key, self._make_column(cls, key)) 474 483 475 484 if key in indices: … … 479 488 480 489 # Hack to get PRIMARY KEY right. See MySQLTableSet.__setitem__ 481 t.mysql_identifiers = cls.identifiers 482 483 # Hack to get AUTO_INCREMENT right where initial > 1. 484 # See MySQLTableSet.__setitem__ 485 if isinstance(cls.sequencer, dejavu.UnitSequencerInteger): 486 i = cls.sequencer.initial 487 if i > 1: 488 t.mysql_sequencer = (t.columns[cls.identifiers[0]].name, i) 490 t.mysql_identifiers = [t.columns[i].name for i in cls.identifiers] 489 491 490 492 # Attach to self.db, which should call CREATE TABLE. 491 493 self.db[cls.__name__] = t 492 494 495 def _make_column(self, cls, key): 496 dbtype = self.typeAdapter.coerce(cls, key) 497 col = self.db.make_column(cls.__name__, key, dbtype) 498 prop = getattr(cls, key) 499 col.default = prop.default 500 col.hints = prop.hints.copy() 501 502 if key in cls.identifiers: 503 if isinstance(cls.sequencer, dejavu.UnitSequencerInteger): 504 col.autoincrement = True 505 col.default = cls.sequencer.initial 506 return col trunk/storage/storesqlite.py
r231 r232 166 166 def coerce(self, cls, key): 167 167 """coerce(cls, key) -> SQL typename for valuetype.""" 168 if _autoincrement_support:169 prop = cls.property(key)170 if prop.type is int and key in cls.identifiers:171 if isinstance(cls.sequencer, dejavu.UnitSequencerInteger):172 return "INTEGER PRIMARY KEY AUTOINCREMENT"173 174 168 if self.db.typeless: 175 169 # SQLite can be 'typeless' (but we lose the type introspection) … … 213 207 def __setitem__(self, key, column): 214 208 t = self.table 209 if key in self: 210 del self[key] 215 211 216 212 if _add_column_support: 213 dbtype = column.dbtype 214 if column.autoincrement: 215 dbtype = "INTEGER PRIMARY KEY AUTOINCREMENT" 216 else: 217 default = column.default or "" 218 if not isinstance(default, str): 219 default = t.db.adaptertosql.coerce(default) 220 if default: 221 dbtype += " DEFAULT %s" % default 222 217 223 t.db.execute("ALTER TABLE %s ADD COLUMN %s %s;" % 218 (t.qname, column.qname, column.dbtype))224 (t.qname, column.qname, dbtype)) 219 225 dict.__setitem__(self, key, column) 220 226 else: … … 250 256 # Drop the intermediate table. 251 257 t.db[temptable.name] 258 259 if column.autoincrement: 260 self._set_initials(t.name, col.default) 252 261 253 262 def __delitem__(self, key): … … 399 408 400 409 return str 410 411 def _set_initials(self, tablename, initial): 412 # SQLite AUTOINCREMENT columns start at 1 by default. 413 # Manhandle the special SQLITE_SEQUENCE table to include 414 # the value of sequencer.initial - 1. 415 prev = initial - 1 416 data, coldefs = self.fetch("SELECT * FROM SQLITE_SEQUENCE " 417 "WHERE name = '%s'" % tablename) 418 if data: 419 self.execute("UPDATE SQLITE_SEQUENCE SET seq = %s " 420 "WHERE name = '%s'" % (prev, tablename)) 421 else: 422 self.execute("INSERT INTO SQLITE_SEQUENCE (seq, name) " 423 "VALUES (%s, '%s')" % (prev, tablename)) 424 425 def __setitem__(self, key, table): 426 if key in self: 427 del self[key] 428 429 fields = [] 430 autoincr_initial = None 431 for column in table.columns.itervalues(): 432 dbtype = column.dbtype 433 if column.autoincrement: 434 dbtype = "INTEGER PRIMARY KEY AUTOINCREMENT" 435 autoincr_initial = column.default 436 else: 437 default = column.default or "" 438 if not isinstance(default, str): 439 default = table.db.adaptertosql.coerce(default) 440 if default: 441 dbtype = " DEFAULT %s" % default 442 fields.append('%s %s' % (column.qname, dbtype)) 443 444 self.execute('CREATE TABLE %s (%s);' % 445 (table.qname, ", ".join(fields))) 446 447 for index in table.columns.indices.itervalues(): 448 self.execute('CREATE INDEX %s ON %s (%s);' % 449 (index.qname, table.qname, 450 self.quote(index.colname))) 451 452 if autoincr_initial: 453 self._set_initials(table.name, autoincr_initial) 454 455 dict.__setitem__(self, key, table) 401 456 402 457 def _rename(self, oldtable, newtable): … … 562 617 values = [] 563 618 for key in cls.properties: 564 if "AUTOINCREMENT" in self.typeAdapter.coerce(cls, key): 619 col = t.columns[key] 620 if col.autoincrement: 565 621 # Skip this field, since we're using AUTOINCREMENT 566 622 continue 567 623 val = self.db.adaptertosql.coerce(getattr(unit, key)) 568 fields.append( t.columns[key].qname)624 fields.append(col.qname) 569 625 values.append(val) 570 626 … … 583 639 # Schemas # 584 640 585 def create_storage(self, cls): 586 """Create storage for the given class.""" 587 db.StorageManagerDB.create_storage(self, cls) 588 589 typename = self.typeAdapter.coerce 590 591 for key in cls.properties: 592 if "AUTOINCREMENT" in typename(cls, key): 593 # SQLite AUTOINCREMENT columns start at 1 by default. 594 # Manhandle the special SQLITE_SEQUENCE table to include 595 # the value of sequencer.initial - 1. 596 prev = cls.sequencer.initial - 1 597 tablename = self.db[cls.__name__].name 598 d, c = self.db.fetch("SELECT * FROM SQLITE_SEQUENCE " 599 "WHERE name = '%s'" % tablename) 600 if d: 601 self.db.execute("UPDATE SQLITE_SEQUENCE SET seq = %s " 602 "WHERE name = '%s'" % (prev, tablename)) 603 else: 604 self.db.execute("INSERT INTO SQLITE_SEQUENCE (seq, name) " 605 "VALUES (%s, '%s')" % (prev, tablename)) 606 641 def _make_column(self, cls, key): 642 col = db.StorageManagerDB._make_column(self, cls, key) 643 if (_autoincrement_support and key in cls.identifiers and 644 isinstance(cls.sequencer, dejavu.UnitSequencerInteger)): 645 col.autoincrement = True 646 col.default = cls.sequencer.initial 647 return col 648
