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 +10 -0
- data/VERSION.yml +1 -1
- data/bin/dbf +10 -2
- data/dbf.gemspec +5 -2
- data/lib/dbf/column.rb +9 -1
- data/lib/dbf/record.rb +19 -7
- data/lib/dbf/table.rb +3 -2
- data/spec/fixtures/dbase_31.dbf +0 -0
- data/spec/functional/dbf_shared.rb +1 -1
- data/spec/functional/format_03_spec.rb +2 -2
- data/spec/functional/format_30_spec.rb +1 -1
- data/spec/functional/format_31_spec.rb +23 -0
- data/spec/functional/format_83_spec.rb +1 -1
- data/spec/functional/format_8b_spec.rb +1 -1
- data/spec/functional/format_f5_spec.rb +1 -1
- data/spec/unit/column_spec.rb +13 -7
- metadata +6 -3
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
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
|
-
|
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.
|
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-
|
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
|
-
|
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
|
-
|
54
|
-
hash[column.name] =
|
55
|
-
hash[column.name.underscore] =
|
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
|
-
|
59
|
-
hash[column.name
|
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
|
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
|
19
|
+
it "should have a nil memo_file_format" do
|
20
20
|
@table.memo_file_format.should be_nil
|
21
21
|
end
|
22
22
|
|
@@ -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
|
data/spec/unit/column_spec.rb
CHANGED
@@ -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
|
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
|
68
|
-
value = "
|
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
|
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
|
-
-
|
9
|
-
version: 1.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-
|
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
|