require 'digest/md5' # Represents a single btrieve record for a particular BTR table. class BtrieveRecord include Btrieve attr_reader :data_buffer, :btrieve_table attr_accessor :position # Initializes a btrieve record. def initialize(btrieve_table, data_buffer=nil) @btrieve_table = btrieve_table @data_buffer = data_buffer.nil? ? Btrieve.create_string_buffer(@btrieve_table.schema[:record_size]) : data_buffer reset_physical_position end # Inserts a new btrieve record through the transactional BTR engine. def insert btr_op(INSERT, @btrieve_table.pos_buffer, @data_buffer, NULL_BUFFER, SYSTEM_LOG_KEY) set_physical_position end # Updates an existing btrieve record through the transactional BTR engine. def update new_state="#{@data_buffer}" @data_buffer[0..3]=@position btr_op(GET_DIRECT, @btrieve_table.pos_buffer, @data_buffer, NULL_BUFFER, SYSTEM_LOG_KEY) btr_op(UPDATE, @btrieve_table.pos_buffer, new_state, NULL_BUFFER, SYSTEM_LOG_KEY) set_physical_position end # Deletes an existing btrieve record through the transactional BTR engine. def delete @data_buffer[0..3]=@position btr_op(GET_DIRECT, @btrieve_table.pos_buffer, @data_buffer, NULL_BUFFER, SYSTEM_LOG_KEY) btr_op(DELETE, @btrieve_table.pos_buffer, NULL_BUFFER, NULL_BUFFER, NULL_KEY) reset_physical_position end # Returns hash of column-value pairs for this btrieve record, given an array of named columns. # If the array is nil, the hash will contain ALL the column-value pairs defined by the schema. def values(column_names=nil) if(column_names.nil?) column_names=@btrieve_table.schema[:columns].keys.sort.inject([]){|array,column|array<< column;array} end column_names.inject({}){|vals, key| vals[key]=self[key]; vals} end # Sets the column valuesof this record based on the values passed through the 'column_values' map. def values=(column_values) column_values.each{ |key, value| self[key]=value } end # Returns this record's primary key value. Supports composite keys. def primary_key() values(@btrieve_table.primary_key) end # Returns this record's value of the column passed in. def [](key_name) column = @btrieve_table.schema[:columns][key_name] return nil if(column.nil?) val = @data_buffer.unpack(column[:unpacker])[0] val = val.strip if val.respond_to?('strip') val end # Sets this record's value for a particular column. def []=(key_name, value) column = @btrieve_table.schema[:columns][key_name] packed_value = @btrieve_table.pack_value(column, value) offset = column[:offset] range = (offset..offset+packed_value.size-1) @data_buffer[range] = packed_value end # Determines if a record is nil. def nil?() @data_buffer.gsub("\x00", "").size==0 end # Returns a string representation of this record. def to_s() @btrieve_table.schema[:columns].keys.inject("[position=>'#{position.unpack('i')[0]}'"){|pretty_print, key| pretty_print << ", #{key}=>'#{self[key]}'"; pretty_print } << "]" end # Returns this record's version as a MD5 Digest value. def version() Digest::MD5.hexdigest(@data_buffer) end # TODO - documentation def set_physical_position reset_physical_position btr_op(GET_POSITION, @btrieve_table.pos_buffer, @position, NULL_BUFFER, NULL_KEY) self end # TODO - documentation def reset_physical_position @position = Btrieve.create_string_buffer(RECORD_POSITION_SIZE) end end