# File vapor/repositorymgr.rb, line 386 def updateclass( new_klassdef ) raise TypeError unless new_klassdef.is_a? ClassMetaData old_klassdef = known_classes().find{|k| k.name == new_klassdef.name } # check if the class is known to the repository raise ClassNotKnownError unless old_klassdef # check if superclass still the same unless old_klassdef.superclass == new_klassdef.superclass raise InvalidMetadataError, "different superclass `#{new_klassdef.superclass}' for `#{new_klassdef.name}'" end # get the class' oid oid = @dbh.select_one( %!SELECT _oid FROM ":Vapor::ClassMetaData" WHERE _name = '#{old_klassdef.name}' ! )[0] # let's check out each attribute new_klassdef.attributes.each{|new_attr| # search for same name field old_attr = old_klassdef.attributes.find{|a| a.name == new_attr.name } if !old_attr.nil? # an attribute with same name exists if old_attr == new_attr then # skip it if it's exactly same next else # changing not allowed raise InvalidMetadataError, "can't change type of defined attribute `#{old_attr.name}'" end end # !old_attr.nil? ### new attribute not in the class' attribute list, must be new ## attempt to modify the table(s) begin @dbh.execute( %!ALTER TABLE "#{old_klassdef.table}" ADD COLUMN "#{new_attr.name}" #{new_attr.type_sql}! ) @dbh.execute( %!ALTER TABLE "_#{old_klassdef.table}" ADD COLUMN "#{new_attr.name}" #{new_attr.type_sql}! ) rescue DBI::ProgrammingError => e case e.message when %!ALTER TABLE: column.*already exists in table "#{old_klassdef.table}"! # redefining a parent class's attribute raise InvalidMetadataError, "can't override attribute `#{new_attr.name}' defined in superclass" when %!ALTER TABLE: column.*already exists in table "(\w+)"! # defining attribute in child class raise InvalidMetadataError, "creation of attribute `#{new_attr.name}' with same name as attribute defined in child class `#{$~[1]}' not supported by PostgreSQL 7.2" else raise e end end ## add to metadata # insert attribute @dbh.execute( %!INSERT INTO ":Vapor::AttributeMetaData" (_oid, _name, _type, _array ) VALUES ( #{oid}, '#{new_attr.name}', '#{new_attr.type_s}', #{new_attr.is_array} )! ) } # new_klassdef.attributes.each ## update indexes by first dropping all and then (re)creating them # drop non-unique indexes (common method to PostgreSQL 7.2 and 7.3) @dbh.execute( %!SELECT i.relname FROM pg_index index, pg_class r, pg_class i WHERE r.relname = '#{old_klassdef.table}' AND index.indisprimary = false AND index.indisunique = false AND r.oid = index.indrelid AND index.indexrelid = i.oid! ).each{|index| @dbh.execute( %!DROP INDEX "#{index[0]}"! ) } # drop unique indexes (method dependent on PostgreSQL version) @dbh.execute( %!SELECT i.relname FROM pg_index index, pg_class r, pg_class i WHERE r.relname = '#{old_klassdef.table}' AND index.indisprimary = false AND index.indisunique = true AND r.oid = index.indrelid AND index.indexrelid = i.oid! ).each{|index| if @psql_version >= "7.3" @dbh.execute( %!ALTER TABLE "#{old_klassdef.table}" DROP CONSTRAINT "#{index[0]}"! ) else # PostgreSQL 7.2 @dbh.execute( %!DROP INDEX "#{index[0]}"! ) end } index_number = 0 new_klassdef.indexes.each{|index| create_index( new_klassdef.name, index_number, index, false ) index_number += 1 } new_klassdef.unique.each{|index| create_index( new_klassdef.name, index_number, index, true ) index_number += 1 } end