jackcess-rb 0.1.0-java
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE +21 -0
- data/README.md +435 -0
- data/lib/jackcess/column.rb +61 -0
- data/lib/jackcess/database.rb +440 -0
- data/lib/jackcess/errors.rb +9 -0
- data/lib/jackcess/index.rb +89 -0
- data/lib/jackcess/row.rb +173 -0
- data/lib/jackcess/table.rb +191 -0
- data/lib/jackcess/type_converter.rb +130 -0
- data/lib/jackcess/version.rb +11 -0
- data/lib/jackcess.rb +35 -0
- data/vendor/commons-lang3-3.13.0.jar +0 -0
- data/vendor/commons-logging-1.2.jar +0 -0
- data/vendor/jackcess-4.0.4.jar +0 -0
- metadata +63 -0
data/lib/jackcess/row.rb
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jackcess
|
|
4
|
+
class Row
|
|
5
|
+
attr_reader :java_row, :table
|
|
6
|
+
attr_accessor :data
|
|
7
|
+
|
|
8
|
+
def initialize(java_row, table)
|
|
9
|
+
@java_row = java_row # This is actually a Map from Jackcess
|
|
10
|
+
@table = table
|
|
11
|
+
@data = {}
|
|
12
|
+
@original_data = {}
|
|
13
|
+
@dirty = false
|
|
14
|
+
|
|
15
|
+
# Convert Java map to Ruby hash
|
|
16
|
+
if java_row
|
|
17
|
+
java_row.each do |key, value|
|
|
18
|
+
converted_value = TypeConverter.from_java(value)
|
|
19
|
+
@data[key.to_s] = converted_value
|
|
20
|
+
@original_data[key.to_s] = converted_value
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get column value by name
|
|
26
|
+
def [](column_name)
|
|
27
|
+
raise ArgumentError, "Column name cannot be nil" if column_name.nil?
|
|
28
|
+
|
|
29
|
+
@data[column_name.to_s]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Set column value by name
|
|
33
|
+
def []=(column_name, value)
|
|
34
|
+
raise ArgumentError, "Column name cannot be nil" if column_name.nil?
|
|
35
|
+
|
|
36
|
+
column_name = column_name.to_s
|
|
37
|
+
|
|
38
|
+
# Mark as dirty if value changed
|
|
39
|
+
if @data[column_name] != value
|
|
40
|
+
@dirty = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
@data[column_name] = value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Save changes to the database
|
|
47
|
+
def save
|
|
48
|
+
return nil unless @dirty
|
|
49
|
+
|
|
50
|
+
begin
|
|
51
|
+
# Get primary key to find the row
|
|
52
|
+
pk_index = @table.java_table.get_primary_key_index
|
|
53
|
+
raise DatabaseError, "Cannot update row: table has no primary key" if pk_index.nil?
|
|
54
|
+
|
|
55
|
+
pk_column_name = pk_index.get_columns.first.get_name
|
|
56
|
+
pk_value = @data[pk_column_name]
|
|
57
|
+
|
|
58
|
+
# Create a new cursor for this update operation
|
|
59
|
+
cursor = com.healthmarketscience.jackcess.CursorBuilder.create_cursor(@table.java_table)
|
|
60
|
+
|
|
61
|
+
while cursor.move_to_next_row
|
|
62
|
+
current_row = cursor.get_current_row
|
|
63
|
+
current_pk = TypeConverter.from_java(current_row.get(pk_column_name))
|
|
64
|
+
|
|
65
|
+
if current_pk == pk_value
|
|
66
|
+
# Update each changed column value
|
|
67
|
+
@data.each do |column_name, value|
|
|
68
|
+
# Skip if value hasn't changed
|
|
69
|
+
next if @original_data[column_name] == value
|
|
70
|
+
|
|
71
|
+
column = @table.java_table.get_column(column_name)
|
|
72
|
+
cursor.setCurrentRowValue(column, TypeConverter.to_java(value))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Update original data to match current data
|
|
76
|
+
@original_data = @data.dup
|
|
77
|
+
@dirty = false
|
|
78
|
+
|
|
79
|
+
return true
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
raise DatabaseError, "Row not found for update"
|
|
84
|
+
rescue Java::JavaIo::IOException => e
|
|
85
|
+
raise DatabaseError, "Failed to save row: #{e.message}"
|
|
86
|
+
rescue Java::JavaLang::Exception => e
|
|
87
|
+
raise DatabaseError, "Failed to save row: #{e.message}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Delete this row
|
|
92
|
+
def delete
|
|
93
|
+
begin
|
|
94
|
+
# Get primary key to find the row
|
|
95
|
+
pk_index = @table.java_table.get_primary_key_index
|
|
96
|
+
raise DatabaseError, "Cannot delete row: table has no primary key" if pk_index.nil?
|
|
97
|
+
|
|
98
|
+
pk_column_name = pk_index.get_columns.first.get_name
|
|
99
|
+
pk_value = @data[pk_column_name]
|
|
100
|
+
|
|
101
|
+
# Create a new cursor for this delete operation
|
|
102
|
+
cursor = com.healthmarketscience.jackcess.CursorBuilder.create_cursor(@table.java_table)
|
|
103
|
+
|
|
104
|
+
while cursor.move_to_next_row
|
|
105
|
+
current_row = cursor.get_current_row
|
|
106
|
+
current_pk = TypeConverter.from_java(current_row.get(pk_column_name))
|
|
107
|
+
|
|
108
|
+
if current_pk == pk_value
|
|
109
|
+
cursor.deleteCurrentRow
|
|
110
|
+
return true
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
raise DatabaseError, "Row not found for deletion"
|
|
115
|
+
rescue Java::JavaIo::IOException => e
|
|
116
|
+
raise DatabaseError, "Failed to delete row: #{e.message}"
|
|
117
|
+
rescue Java::JavaLang::Exception => e
|
|
118
|
+
raise DatabaseError, "Failed to delete row: #{e.message}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Get all column names
|
|
123
|
+
def keys
|
|
124
|
+
@data.keys
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Get all values
|
|
128
|
+
def values
|
|
129
|
+
@data.values
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Convert to hash
|
|
133
|
+
def to_h
|
|
134
|
+
@data.dup
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Check if row has been modified
|
|
138
|
+
def dirty?
|
|
139
|
+
@dirty
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Reload row from database
|
|
143
|
+
def reload
|
|
144
|
+
begin
|
|
145
|
+
# Get primary key to find the row
|
|
146
|
+
pk_index = @table.java_table.get_primary_key_index
|
|
147
|
+
raise DatabaseError, "Cannot reload row: table has no primary key" if pk_index.nil?
|
|
148
|
+
|
|
149
|
+
pk_column_name = pk_index.get_columns.first.get_name
|
|
150
|
+
pk_value = @original_data[pk_column_name]
|
|
151
|
+
|
|
152
|
+
# Find the row again
|
|
153
|
+
reloaded_row = @table.find_by_id(pk_value)
|
|
154
|
+
|
|
155
|
+
if reloaded_row
|
|
156
|
+
@data = reloaded_row.data.dup
|
|
157
|
+
@original_data = reloaded_row.data.dup
|
|
158
|
+
@dirty = false
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
self
|
|
162
|
+
rescue Java::JavaIo::IOException => e
|
|
163
|
+
raise DatabaseError, "Failed to reload row: #{e.message}"
|
|
164
|
+
rescue Java::JavaLang::Exception => e
|
|
165
|
+
raise DatabaseError, "Failed to reload row: #{e.message}"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def inspect
|
|
170
|
+
"#<Jackcess::Row #{@data.inspect}>"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jackcess
|
|
4
|
+
class Table
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
attr_reader :java_table, :database
|
|
8
|
+
|
|
9
|
+
def initialize(java_table, database)
|
|
10
|
+
@java_table = java_table
|
|
11
|
+
@database = database
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Get table name
|
|
15
|
+
def name
|
|
16
|
+
@java_table.get_name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Iterate through all rows
|
|
20
|
+
def each
|
|
21
|
+
return enum_for(:each) unless block_given?
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
# Create a new cursor for iteration to avoid state issues
|
|
25
|
+
cursor = com.healthmarketscience.jackcess.CursorBuilder.create_cursor(@java_table)
|
|
26
|
+
while cursor.move_to_next_row
|
|
27
|
+
java_row = cursor.get_current_row
|
|
28
|
+
yield Row.new(java_row, self)
|
|
29
|
+
end
|
|
30
|
+
rescue Java::JavaIo::IOException => e
|
|
31
|
+
raise DatabaseError, "Failed to iterate rows: #{e.message}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Add a new row
|
|
36
|
+
def add_row(data)
|
|
37
|
+
raise ArgumentError, "Data cannot be nil" if data.nil?
|
|
38
|
+
raise ArgumentError, "Data must be a Hash" unless data.is_a?(Hash)
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
java_row_data = java.util.HashMap.new
|
|
42
|
+
data.each do |key, value|
|
|
43
|
+
java_row_data.put(key.to_s, TypeConverter.to_java(value))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
java_row = @java_table.add_row_from_map(java_row_data)
|
|
47
|
+
Row.new(java_row, self)
|
|
48
|
+
rescue Java::JavaIo::IOException => e
|
|
49
|
+
raise DatabaseError, "Failed to add row to table '#{name}': #{e.message}"
|
|
50
|
+
rescue Java::JavaLang::Exception => e
|
|
51
|
+
raise DatabaseError, "Failed to add row to table '#{name}': #{e.message}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Find row by primary key
|
|
56
|
+
def find_by_id(id)
|
|
57
|
+
begin
|
|
58
|
+
primary_key_index = @java_table.get_primary_key_index
|
|
59
|
+
|
|
60
|
+
if primary_key_index.nil?
|
|
61
|
+
# No primary key, do a linear search
|
|
62
|
+
each do |row|
|
|
63
|
+
return row if row[primary_key_columns.first] == id
|
|
64
|
+
end
|
|
65
|
+
nil
|
|
66
|
+
else
|
|
67
|
+
# Use index search
|
|
68
|
+
search_map = java.util.HashMap.new
|
|
69
|
+
search_map.put(primary_key_index.get_columns.first.get_name, TypeConverter.to_java(id))
|
|
70
|
+
|
|
71
|
+
java_row = com.healthmarketscience.jackcess.CursorBuilder.find_row(@java_table, search_map)
|
|
72
|
+
java_row ? Row.new(java_row, self) : nil
|
|
73
|
+
end
|
|
74
|
+
rescue Java::JavaIo::IOException => e
|
|
75
|
+
raise DatabaseError, "Failed to find row: #{e.message}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get all columns
|
|
80
|
+
def columns
|
|
81
|
+
@java_table.get_columns.map { |java_col| Column.new(java_col) }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Get column by name
|
|
85
|
+
def column(name)
|
|
86
|
+
raise ArgumentError, "Column name cannot be nil" if name.nil?
|
|
87
|
+
raise ArgumentError, "Column name must be a String or Symbol" unless name.is_a?(String) || name.is_a?(Symbol)
|
|
88
|
+
|
|
89
|
+
name = name.to_s
|
|
90
|
+
begin
|
|
91
|
+
java_col = @java_table.get_column(name)
|
|
92
|
+
raise ColumnNotFoundError, "Column not found: #{name}" if java_col.nil?
|
|
93
|
+
|
|
94
|
+
Column.new(java_col)
|
|
95
|
+
rescue Java::JavaLang::IllegalArgumentException => e
|
|
96
|
+
raise ColumnNotFoundError, "Column not found: #{name}"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Get all indexes
|
|
101
|
+
def indexes
|
|
102
|
+
@java_table.get_indexes.map { |java_idx| Index.new(java_idx) }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Get row count
|
|
106
|
+
def row_count
|
|
107
|
+
@java_table.get_row_count
|
|
108
|
+
end
|
|
109
|
+
alias size row_count
|
|
110
|
+
alias length row_count
|
|
111
|
+
|
|
112
|
+
# Find rows matching the given criteria.
|
|
113
|
+
#
|
|
114
|
+
# This method provides a simple filtering interface for finding rows.
|
|
115
|
+
# For more complex queries, iterate through rows with {#each} and filter manually.
|
|
116
|
+
#
|
|
117
|
+
# @param criteria [Hash] Column name/value pairs to match
|
|
118
|
+
#
|
|
119
|
+
# @return [Array<Row>] Array of matching rows
|
|
120
|
+
#
|
|
121
|
+
# @example Find users by name
|
|
122
|
+
# users = table.where('Name' => 'Alice')
|
|
123
|
+
#
|
|
124
|
+
# @example Find with multiple criteria
|
|
125
|
+
# users = table.where('Name' => 'Bob', 'Active' => true)
|
|
126
|
+
def where(criteria)
|
|
127
|
+
raise ArgumentError, "Criteria cannot be nil" if criteria.nil?
|
|
128
|
+
raise ArgumentError, "Criteria must be a Hash" unless criteria.is_a?(Hash)
|
|
129
|
+
|
|
130
|
+
select { |row| criteria.all? { |key, value| row[key.to_s] == value } }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Find the first row matching the given criteria.
|
|
134
|
+
#
|
|
135
|
+
# @param criteria [Hash] Column name/value pairs to match
|
|
136
|
+
#
|
|
137
|
+
# @return [Row, nil] The first matching row, or nil if no match
|
|
138
|
+
#
|
|
139
|
+
# @example Find first user by name
|
|
140
|
+
# user = table.find_first('Name' => 'Alice')
|
|
141
|
+
def find_first(criteria)
|
|
142
|
+
raise ArgumentError, "Criteria cannot be nil" if criteria.nil?
|
|
143
|
+
raise ArgumentError, "Criteria must be a Hash" unless criteria.is_a?(Hash)
|
|
144
|
+
|
|
145
|
+
detect { |row| criteria.all? { |key, value| row[key.to_s] == value } }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Count rows matching the given criteria.
|
|
149
|
+
#
|
|
150
|
+
# @param criteria [Hash, nil] Column name/value pairs to match (nil counts all rows)
|
|
151
|
+
#
|
|
152
|
+
# @return [Integer] The number of matching rows
|
|
153
|
+
#
|
|
154
|
+
# @example Count all rows
|
|
155
|
+
# table.count # => 100
|
|
156
|
+
#
|
|
157
|
+
# @example Count filtered rows
|
|
158
|
+
# table.count('Active' => true) # => 75
|
|
159
|
+
def count(criteria = nil)
|
|
160
|
+
return row_count if criteria.nil?
|
|
161
|
+
|
|
162
|
+
raise ArgumentError, "Criteria must be a Hash" unless criteria.is_a?(Hash)
|
|
163
|
+
|
|
164
|
+
where(criteria).size
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Check if any rows match the given criteria.
|
|
168
|
+
#
|
|
169
|
+
# @param criteria [Hash] Column name/value pairs to match
|
|
170
|
+
#
|
|
171
|
+
# @return [Boolean] true if at least one row matches, false otherwise
|
|
172
|
+
#
|
|
173
|
+
# @example Check if any active users exist
|
|
174
|
+
# table.any?('Active' => true) # => true
|
|
175
|
+
def any?(criteria)
|
|
176
|
+
raise ArgumentError, "Criteria cannot be nil" if criteria.nil?
|
|
177
|
+
raise ArgumentError, "Criteria must be a Hash" unless criteria.is_a?(Hash)
|
|
178
|
+
|
|
179
|
+
!find_first(criteria).nil?
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
def primary_key_columns
|
|
185
|
+
pk_index = @java_table.get_primary_key_index
|
|
186
|
+
return [] if pk_index.nil?
|
|
187
|
+
|
|
188
|
+
pk_index.get_columns.map(&:get_name)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bigdecimal"
|
|
4
|
+
require "date"
|
|
5
|
+
|
|
6
|
+
module Jackcess
|
|
7
|
+
module TypeConverter
|
|
8
|
+
class << self
|
|
9
|
+
# Convert Java types to Ruby types
|
|
10
|
+
def from_java(value)
|
|
11
|
+
return nil if value.nil?
|
|
12
|
+
|
|
13
|
+
case value
|
|
14
|
+
when Java::JavaLang::String
|
|
15
|
+
value.to_s
|
|
16
|
+
when Java::JavaLang::Integer, Java::JavaLang::Short, Java::JavaLang::Byte
|
|
17
|
+
value.to_i
|
|
18
|
+
when Java::JavaLang::Long
|
|
19
|
+
value.to_i
|
|
20
|
+
when Java::JavaLang::Float, Java::JavaLang::Double
|
|
21
|
+
value.to_f
|
|
22
|
+
when Java::JavaLang::Boolean
|
|
23
|
+
value.boolean_value
|
|
24
|
+
when Java::JavaUtil::Date
|
|
25
|
+
Time.at(value.time / 1000.0)
|
|
26
|
+
when Java::JavaMath::BigDecimal
|
|
27
|
+
BigDecimal(value.to_s)
|
|
28
|
+
when Java::byte[]
|
|
29
|
+
String.from_java_bytes(value)
|
|
30
|
+
else
|
|
31
|
+
value
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Convert Ruby types to Java types
|
|
36
|
+
def to_java(value)
|
|
37
|
+
return nil if value.nil?
|
|
38
|
+
|
|
39
|
+
case value
|
|
40
|
+
when String
|
|
41
|
+
value.to_java
|
|
42
|
+
when Integer
|
|
43
|
+
# Use appropriate Java type based on value range
|
|
44
|
+
if value >= -2_147_483_648 && value <= 2_147_483_647
|
|
45
|
+
java.lang.Integer.new(value)
|
|
46
|
+
else
|
|
47
|
+
java.lang.Long.new(value)
|
|
48
|
+
end
|
|
49
|
+
when Float
|
|
50
|
+
java.lang.Double.new(value)
|
|
51
|
+
when TrueClass, FalseClass
|
|
52
|
+
java.lang.Boolean.new(value)
|
|
53
|
+
when Time
|
|
54
|
+
java.util.Date.new((value.to_f * 1000).to_i)
|
|
55
|
+
when Date
|
|
56
|
+
# Convert Ruby Date to Time first, then to Java Date
|
|
57
|
+
java.util.Date.new((value.to_time.to_f * 1000).to_i)
|
|
58
|
+
when BigDecimal
|
|
59
|
+
java.math.BigDecimal.new(value.to_s)
|
|
60
|
+
else
|
|
61
|
+
value
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Map Ruby type symbols to Jackcess DataType enums
|
|
66
|
+
def ruby_type_to_data_type(type_sym)
|
|
67
|
+
case type_sym
|
|
68
|
+
when :text
|
|
69
|
+
DataType::TEXT
|
|
70
|
+
when :memo
|
|
71
|
+
DataType::MEMO
|
|
72
|
+
when :byte
|
|
73
|
+
DataType::BYTE
|
|
74
|
+
when :int
|
|
75
|
+
DataType::INT
|
|
76
|
+
when :long
|
|
77
|
+
DataType::LONG
|
|
78
|
+
when :float
|
|
79
|
+
DataType::FLOAT
|
|
80
|
+
when :double
|
|
81
|
+
DataType::DOUBLE
|
|
82
|
+
when :currency
|
|
83
|
+
DataType::MONEY
|
|
84
|
+
when :date_time
|
|
85
|
+
DataType::SHORT_DATE_TIME
|
|
86
|
+
when :boolean
|
|
87
|
+
DataType::BOOLEAN
|
|
88
|
+
when :binary
|
|
89
|
+
DataType::BINARY
|
|
90
|
+
when :guid
|
|
91
|
+
DataType::GUID
|
|
92
|
+
else
|
|
93
|
+
raise InvalidTypeError, "Unknown type: #{type_sym}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Map Jackcess DataType to Ruby type symbol
|
|
98
|
+
def data_type_to_ruby_type(data_type)
|
|
99
|
+
case data_type.to_s
|
|
100
|
+
when "TEXT"
|
|
101
|
+
:text
|
|
102
|
+
when "MEMO"
|
|
103
|
+
:memo
|
|
104
|
+
when "BYTE"
|
|
105
|
+
:byte
|
|
106
|
+
when "INT"
|
|
107
|
+
:int
|
|
108
|
+
when "LONG"
|
|
109
|
+
:long
|
|
110
|
+
when "FLOAT"
|
|
111
|
+
:float
|
|
112
|
+
when "DOUBLE"
|
|
113
|
+
:double
|
|
114
|
+
when "MONEY"
|
|
115
|
+
:currency
|
|
116
|
+
when "SHORT_DATE_TIME"
|
|
117
|
+
:date_time
|
|
118
|
+
when "BOOLEAN"
|
|
119
|
+
:boolean
|
|
120
|
+
when "BINARY", "OLE"
|
|
121
|
+
:binary
|
|
122
|
+
when "GUID"
|
|
123
|
+
:guid
|
|
124
|
+
else
|
|
125
|
+
:unknown
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jackcess
|
|
4
|
+
# The current version of the jackcess-rb gem.
|
|
5
|
+
#
|
|
6
|
+
# This follows Semantic Versioning 2.0.0 (https://semver.org/):
|
|
7
|
+
# - MAJOR version: Incompatible API changes
|
|
8
|
+
# - MINOR version: Backwards-compatible functionality additions
|
|
9
|
+
# - PATCH version: Backwards-compatible bug fixes
|
|
10
|
+
VERSION = "0.1.0"
|
|
11
|
+
end
|
data/lib/jackcess.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
unless RUBY_PLATFORM == "java"
|
|
4
|
+
raise LoadError, "jackcess-rb requires JRuby. You are running #{RUBY_DESCRIPTION}"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require "java"
|
|
8
|
+
|
|
9
|
+
# Load the Jackcess JAR and its dependencies
|
|
10
|
+
vendor_dir = File.expand_path("../vendor", __dir__)
|
|
11
|
+
require File.join(vendor_dir, "commons-logging-1.2.jar")
|
|
12
|
+
require File.join(vendor_dir, "commons-lang3-3.13.0.jar")
|
|
13
|
+
require File.join(vendor_dir, "jackcess-4.0.4.jar")
|
|
14
|
+
|
|
15
|
+
# Import necessary Java classes
|
|
16
|
+
java_import "com.healthmarketscience.jackcess.DatabaseBuilder"
|
|
17
|
+
java_import "com.healthmarketscience.jackcess.Database"
|
|
18
|
+
java_import "com.healthmarketscience.jackcess.Table"
|
|
19
|
+
java_import "com.healthmarketscience.jackcess.Column"
|
|
20
|
+
java_import "com.healthmarketscience.jackcess.Row"
|
|
21
|
+
java_import "com.healthmarketscience.jackcess.DataType"
|
|
22
|
+
java_import "com.healthmarketscience.jackcess.ColumnBuilder"
|
|
23
|
+
java_import "com.healthmarketscience.jackcess.TableBuilder"
|
|
24
|
+
|
|
25
|
+
require_relative "jackcess/version"
|
|
26
|
+
require_relative "jackcess/type_converter"
|
|
27
|
+
require_relative "jackcess/database"
|
|
28
|
+
require_relative "jackcess/table"
|
|
29
|
+
require_relative "jackcess/row"
|
|
30
|
+
require_relative "jackcess/column"
|
|
31
|
+
require_relative "jackcess/index"
|
|
32
|
+
require_relative "jackcess/errors"
|
|
33
|
+
|
|
34
|
+
module Jackcess
|
|
35
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jackcess-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: java
|
|
6
|
+
authors:
|
|
7
|
+
- Durable Programming LLC
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: jackcess-rb provides a Ruby-friendly interface to the powerful Jackcess
|
|
13
|
+
Java library, enabling programmatic interaction with Access database files (.mdb
|
|
14
|
+
and .accdb) directly from JRuby.
|
|
15
|
+
email:
|
|
16
|
+
- commercial@durableprogramming.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- CHANGELOG.md
|
|
22
|
+
- LICENSE
|
|
23
|
+
- README.md
|
|
24
|
+
- lib/jackcess.rb
|
|
25
|
+
- lib/jackcess/column.rb
|
|
26
|
+
- lib/jackcess/database.rb
|
|
27
|
+
- lib/jackcess/errors.rb
|
|
28
|
+
- lib/jackcess/index.rb
|
|
29
|
+
- lib/jackcess/row.rb
|
|
30
|
+
- lib/jackcess/table.rb
|
|
31
|
+
- lib/jackcess/type_converter.rb
|
|
32
|
+
- lib/jackcess/version.rb
|
|
33
|
+
- vendor/commons-lang3-3.13.0.jar
|
|
34
|
+
- vendor/commons-logging-1.2.jar
|
|
35
|
+
- vendor/jackcess-4.0.4.jar
|
|
36
|
+
homepage: https://github.com/durableprogramming/jackcess-rb
|
|
37
|
+
licenses:
|
|
38
|
+
- MIT
|
|
39
|
+
metadata:
|
|
40
|
+
homepage_uri: https://github.com/durableprogramming/jackcess-rb
|
|
41
|
+
source_code_uri: https://github.com/durableprogramming/jackcess-rb
|
|
42
|
+
changelog_uri: https://github.com/durableprogramming/jackcess-rb/blob/main/CHANGELOG.md
|
|
43
|
+
rdoc_options: []
|
|
44
|
+
require_paths:
|
|
45
|
+
- lib
|
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: 2.6.0
|
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
56
|
+
requirements:
|
|
57
|
+
- Java 8 or higher
|
|
58
|
+
- JRuby 9.3 or higher
|
|
59
|
+
rubygems_version: 3.6.9
|
|
60
|
+
specification_version: 4
|
|
61
|
+
summary: JRuby interface to the Jackcess library for reading and writing Microsoft
|
|
62
|
+
Access databases
|
|
63
|
+
test_files: []
|