Class: BtrieveTable

Inherits:
Object
  • Object
show all
Includes:
Btrieve
Defined in:
lib/btrieve/btrieve_table.rb

Overview

Represents a single btrieve table for a particular BTR database.

Constant Summary

Constants included from BtrCodes

BtrCodes::ABORT_TRANSACTION, BtrCodes::ACCELERATED_MODE, BtrCodes::BEGIN_TRANSACTION, BtrCodes::CLOSE, BtrCodes::DELETE, BtrCodes::END_TRANSACTION, BtrCodes::EOF, BtrCodes::EXCEPTION_MESSAGES, BtrCodes::EXCLUSIVE_MODE, BtrCodes::GET_DIRECT, BtrCodes::GET_EQUAL, BtrCodes::GET_EQUAL_KEY, BtrCodes::GET_FIRST, BtrCodes::GET_GREATER_THAN_OR_EQUAL, BtrCodes::GET_LESS_THAN_OR_EQUAL, BtrCodes::GET_NEXT, BtrCodes::GET_NEXT_EXTENDED, BtrCodes::GET_NEXT_KEY, BtrCodes::GET_POSITION, BtrCodes::GET_PREVIOUS, BtrCodes::INSERT, BtrCodes::KEY_NOT_FOUND, BtrCodes::LOCAL_ACCELERATED_MODE, BtrCodes::LOCAL_EXCLUSIVE_MODE, BtrCodes::LOCAL_NORMAL_MODE, BtrCodes::LOCAL_READ_ONLY_MODE, BtrCodes::MAX_DATATYPE, BtrCodes::NORMAL_MODE, BtrCodes::NO_CURRENCY_CHANGE, BtrCodes::NO_LOGICAL_CURRENCY_KEY, BtrCodes::NULL_BUFFER, BtrCodes::NULL_KEY, BtrCodes::OK, BtrCodes::OPEN, BtrCodes::POS_BLOCK_SIZE, BtrCodes::READ_ONLY_MODE, BtrCodes::RECORD_POSITION_SIZE, BtrCodes::REMOTE_ACCELERATED_MODE, BtrCodes::REMOTE_EXCLUSIVE_MODE, BtrCodes::REMOTE_NORMAL_MODE, BtrCodes::REMOTE_READ_ONLY_MODE, BtrCodes::RESET, BtrCodes::STEP_NEXT, BtrCodes::STEP_NEXT_EXTENDED, BtrCodes::STOP, BtrCodes::SYSTEM_LOG_KEY, BtrCodes::UPDATE, BtrCodes::VERIFY_MODE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Btrieve

#btr_op, create_string_buffer

Constructor Details

#initialize(tablename, schema = nil) ⇒ BtrieveTable

Initializes a btrieve table.



10
11
12
13
14
# File 'lib/btrieve/btrieve_table.rb', line 10

def initialize(tablename, schema=nil)
  @tablename = tablename
  @pos_buffer = Btrieve.create_string_buffer(POS_BLOCK_SIZE)
  @schema = schema ? schema : session.btrieve_schema.get_table_schema(@tablename)
end

Instance Attribute Details

#pos_bufferObject (readonly)

Returns the value of attribute pos_buffer.



6
7
8
# File 'lib/btrieve/btrieve_table.rb', line 6

def pos_buffer
  @pos_buffer
end

#primary_keyObject

Returns the value of attribute primary_key.



7
8
9
# File 'lib/btrieve/btrieve_table.rb', line 7

def primary_key
  @primary_key
end

#schemaObject (readonly)

Returns the value of attribute schema.



6
7
8
# File 'lib/btrieve/btrieve_table.rb', line 6

def schema
  @schema
end

#tablenameObject (readonly)

Returns the value of attribute tablename.



6
7
8
# File 'lib/btrieve/btrieve_table.rb', line 6

def tablename
  @tablename
end

Instance Method Details

#batch(mode = NORMAL_MODE, &block) ⇒ Object

Wraps a sequence of BTR operations between a pair of open and close statements for this table. DEPRECATED - Use the “open” method instead and pass a block to it.



99
100
101
102
103
# File 'lib/btrieve/btrieve_table.rb', line 99

def batch(mode=NORMAL_MODE, &block)
  open(mode)
  yield
  close
end

#closeObject

Closes this btrieve table to conclude a sequence of BTR operation(s).



83
84
85
86
# File 'lib/btrieve/btrieve_table.rb', line 83

def close
  btr_op(CLOSE, @pos_buffer, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
  @pos_buffer=Btrieve.create_string_buffer(POS_BLOCK_SIZE)
end

#each_record(mode = NORMAL_MODE, &block) ⇒ Object

Loops over the records of this BTR table and passes each record to the block passed in.



89
90
91
92
93
94
95
# File 'lib/btrieve/btrieve_table.rb', line 89

def each_record(mode=NORMAL_MODE, &block)
  batch(mode) do
    while(record = step_next) do
      yield record
    end
  end
end

#find(match, index_number, &block) ⇒ Object

Finds an array of records in this table, using the specified index number and match hash. If a block is passed in, the entries of this set are passed into this block one by one. Otherwise, the set is returned to the caller.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/btrieve/btrieve_table.rb', line 31

def find(match, index_number, &block)
  allows_duplicates=schema[:index_flags].map{|f|f&1==1;}[index_number]
  set=nil
  if(allows_duplicates)
    set=find_in_index(match, index_number)
  else
    rec=find_in_unique_index(match, index_number)
    set=rec.nil? ? [] : [rec]
  end
  if(block_given?)
    set.each{|record| yield record}
  else
    set
  end
end

#find_extended(index, filter, fields_to_return, records_to_fetch) ⇒ Object

Returns an array of hashes that match the criteria defined by the filter parameter. An example of the filter parameter is given below -

filter = [[:dept_name, :equal, ‘Philosophy’], :and, [:name, :not_equal, ‘PHI 101’], :and, [:name, :not_equal, :dept_name]]

The following COMPARISON operators are supported in the logical comparison clauses -

:equal
:greater_than
:less_than
:not_equal
:greater_than_or_equal
:less_than_or_equal

Logical comparison clauses can chained together using the following boolean operators -

:and
:or

NOTE - The logical comparisons can compare a columns to a constant OR to another column in the same record.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/btrieve/btrieve_table.rb', line 139

def find_extended(index, filter, fields_to_return, records_to_fetch)
  record_size = @schema[:record_size]
  records_buffer = record_size*records_to_fetch
  max_reject_count = 65535
  start_point = :next_record
  searcher = BtrieveSearchBuffer.new(self, filter, fields_to_return, records_to_fetch, max_reject_count, max_reject_count)
  search_buffer = searcher.get_encoded_buffer
  buff_diff = records_buffer - search_buffer.size
  search_buffer << Btrieve.create_string_buffer(buff_diff) if(buff_diff > 0)
  tmp_buff = Btrieve.create_string_buffer(record_size)
  key_buff = Btrieve.create_string_buffer(record_size)
  btr_op(GET_FIRST, @pos_buffer, tmp_buff, key_buff, index, [OK])
  ops_result = btr_op(GET_NEXT_EXTENDED, @pos_buffer, search_buffer, key_buff, index, [OK, EOF])
  num_records = search_buffer.unpack('S')[0]
  record_byte_pointer=2
  records = []
  (0...num_records).each do |index|
    record_length = search_buffer.unpack("@#{record_byte_pointer}S")[0]
    record_position = search_buffer.unpack("@#{2+record_byte_pointer}i")[0]
    record=search_buffer.unpack("@#{6+record_byte_pointer}a#{record_length}")[0]
    record_byte_pointer += 6+record_length
    unpacker = fields_to_return.inject(["", 0]) do |arr, c|
      column = @schema[:columns][c]
      str = BtrieveSchema.unpacker(arr[1], column[:datatype], column[:size])
      arr[0] << str
      arr[1] += column[:size]
      arr
    end
    fields = record.unpack(unpacker[0])
    records << {:position=>record_position, :values=>Hash[*fields_to_return.zip(fields).flatten]}
  end
  records
end

#find_in_range(index_num, key, range, &block) ⇒ Object

Finds an array of records in this table, using the specified index number, a key and a range of values. If a block is passed in, the entries of this set are passed into this block one by one. Otherwise, the set is returned to the caller. WARNING - NO UNIT TEST EXIST YET! CONSIDER - Deprecation coming soon… Should use the ‘find_extended’ method instead.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/btrieve/btrieve_table.rb', line 52

def find_in_range(index_num, key, range, &block)
  index = @schema[:indices][index_num]
  columns = @schema[:columns]
  index_values = index.inject([]){|vals,akey|vals << (akey == key ? range.first : nil); vals}
  key_packer = index.inject("") do |packer, akey|
    value_packer = BtrieveSchema.lookup(columns[akey][:datatype], columns[akey][:size])[:unpacker]
    nil_packer = 'x'*columns[key][:size]
    packer << (akey == key ? value_packer : nil_packer)
    packer
  end
  key_buffer = index_values.pack(key_packer)
  btr_record = BtrieveRecord.new(self)
  records = []
  batch do
    btr_op(GET_GREATER_THAN_OR_EQUAL, @pos_buffer, btr_record.data_buffer, key_buffer, index_num, [OK, EOF])
    while(range.include?(btr_record[key]))
      if(!block.nil?)
       yield btr_record
     else
       records << btr_record
     end
      btr_record = BtrieveRecord.new(self)
      btr_op(GET_NEXT, @pos_buffer, btr_record.data_buffer, key_buffer, index_num, [OK, EOF])
    end
  end
  if(block.nil?)
   records
 end
end

#open(mode = NORMAL_MODE, &block) ⇒ Object

Opens this btrieve table in preparation for some BTR operation(s). If a block is passed to the call, the table is closed automatically. If a block is NOT passed to the call, the client code has to make sure to close the file.



19
20
21
22
23
24
25
26
# File 'lib/btrieve/btrieve_table.rb', line 19

def open(mode=NORMAL_MODE, &block)
  file_unc="//#{session.db}/#{@schema[:filename]}"
  btr_op(OPEN, @pos_buffer, NULL_BUFFER, file_unc, mode)
  if block_given?
    yield
    close()
  end
end

#pack_value(column, value) ⇒ Object

Packs a value according to the metadata of a particular column.



111
112
113
114
115
116
117
118
119
# File 'lib/btrieve/btrieve_table.rb', line 111

def pack_value(column, value)
  packer_string = column[:unpacker]
  match = packer_string.match(/@(\d+)([a-zA-Z]+)(\d*)/)
  datatype = match[2]
  size = match[3].empty? ? BtrieveSchema::SIZEOF[datatype] : BtrieveSchema::SIZEOF[datatype]*match[3].to_i
  packer = "#{datatype}#{size}"
  array = [value]
  array.pack(packer)
end

#versionObject

Returns this table’s version as a MD5 Digest value.



106
107
108
# File 'lib/btrieve/btrieve_table.rb', line 106

def version()
  Digest::MD5.hexdigest(BtrieveSchema.sort(schema[:columns]).inject([]){|array,column|array << BtrieveSchema.readable_type(column);array}.to_s)
end