dbf 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 1.2.4
2
+
3
+ * Add csv output option to dbf command-line utility
4
+ * Read Visual FoxPro memos
5
+
6
+ == 1.2.3
7
+
8
+ * Small performance gain when unpacking values from the dbf file
9
+ * Correctly handle FoxPro's integer data type
10
+
1
11
  == 1.2.2
2
12
 
3
13
  * Handle invalid date fields
data/VERSION.yml CHANGED
@@ -2,4 +2,4 @@
2
2
  :major: 1
3
3
  :minor: 2
4
4
  :build:
5
- :patch: 2
5
+ :patch: 4
data/bin/dbf CHANGED
@@ -5,12 +5,14 @@ require 'dbf'
5
5
 
6
6
  $a ||= false
7
7
  $s ||= false
8
+ $c ||= false
8
9
 
9
10
  if defined? $h then
10
- puts "usage: #{File.basename(__FILE__)} [-h|-s|-a] filename"
11
+ puts "usage: #{File.basename(__FILE__)} [-h|-s|-a|-c] filename"
11
12
  puts " -h = print this message"
12
13
  puts " -s = print summary information"
13
14
  puts " -a = create an ActiveRecord::Schema"
15
+ puts " -c = create a csv file"
14
16
  else
15
17
 
16
18
  filename = ARGV.shift
@@ -37,4 +39,10 @@ else
37
39
  puts "%-16s %-10s %-10s %-10s" % [f.name, f.type, f.length, f.decimal]
38
40
  end
39
41
  end
40
- end
42
+
43
+ if $c
44
+ table = DBF::Table.new filename
45
+ table.to_csv
46
+ end
47
+
48
+ end
data/dbf.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dbf}
8
- s.version = "1.2.2"
8
+ s.version = "1.2.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Keith Morrison"]
12
- s.date = %q{2010-04-01}
12
+ s.date = %q{2010-04-06}
13
13
  s.default_executable = %q{dbf}
14
14
  s.description = %q{A small fast library for reading dBase, xBase, Clipper and FoxPro database files.}
15
15
  s.email = %q{keithm@infused.org}
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
34
34
  "spec/fixtures/dbase_03.dbf",
35
35
  "spec/fixtures/dbase_30.dbf",
36
36
  "spec/fixtures/dbase_30.fpt",
37
+ "spec/fixtures/dbase_31.dbf",
37
38
  "spec/fixtures/dbase_83.dbf",
38
39
  "spec/fixtures/dbase_83.dbt",
39
40
  "spec/fixtures/dbase_83_schema.txt",
@@ -44,6 +45,7 @@ Gem::Specification.new do |s|
44
45
  "spec/functional/dbf_shared.rb",
45
46
  "spec/functional/format_03_spec.rb",
46
47
  "spec/functional/format_30_spec.rb",
48
+ "spec/functional/format_31_spec.rb",
47
49
  "spec/functional/format_83_spec.rb",
48
50
  "spec/functional/format_8b_spec.rb",
49
51
  "spec/functional/format_f5_spec.rb",
@@ -61,6 +63,7 @@ Gem::Specification.new do |s|
61
63
  "spec/functional/dbf_shared.rb",
62
64
  "spec/functional/format_03_spec.rb",
63
65
  "spec/functional/format_30_spec.rb",
66
+ "spec/functional/format_31_spec.rb",
64
67
  "spec/functional/format_83_spec.rb",
65
68
  "spec/functional/format_8b_spec.rb",
66
69
  "spec/functional/format_f5_spec.rb",
data/lib/dbf/column.rb CHANGED
@@ -29,7 +29,7 @@ module DBF
29
29
  when 'N' # number
30
30
  unpack_number(value)
31
31
  when 'I' # integer
32
- unpack_integer(value)
32
+ unpack_unsigned_long(value)
33
33
  when 'F' # float
34
34
  unpack_float(value)
35
35
  when 'D' # date
@@ -87,6 +87,14 @@ module DBF
87
87
  value.to_i
88
88
  end
89
89
 
90
+ # Decode an unsigned long
91
+ #
92
+ # @param [String] value
93
+ # @return [Fixnum]
94
+ def unpack_unsigned_long(value)
95
+ value.unpack('V')[0]
96
+ end
97
+
90
98
  # Decode a boolean value
91
99
  #
92
100
  # @param [String] value
data/lib/dbf/record.rb CHANGED
@@ -50,18 +50,30 @@ module DBF
50
50
  def initialize_values
51
51
  @attributes = columns.inject({}) do |hash, column|
52
52
  if column.type == 'M'
53
- starting_block = unpack_data(column.length).to_i
54
- hash[column.name] = read_memo(starting_block)
55
- hash[column.name.underscore] = read_memo(starting_block)
53
+ memo = read_memo(get_starting_block(column))
54
+ hash[column.name] = memo
55
+ hash[column.name.underscore] = memo
56
56
  else
57
57
  value = unpack_data(column.length)
58
- hash[column.name] = column.type_cast(value)
59
- hash[column.name.underscore] = column.type_cast(value)
58
+ type_cast_value = column.type_cast(value)
59
+ hash[column.name] = type_cast_value
60
+ hash[column.name.underscore] = type_cast_value
60
61
  end
61
62
  hash
62
63
  end
63
64
  end
64
-
65
+
66
+ # Unpack starting block from database
67
+ #
68
+ # @param [Fixnum] length
69
+ def get_starting_block(column)
70
+ if %w(30 31).include?(@table.version)
71
+ @data.read(column.length).unpack('V')[0]
72
+ else
73
+ unpack_data(column.length).to_i
74
+ end
75
+ end
76
+
65
77
  # Unpack raw data from database
66
78
  #
67
79
  # @param [Fixnum] length
@@ -93,7 +105,7 @@ module DBF
93
105
  else
94
106
  memo_string = memo_string[0, memo_size]
95
107
  end
96
- memo_string
108
+ memo_string.strip
97
109
  end
98
110
 
99
111
  # Reconstucts a memo from an DBT memo file
data/lib/dbf/table.rb CHANGED
@@ -135,6 +135,7 @@ module DBF
135
135
  def to_csv(path = nil)
136
136
  path = File.basename(@data.path, '.dbf') + '.csv' if path.nil?
137
137
  FCSV.open(path, 'w', :force_quotes => true) do |csv|
138
+ csv << columns.map {|c| c.name}
138
139
  each do |record|
139
140
  csv << record.to_a
140
141
  end
@@ -188,7 +189,7 @@ module DBF
188
189
  def find_all(options, &block)
189
190
  results = []
190
191
  each do |record|
191
- if all_values_match?(record, options)
192
+ if record && all_values_match?(record, options)
192
193
  if block_given?
193
194
  yield(record)
194
195
  else
@@ -205,7 +206,7 @@ module DBF
205
206
  # @return [DBF::Record, nil]
206
207
  def find_first(options)
207
208
  each do |record|
208
- return record if all_values_match?(record, options)
209
+ return record if record && all_values_match?(record, options)
209
210
  end
210
211
  nil
211
212
  end
Binary file
@@ -21,7 +21,7 @@ describe DBF, :shared => true do
21
21
  end
22
22
 
23
23
  specify "column types should be valid" do
24
- valid_column_types = %w(C N L D M F B G P Y T I V X @ O +)
24
+ valid_column_types = %w(C N L D M F B G P Y T I V X @ O + 0)
25
25
  @table.columns.all? {|column| valid_column_types.should include(column.type)}
26
26
  end
27
27
 
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
  require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 03 (dBase III without memo file)" do
5
- before(:each) do
5
+ before do
6
6
  @table = DBF::Table.new "#{DB_PATH}/dbase_03.dbf"
7
7
  end
8
8
 
@@ -16,7 +16,7 @@ describe DBF, "of type 03 (dBase III without memo file)" do
16
16
  @table.should_not have_memo_file
17
17
  end
18
18
 
19
- it "should report the correct memo type" do
19
+ it "should have a nil memo_file_format" do
20
20
  @table.memo_file_format.should be_nil
21
21
  end
22
22
 
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
  require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 30 (Visual FoxPro)" do
5
- before(:each) do
5
+ before do
6
6
  @table = DBF::Table.new "#{DB_PATH}/dbase_30.dbf"
7
7
  end
8
8
 
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+ require File.dirname(__FILE__) + "/dbf_shared"
3
+
4
+ describe DBF, "of type 31 (Visual FoxPro with AutoIncrement field)" do
5
+ before do
6
+ @table = DBF::Table.new "#{DB_PATH}/dbase_31.dbf"
7
+ end
8
+
9
+ it_should_behave_like "DBF"
10
+
11
+ it "should have a dBase version of 31" do
12
+ @table.version.should == "31"
13
+ end
14
+
15
+ it "should have a memo file" do
16
+ @table.should_not have_memo_file
17
+ end
18
+
19
+ it "should have a nil memo_file_format" do
20
+ @table.memo_file_format.should be_nil
21
+ end
22
+
23
+ end
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
  require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 83 (dBase III with memo file)" do
5
- before(:each) do
5
+ before do
6
6
  @table = DBF::Table.new "#{DB_PATH}/dbase_83.dbf"
7
7
  end
8
8
 
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
  require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type 8b (dBase IV with memo file)" do
5
- before(:each) do
5
+ before do
6
6
  @table = DBF::Table.new "#{DB_PATH}/dbase_8b.dbf"
7
7
  end
8
8
 
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
2
2
  require File.dirname(__FILE__) + "/dbf_shared"
3
3
 
4
4
  describe DBF, "of type f5 (FoxPro with memo file)" do
5
- before(:each) do
5
+ before do
6
6
  @table = DBF::Table.new "#{DB_PATH}/dbase_f5.dbf"
7
7
  end
8
8
 
@@ -10,15 +10,15 @@ describe DBF::Column do
10
10
  it "should set the #name accessor" do
11
11
  @column.name.should == "ColumnName"
12
12
  end
13
-
13
+
14
14
  it "should set the #type accessor" do
15
15
  @column.type.should == "N"
16
16
  end
17
-
17
+
18
18
  it "should set the #length accessor" do
19
19
  @column.length.should == 1
20
20
  end
21
-
21
+
22
22
  it "should set the #decimal accessor" do
23
23
  @column.decimal.should == 0
24
24
  end
@@ -39,9 +39,10 @@ describe DBF::Column do
39
39
  context "#type_cast" do
40
40
  context 'with type N (number)' do
41
41
  context 'with 0 decimals' do
42
- it "should cast value to Integer" do
42
+ it 'should cast value to Fixnum' do
43
43
  value = "135"
44
44
  column = DBF::Column.new "ColumnName", "N", 3, 0
45
+ column.type_cast(value).should be_a Fixnum
45
46
  column.type_cast(value).should == 135
46
47
  end
47
48
  end
@@ -50,6 +51,7 @@ describe DBF::Column do
50
51
  it "should cast value to Float" do
51
52
  value = "13.5"
52
53
  column = DBF::Column.new "ColumnName", "N", 2, 1
54
+ column.type_cast(value).should be_a Float
53
55
  column.type_cast(value).should == 13.5
54
56
  end
55
57
  end
@@ -59,15 +61,17 @@ describe DBF::Column do
59
61
  it "should cast value to Float" do
60
62
  value = "135"
61
63
  column = DBF::Column.new "ColumnName", "F", 3, 0
64
+ column.type_cast(value).should be_a Float
62
65
  column.type_cast(value).should == 135.0
63
66
  end
64
67
  end
65
68
 
66
69
  context 'with type I (integer)' do
67
- it "should cast value to Integer" do
68
- value = "135"
70
+ it "should cast value to Fixnum" do
71
+ value = "\203\171\001\000"
69
72
  column = DBF::Column.new "ColumnName", "I", 3, 0
70
- column.type_cast(value).should == 135
73
+ column.type_cast(value).should be_a Fixnum
74
+ column.type_cast(value).should == 96643
71
75
  end
72
76
  end
73
77
 
@@ -75,12 +79,14 @@ describe DBF::Column do
75
79
  it "should cast 'y' to true" do
76
80
  value = "y"
77
81
  column = DBF::Column.new "ColumnName", "L", 1, 0
82
+ column.type_cast(value).should be_a TrueClass
78
83
  column.type_cast(value).should == true
79
84
  end
80
85
 
81
86
  it "should cast 'n' to false" do
82
87
  value = "n"
83
88
  column = DBF::Column.new "ColumnName", "L", 1, 0
89
+ column.type_cast(value).should be_a FalseClass
84
90
  column.type_cast(value).should == false
85
91
  end
86
92
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 2
8
- - 2
9
- version: 1.2.2
8
+ - 4
9
+ version: 1.2.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Keith Morrison
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-01 00:00:00 -07:00
17
+ date: 2010-04-06 00:00:00 -07:00
18
18
  default_executable: dbf
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -70,6 +70,7 @@ files:
70
70
  - spec/fixtures/dbase_03.dbf
71
71
  - spec/fixtures/dbase_30.dbf
72
72
  - spec/fixtures/dbase_30.fpt
73
+ - spec/fixtures/dbase_31.dbf
73
74
  - spec/fixtures/dbase_83.dbf
74
75
  - spec/fixtures/dbase_83.dbt
75
76
  - spec/fixtures/dbase_83_schema.txt
@@ -80,6 +81,7 @@ files:
80
81
  - spec/functional/dbf_shared.rb
81
82
  - spec/functional/format_03_spec.rb
82
83
  - spec/functional/format_30_spec.rb
84
+ - spec/functional/format_31_spec.rb
83
85
  - spec/functional/format_83_spec.rb
84
86
  - spec/functional/format_8b_spec.rb
85
87
  - spec/functional/format_f5_spec.rb
@@ -121,6 +123,7 @@ test_files:
121
123
  - spec/functional/dbf_shared.rb
122
124
  - spec/functional/format_03_spec.rb
123
125
  - spec/functional/format_30_spec.rb
126
+ - spec/functional/format_31_spec.rb
124
127
  - spec/functional/format_83_spec.rb
125
128
  - spec/functional/format_8b_spec.rb
126
129
  - spec/functional/format_f5_spec.rb