lib/og/store/psql.rb in og-0.29.0 vs lib/og/store/psql.rb in og-0.30.0

- old
+ new

@@ -222,11 +222,11 @@ ) conn.list_tables.each do |table| begin conn.exec "DROP TABLE #{table} CASCADE" - Logger.debug "Dropped database table #{table}" + Logger.debug "Dropped database table #{table}" if $DBG rescue RuntimeError => ex catch :ok do # Racing throw :ok if ex.message =~ /tuple concurrently updated/ throw :ok if ex.message =~ /does not exist/ throw :ok if ex.message =~ /cache lookup failed/ @@ -348,11 +348,11 @@ # row is deleted. # :name => The name of the constraint to apply. def constraint_info(rel) if rel.join_table - info = join_table_info(rel.owner_class,rel.target_class) + info = join_table_info(rel) constraints = [ { :fk => info[:first_key], :referenced_table => info[:first_table], :table => rel.join_table, :pk => ( rel.owner_class.primary_key.field || rel.owner_class.primary_key.symbol ), :update => 'CASCADE', :delete => 'CASCADE'}, { :fk => info[:second_key], :referenced_table => info[:second_table], :table => rel.join_table, :pk => ( rel.target_class.primary_key.field || rel.target_class.primary_key.symbol ), :update => 'CASCADE', :delete => 'CASCADE' } ] elsif rel.class == Og::HasMany constraints = [ { :fk => rel.foreign_key, :table => rel.target_class::OGTABLE, :referenced_table => rel.owner_class::OGTABLE, :pk => ( rel.owner_class.primary_key.field || rel.owner_class.primary_key.symbol ), :update => 'SET NULL', :delete => 'SET NULL' } ] else @@ -457,11 +457,11 @@ elsif all_existing[table][name] != definition # Exists in database and matches the object structure but has the # wrong definition (unlikely to happen very often). - Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which is incorrectly defined and will be redefined (OLD: '#{all_existing[table][name]}', NEW: '#{definition}')" + Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which is incorrectly defined and will be redefined (OLD: '#{all_existing[table][name]}', NEW: '#{definition}')" if $DBG drop_constraints << "ALTER TABLE #{table} DROP CONSTRAINT #{name}" create_constraints << "ALTER TABLE #{table} ADD CONSTRAINT #{name} #{definition}" end end end @@ -478,11 +478,11 @@ constraints.each_key do |name| if all_needed[table].nil? or all_needed[table][name].nil? # Exists in database but doesn't match object model at all raise Exception if table.to_s.downcase == "table" - Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which does not match the object model and will be deleted" + Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which does not match the object model and will be deleted" if $DBG drop_constraints << "ALTER TABLE #{table} DROP CONSTRAINT #{name}" end end end end @@ -498,11 +498,11 @@ # the work. def create_constraints(param = nil) subsection_only = !!param sql_hash = param ? param : needed_constraints_sql - Logger.debug "PostgreSQL processing foreign key constraints" unless subsection_only + Logger.debug "PostgreSQL processing foreign key constraints" unless subsection_only if $DBG started = Time.now deleted = 0 nulled_relations = 0 deleted_relations = 0 created = 0 @@ -581,11 +581,11 @@ text << "#{nullified_relations} relations to have rows with non-existant foreign keys deleted, " if deleted_relations != 0 end end text = text[0..-3].gsub(/,([^,]+)$/,' and \1') text << " in #{taken} seconds." - Logger.debug text + Logger.debug text if $DBG end # Called by Og.manager (in turn called by Og.setup) when Og.setup # has finished, allowing better processing of foreign key # constraints and possibly other enhancements. @@ -632,11 +632,11 @@ throw :ok if ex.message =~ /already exists/ raise end end else - Logger.debug "Table #{klass::OGTABLE} already exists" + Logger.debug "Table #{klass::OGTABLE} already exists" if $DBG #rp: basic field interrogation # TODO: Add type checking. actual_fields = @conn.table_field_list(klass::OGTABLE).map {|pair| pair.first} @@ -644,11 +644,11 @@ need_fields = fields.each do |needed_field| field_name = needed_field[0..(needed_field.index(' ')-1)] next if actual_fields.include?(field_name) if @options[:evolve_schema] == true - Logger.debug "Adding field '#{needed_field}' to '#{klass::OGTABLE}'" + Logger.debug "Adding field '#{needed_field}' to '#{klass::OGTABLE}'" if $DBG sql = "ALTER TABLE #{klass::OGTABLE} ADD COLUMN #{needed_field}" begin @conn.exec(sql) rescue RuntimeError => ex raise unless ex.message =~ /already exists/ @@ -666,11 +666,11 @@ sql = "ALTER TABLE #{klass::OGTABLE} DROP COLUMN #{obsolete_field}" begin @conn.exec(sql) rescue RuntimeError => ex raise unless ex.message =~ /does not exist/ - Logger.debug "Removed obsolete field '#{obsolete_field}' from '#{klass::OGTABLE}'" + Logger.debug "Removed obsolete field '#{obsolete_field}' from '#{klass::OGTABLE}'" if $DBG end else Logger.info "WARNING: You have an obsolete field '#{obsolete_field}' on table '#{klass::OGTABLE}' and :evolve_schema is not set or is in cautious mode!" end end @@ -683,11 +683,12 @@ # and therefore can't be used. # if join_tables = klass.ann.self[:join_tables] # for info in join_tables # unless @conn.table_exists? info[:table] # join_tables = Array.new - join_tables = klass.relations.reject{|rel| !rel.join_table}.map{|rel| join_table_info(rel.owner_class, rel.target_class)} +# join_tables = klass.relations.reject{|rel| !rel.join_table}.map{|rel| join_table_info(rel)} + if join_tables = klass.ann.self[:join_tables] for info in join_tables unless @conn.table_exists? info[:table] create_join_table_sql(info).each do |sql| begin res = @conn.exec(sql) @@ -695,15 +696,16 @@ rescue RuntimeError => ex raise unless ex.message =~ /duplicate key violates unique constraint "pg_class_relname_nsp_index"/ # Racing end end - Logger.debug "Created jointable '#{info[:table]}'." + Logger.debug "Created jointable '#{info[:table]}'." if $DBG else - Logger.debug "Join table '#{info[:table]}' already exists." + Logger.debug "Join table '#{info[:table]}' already exists." if $DBG end end + end # If we are being called by Og.setup, we can use a much cleaner method # for constructing foreign key constraints. return if @options[:called_by_og_setup] @@ -711,11 +713,11 @@ # must be here for now while glycerin is still bleeding-edge to fix # changes and a nasty error that made it into the glycerin developers # darcs repo (but NOT into any released version of Nitro) unless @options[:leave_constraints] == true or @stripped_constraints - Logger.debug "Stripping PostgreSQL foreign key constraints" + Logger.debug "Stripping PostgreSQL foreign key constraints" if $DBG all_foreign_keys.map{|k| k[1].map{|v| [k[0],v[0]] }[0]}.each do |table,constraint| prefix = constraint_prefix next unless constraint[0-prefix.size..-1] == constraint_prefix begin m.store.conn.exec "ALTER TABLE #{table} DROP CONSTRAINT #{constraint}" @@ -732,11 +734,11 @@ def drop_table(klass) # foreign key constraints will remove the need to do manual cleanup on # related rows. exec "DROP TABLE #{klass.table} CASCADE" end - + def create_field_map(klass) begin res = @conn.exec "SELECT * FROM #{klass::OGTABLE} LIMIT 1" rescue RuntimeError => ex raise unless ex.message =~ /does not exist/ or ex.message =~ /deleted while still in use/ @@ -744,13 +746,21 @@ create_table(klass) retry end map = {} + # Check if the field should be ignored. + ignore = klass.ann[:self][:ignore_field] || klass.ann[:self][:ignore_fields] || klass.ann[:self][:ignore_columns] + for field in res.fields - map[field.intern] = res.fieldnum(field) + field_name = field.to_sym + + unless (ignore and ignore.include?(field_name)) + map[field_name] = res.fieldnum(field) + end end + return map ensure res.clear if res end @@ -789,21 +799,21 @@ sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})" klass.class_eval %{ def og_insert(store) - #{Glue::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)} + #{::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)} res = store.conn.exec "SELECT nextval('#{klass::OGSEQ}')" @#{klass.pk_symbol} = res.getvalue(0, 0).to_i res.clear store.conn.exec("#{sql}").clear - #{Glue::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)} + #{::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)} end } end def eval_og_allocate(klass) - if klass.ann.self[:subclasses] + if klass.schema_inheritance? klass.module_eval %{ def self.og_allocate(res, row = 0) Object.constant(res.getvalue(row, 0)).allocate end }