Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

Changeset 193

Show
Ignore:
Timestamp:
03/15/06 15:45:27
Author:
fumanchu
Message:

Fix for #51 (remove expanded columns). If anyone objects, this can be reinstated with very little work.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doc/storage.html

    r192 r193  
    219219        The value should be the full dotted package name of the class you 
    220220        wish to use.</td> 
    221 </tr> 
    222 <tr> 
    223     <td>Expanded Columns</td> 
    224     <td><tt>Animal.PreviousZoos:int, Exhibit.Animals:int</tt></td> 
    225     <td>Optional. A comma-separated list of UnitClass.Property:subtype 
    226         strings. Each such property should be of .type list or tuple. 
    227         Usually, lists are pickled for storage in a normal database 
    228         field. Properties listed in <tt>Expanded Columns</tt> will 
    229         be stored each in their own table. The "subtype" portion tells 
    230         the Storage Manager the type of each value in the list. This is 
    231         mostly here to support a legacy database which already normalizes 
    232         the values in this way; for new projects, we recommend using the 
    233         default pickle method, which is much faster and more manageable.</td> 
    234221</tr> 
    235222</table> 
  • trunk/storage/db.py

    r192 r193  
    295295        # self.encoding. 
    296296        value = pickle.dumps(value) 
    297         return self.coerce_str(value, skip_encoding=True) 
     297        value = self.coerce_str(value, skip_encoding=True) 
     298        return value 
    298299     
    299300    coerce_dict = do_pickle 
     
    832833        self.prefix = allOptions.get('Prefix', "djv") 
    833834        self.reserve_lock = threading.Lock() 
    834          
    835         ec = {} 
    836         for prop in allOptions.get('Expanded Columns', '').split(","): 
    837             if prop: 
    838                 cls, type = [x.strip() for x in prop.split(":", 1)] 
    839                 lastdot = cls.rfind(".") 
    840                 clsname, key = cls[:lastdot], cls[lastdot + 1:] 
    841                 ec[(clsname, key)] = type 
    842         self.expanded_columns = ec 
    843835     
    844836    #                               Naming                               # 
     
    10281020            # Get specs on properties. Put the identifier properties 
    10291021            # first, in case other fields depend upon them. 
    1030             # See load_expanded, for example. 
    10311022            props = [] 
    10321023            idnames = list(cls.identifiers) 
    10331024            for key in idnames + [x for x in cls.properties if x not in idnames]: 
    10341025                index, ftype = columns[self.column_name(clsname, key, quoted=False)] 
    1035                 subtype = self.expanded_columns.get((clsname, key)) 
    1036                 props.append((key, index, ftype, subtype)) 
     1026                props.append((key, index, ftype)) 
    10371027             
    10381028            consume = self.fromAdapter.consume 
    10391029            for row in data: 
    10401030                unit = cls() 
    1041                 for key, index, ftype, subtype in props: 
     1031                for key, index, ftype in props: 
    10421032                    value = row[index] 
    1043                     if subtype: 
    1044                         self.load_expanded(unit, key, subtype) 
    1045                     else: 
    1046                         consume(unit, key, value, ftype) 
     1033                    consume(unit, key, value, ftype) 
    10471034                 
    10481035                # If our SQL is imperfect, don't yield it to the 
     
    11041091        values = [] 
    11051092        for key in cls.properties: 
    1106             subtype = self.expanded_columns.get((clsname, key)) 
    1107             if subtype: 
    1108                 self.save_expanded(unit, key, subtype) 
    1109             else: 
    1110                 val = self.toAdapter.coerce(getattr(unit, key)) 
    1111                 fields.append(self.column_name(clsname, key)) 
    1112                 values.append(val) 
     1093            val = self.toAdapter.coerce(getattr(unit, key)) 
     1094            fields.append(self.column_name(clsname, key)) 
     1095            values.append(val) 
    11131096         
    11141097        fields = ", ".join(fields) 
     
    11351118            for key in cls.properties: 
    11361119                if key not in cls.identifiers: 
    1137                     subtype = self.expanded_columns.get((clsname, key)) 
    1138                     if subtype: 
    1139                         self.save_expanded(unit, key, subtype) 
    1140                     else: 
    1141                         val = self.toAdapter.coerce(getattr(unit, key)) 
    1142                         parms.append('%s = %s' % 
    1143                                      (self.column_name(clsname, key), val)) 
     1120                    val = self.toAdapter.coerce(getattr(unit, key)) 
     1121                    parms.append('%s = %s' % 
     1122                                 (self.column_name(clsname, key), val)) 
    11441123             
    11451124            if parms: 
     
    11491128                self.execute(sql) 
    11501129            unit.cleanse() 
    1151      
    1152     def save_expanded(self, unit, key, subtype, conn=None): 
    1153         """save_expanded(unit, key, subtype). Save list in separate table.""" 
    1154         unitcls = unit.__class__ 
    1155         id = "_".join(map(str, unit.identity())) 
    1156         table = self.table_name("_%s_%s_%s" % (unitcls.__name__, id, key)) 
    1157          
    1158         # Just drop the old table and start with a new one. 
    1159         try: 
    1160             self.execute(("DROP TABLE %s;" % table), conn) 
    1161         except: 
    1162             pass 
    1163          
    1164         val = getattr(unit, key) 
    1165         if val is None: 
    1166             # Don't create a new table at all. This will signal 
    1167             # recall() to set the attribute to None on load. 
    1168             pass 
    1169         else: 
    1170             ftype = getattr(self.typeAdapter, "coerce_" + subtype)(unitcls, key) 
    1171             self.execute(("CREATE TABLE %s (EXPVAL %s);" 
    1172                           % (table, ftype)), conn) 
    1173              
    1174             for v in val: 
    1175                 self.execute(("INSERT INTO %s (EXPVAL) VALUES ('%s');" 
    1176                               % (table, self.toAdapter.coerce(v))), conn) 
    1177      
    1178     def load_expanded(self, unit, key, subtype): 
    1179         """load_expanded(unit, key, subtype). Load list from separate table.""" 
    1180         unitcls = unit.__class__ 
    1181         id = "_".join(map(str, unit.identity())) 
    1182         table = self.table_name("_%s_%s_%s" % (unitcls.__name__, id, key)) 
    1183         try: 
    1184             data, col_defs = self.fetch("SELECT EXPVAL FROM %s" % table) 
    1185         except: 
    1186             values = None 
    1187         else: 
    1188             coltype = col_defs[0][1] 
    1189             coercer = getattr(self.fromAdapter, "coerce_" + subtype) 
    1190             values = [coercer(row[0], coltype) for row in data] 
    1191              
    1192             expected_type = unitcls.property_type(key) 
    1193             values = expected_type(values) 
    1194          
    1195         # Set the attribute directly to avoid __set__ overhead. 
    1196         unit._properties[key] = values 
    11971130     
    11981131    def destroy(self, unit): 
     
    13631296                c, key = sup 
    13641297                name, ftype = rec[0], rec[1] 
    1365                 subtype = self.expanded_columns.get((c.__name__, key)) 
    1366                 props.append((c, key, ftype, subtype)) 
     1298                props.append((c, key, ftype)) 
    13671299             
    13681300            consume = self.fromAdapter.consume 
     
    13701302                index = 0 
    13711303                units = {} 
    1372                 for c, key, ftype, subtype in props: 
     1304                for c, key, ftype in props: 
    13731305                    if c in units: 
    13741306                        unit = units[c] 
     
    13761308                        units[c] = unit = c() 
    13771309                    value = row[index] 
    1378                     if subtype: 
    1379                         self.load_expanded(unit, key, subtype) 
    1380                     else: 
    1381                         consume(unit, key, value, ftype) 
     1310                    consume(unit, key, value, ftype) 
    13821311                    index += 1 
    13831312                 
  • trunk/storage/storeado.py

    r192 r193  
    675675        fields = [] 
    676676        values = [] 
    677         # We have to delay expanded tables until we have an ID. 
    678         to_expand = [] 
    679677        for key in cls.properties: 
    680678            typename = self.typeAdapter.coerce(cls, key) 
     
    682680                # Skip this field, since we're using IDENTITY 
    683681                continue 
    684             subtype = self.expanded_columns.get((clsname, key)) 
    685             if subtype: 
    686                 to_expand.append((key, subtype)) 
    687             else: 
    688                 val = self.toAdapter.coerce(getattr(unit, key)) 
    689                 fields.append(self.column_name(clsname, key)) 
    690                 values.append(val) 
     682            val = self.toAdapter.coerce(getattr(unit, key)) 
     683            fields.append(self.column_name(clsname, key)) 
     684            values.append(val) 
    691685         
    692686        fields = ", ".join(fields) 
     
    702696                                    % str(tablename)) 
    703697        setattr(unit, cls.identifiers[0], data[0][0]) 
    704          
    705         # Now that we have an ID, save our expanded tables. 
    706         for key, subtype in to_expand: 
    707             self.save_expanded(unit, key, subtype) 
    708698     
    709699    #                               Schemas                               # 
     
    915905        fields = [] 
    916906        values = [] 
    917         # We have to delay expanded tables until we have an ID. 
    918         to_expand = [] 
    919907        for key in cls.properties: 
    920908            typename = self.typeAdapter.coerce(cls, key) 
     
    922910                # Skip this field, since we're using AUTOINCREMENT 
    923911                continue 
    924             subtype = self.expanded_columns.get((clsname, key)) 
    925             if subtype: 
    926                 to_expand.append((key, subtype)) 
    927             else: 
    928                 val = self.toAdapter.coerce(getattr(unit, key)) 
    929                 fields.append(self.column_name(clsname, key)) 
    930                 values.append(val) 
     912            val = self.toAdapter.coerce(getattr(unit, key)) 
     913            fields.append(self.column_name(clsname, key)) 
     914            values.append(val) 
    931915         
    932916        fields = ", ".join(fields) 
     
    938922        data, col_defs = self.fetch("SELECT @@IDENTITY;") 
    939923        setattr(unit, cls.identifiers[0], data[0][0]) 
    940          
    941         # Now that we have an ID, save our expanded tables. 
    942         for key, subtype in to_expand: 
    943             self.save_expanded(unit, key, subtype) 
    944924     
    945925    #                               Schemas                               # 
  • trunk/storage/storemysql.py

    r192 r193  
    231231        fields = [] 
    232232        values = [] 
    233         # We have to delay expanded tables until we have an ID. 
    234         to_expand = [] 
    235233        for key in cls.properties: 
    236234            typename = self.typeAdapter.coerce(cls, key) 
     
    238236                # Skip this field, since we're using AUTO_INCREMENT 
    239237                continue 
    240             subtype = self.expanded_columns.get((clsname, key)) 
    241             if subtype: 
    242                 to_expand.append((key, subtype)) 
    243             else: 
    244                 val = self.toAdapter.coerce(getattr(unit, key)) 
    245                 fields.append(self.column_name(clsname, key)) 
    246                 values.append(val) 
     238            val = self.toAdapter.coerce(getattr(unit, key)) 
     239            fields.append(self.column_name(clsname, key)) 
     240            values.append(val) 
    247241         
    248242        fields = ", ".join(fields) 
     
    254248        data, col_defs = self.fetch("SELECT LAST_INSERT_ID();") 
    255249        setattr(unit, cls.identifiers[0], data[0][0]) 
    256          
    257         # Now that we have an ID, save our expanded tables. 
    258         for key, subtype in to_expand: 
    259             self.save_expanded(unit, key, subtype) 
    260250     
    261251    #                               Schemas                               # 
  • trunk/storage/storepypgsql.py

    r192 r193  
    138138        fields = [] 
    139139        values = [] 
    140         # We have to delay expanded tables until we have an ID. 
    141         to_expand = [] 
    142140        for key in cls.properties: 
    143141            typename = self.typeAdapter.coerce(cls, key) 
     
    145143                # Skip this field, since we're using a sequencer 
    146144                continue 
    147             subtype = self.expanded_columns.get((clsname, key)) 
    148             if subtype: 
    149                 to_expand.append((key, subtype)) 
    150             else: 
    151                 val = self.toAdapter.coerce(getattr(unit, key)) 
    152                 fields.append(self.column_name(clsname, key)) 
    153                 values.append(val) 
     145            val = self.toAdapter.coerce(getattr(unit, key)) 
     146            fields.append(self.column_name(clsname, key)) 
     147            values.append(val) 
    154148         
    155149        fields = ", ".join(fields) 
     
    162156                                    % (clsname, cls.identifiers[0])) 
    163157        setattr(unit, cls.identifiers[0], data[0][0]) 
    164          
    165         # Now that we have an ID, save our expanded tables. 
    166         for key, subtype in to_expand: 
    167             self.save_expanded(unit, key, subtype) 
    168158     
    169159    #                               Schemas                               # 
  • trunk/storage/storesqlite.py

    r192 r193  
    284284        fields = [] 
    285285        values = [] 
    286         # We have to delay expanded tables until we have an ID. 
    287         to_expand = [] 
    288286        for key in cls.properties: 
    289287            if "AUTOINCREMENT" in self.typeAdapter.coerce(cls, key): 
    290288                # Skip this field, since we're using AUTOINCREMENT 
    291289                continue 
    292             subtype = self.expanded_columns.get((clsname, key)) 
    293             if subtype: 
    294                 to_expand.append((key, subtype)) 
    295             else: 
    296                 val = self.toAdapter.coerce(getattr(unit, key)) 
    297                 fields.append(self.column_name(clsname, key)) 
    298                 values.append(val) 
     290            val = self.toAdapter.coerce(getattr(unit, key)) 
     291            fields.append(self.column_name(clsname, key)) 
     292            values.append(val) 
    299293         
    300294        fields = ", ".join(fields) 
     
    309303        new_id = conn.sqlite_last_insert_rowid() 
    310304        setattr(unit, cls.identifiers[0], new_id) 
    311          
    312         # Now that we have an ID, save our expanded tables. 
    313         for key, subtype in to_expand: 
    314             self.save_expanded(unit, key, subtype, conn) 
    315305     
    316306    #                               Schemas                               # 
  • trunk/test/test_storemsaccess.py

    r192 r193  
    2121        opts = {u'Connect': "PROVIDER=MICROSOFT.JET.OLEDB.4.0;" 
    2222                            "DATA SOURCE=zoo.mdb;", 
    23                 u'Expanded Columns': "Animal.PreviousZoos:int", 
    2423                } 
    2524         
  • trunk/test/test_storeodbc.py

    r192 r193  
    1313                     "Driver={Microsoft Access Driver (*.mdb)};" 
    1414                     "DBQ=zooodbc.mdb;Provider=MSDASQL;"), 
    15         u'Expanded Columns': "Animal.PreviousZoos:int", 
    1615        } 
    1716SM_class = "dejavu.storage.storeodbc.StorageManagerODBC" 
  • trunk/test/test_storesqlserver.py

    r192 r193  
    1010                         "Initial Catalog=dejavu_test; " 
    1111                         "Data Source=REDROVER\\"), 
    12             u'Expanded Columns': "Animal.PreviousZoos:int", 
    1312            } 
    1413    SM_class = "dejavu.storage.storeado.StorageManagerADO_SQLServer"