spreadsheet_db_refi 0.0.0

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.
Files changed (2) hide show
  1. data/lib/spreadsheet_db_refi.rb +332 -0
  2. metadata +78 -0
@@ -0,0 +1,332 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'sqlite3'
4
+
5
+ module Refi
6
+
7
+ # stores spreadsheet data in a sqlite database
8
+ class SpreadsheetDb
9
+ @@std_create_tbls_strs = {
10
+ metadata: %q(
11
+ create table metadata(
12
+ nam text,
13
+ val text,
14
+
15
+ primary key(nam)
16
+ );
17
+ ),
18
+ sheet: %q(
19
+ create table sheet(
20
+ id integer,
21
+ nam text,
22
+ pos integer,
23
+
24
+ primary key(id),
25
+ unique(nam),
26
+ unique(pos)
27
+ );
28
+ ),
29
+ typ: %q(
30
+ create table typ(
31
+ id integer,
32
+ nam text,
33
+ mcv text,
34
+
35
+ primary key(id),
36
+ unique(nam)
37
+ );
38
+ ),
39
+ cell: %q(
40
+ create table cell(
41
+ sheet_id integer,
42
+ row integer,
43
+ col integer,
44
+ val text,
45
+ typ_id integer,
46
+
47
+ primary key(sheet_id, row, col),
48
+ foreign key(sheet_id) references sheet(id),
49
+ foreign key(typ_id) references typ(id)
50
+ );
51
+ )
52
+ }.inject({}){|memo,(k,v)| memo[k] = v.strip_a_lot ; memo}
53
+ @@std_tbl_create_order = [:metadata, :sheet, :typ, :cell]
54
+ @@std_stmts_strs = {
55
+ metadata_set_nam_val: "insert or replace into metadata(nam,val) values(?,?);",
56
+ metadata_get_all: "select * from metadata;",
57
+ metadata_get_val_by_nam: "select val from metadata where nam=?;",
58
+ metadata_del_val_by_nam: "delete from metadata where nam=?;",
59
+ metadata_wipe: "delete from metadata;",
60
+ sheet_set_id_nam_pos: "insert or replace into sheet(id,nam,pos) values(?,?,?);",
61
+ sheet_get_id_by_nam: "select id from sheet where nam=?;",
62
+ sheet_get_nam_by_id: "select nam from sheet where id=?",
63
+ sheet_get_all: "select * from sheet;",
64
+ typ_set_id_nam_mcv: "insert or replace into typ(id,nam,mcv) values(?,?,?);",
65
+ typ_get_all_by_nam: "select * from typ where nam=?",
66
+ cell_set_sheet_row_col_val_typ: "insert or replace into cell(sheet_id,row,col,val,typ_id) values(?,?,?,?,?);",
67
+ cell_get: "select val,typ_id from cell where sheet_id=? and row=? and col=?;",
68
+ get_min_col: "select min(col) from cell where sheet_id=?;",
69
+ get_max_col: "select max(col) from cell where sheet_id=?;",
70
+ get_min_row: "select min(row) from cell where sheet_id=?;",
71
+ get_max_row: "select max(row) from cell where sheet_id=?;",
72
+ get_row: "select col,val,typ_id from cell where sheet_id=? and row=?;",
73
+ get_col: "select row,val,typ_id from cell where sheet_id=? and col=?;",
74
+ sqlite_get_tbl_nam_by_nam: "select name from sqlite_master where name=?;",
75
+ }
76
+ attr_accessor :db
77
+ def initialize(db_pn=nil)
78
+ @create_tbls_strs = @@std_create_tbls_strs
79
+ @stmts_strs = @@std_stmt_strs
80
+ @tbl_create_order = @@std_tbl_create_order
81
+ init2(db_pn)
82
+ end
83
+ def init2(db_pn=nil)
84
+ @is_open = false
85
+ reset
86
+ if(db_pn)
87
+ @db_pn = db_pn
88
+ open
89
+ end
90
+ end
91
+ def reset
92
+ if @is_open
93
+ @prep_stmts.each{|sym,prep_stmt| prep_stmt.close }
94
+ @db.close
95
+ end
96
+ @prep_stmts = {}
97
+ @db = nil
98
+ @is_open = false
99
+ @empty_cell_default_value = ''
100
+ end
101
+ def open
102
+ exist_prior = File.exist?(@db_pn)
103
+ if(exist_prior)
104
+ if(File.zero?(@db_pn))
105
+ File.delete(@db_pn)
106
+ exist_prior = false
107
+ end
108
+ end
109
+ @db = SQLite3::Database.new(@db_pn)
110
+ enhance_db_funcs
111
+
112
+ if(exist_prior)
113
+ assert_db_well_formed({exist_prior: exist_prior,on_err_exit: true})
114
+ prepare_statements
115
+ else
116
+ @db.transaction{|foo|
117
+ create_tables
118
+ prepare_statements
119
+ insert_minimum_records
120
+ }
121
+ assert_db_well_formed({exist_prior: exist_prior,on_err_exit: true})
122
+ end
123
+ @is_open = true
124
+ end
125
+ def create_tables
126
+ @tbl_create_order.each{|tbl_nam|
127
+ db.execute(@create_tbls_strs[tbl_nam])
128
+ }
129
+ end
130
+ def insert_minimum_records # requires prepared statements
131
+ @prep_stmts[:typ_set_id_nam_mcv].execute([nil,'std','{}'])
132
+ end
133
+ def assert_db_well_formed(p={}) # requires good tables(with minimum records) and prepared statements
134
+ exist_prior = p[:exist_prior] || false
135
+ on_err_exit = p[:on_err_exit] || true
136
+ good = true
137
+ @tbl_create_order.each{|sym|
138
+ nam = sym.to_s
139
+ # @prep_stmts is not ready yet
140
+ found_table = @db.execute(@stmts_strs[:sqlite_get_tbl_nam_by_nam],nam)[0] == [nam]
141
+ #found_table = @prep_stmts[:sqlite_get_tbl_name_by_name].execute(sym.to_s).size == 1
142
+ if(!found_table)
143
+ good = false
144
+ # missing table
145
+ $Log.tlog({id: 'err1122',table:sym.to_s})
146
+ end
147
+ }
148
+ if(!good)
149
+ if(exist_prior)
150
+ dperr(120,"existing db not well formed (pn:#{db_pn})",true,on_err_exit)
151
+ else
152
+ dperr(121,"new db not well formed (pn:#{db_pn})",true,on_err_exit)
153
+ end
154
+ end
155
+ return good
156
+ end
157
+ def enhance_db_funcs
158
+ $sqlite_enhance_funcs.each{|func_nam,func|
159
+ @db.create_function(func_nam,func[:func_body].arity + 1,func[:return_type], &func[:func_body])
160
+ }
161
+ end
162
+ def prepare_statements
163
+ @stmts_strs.each{|sym,stmt_str|
164
+ @prep_stmts[sym] = @db.prepare(stmt_str)
165
+ }
166
+ end
167
+ def get_metadata
168
+ if @db
169
+ return Hash[ @prep_stmts[:metadata_get_all].execute!() ]
170
+ else
171
+ return nil
172
+ end
173
+ end
174
+ def create_sheet(sheet_name,pos_ix)
175
+ @prep_stmts[:sheet_set_id_nam_pos].execute(nil,sheet_name,pos_ix)
176
+ new_sheet_id = @prep_stmts[:sheet_get_id_by_nam].execute!(sheet_name).flatten[0]
177
+ return new_sheet_id
178
+ end
179
+ def get_sheet_id_from_xid(sheet_xid)
180
+ if(sheet_xid.is_a?(String))
181
+ return @prep_stmts[:sheet_get_id_by_nam].execute!(sheet_xid).flatten[0]
182
+ elsif(sheet_xid.is_a?(Fixnum))
183
+ return sheet_xid
184
+ end
185
+ end
186
+ def get_sheet_name_from_xid(sheet_xid)
187
+ if(sheet_xid.is_a?(String))
188
+ return sheet_xid
189
+ elsif(sheet_xid.is_a?(Fixnum))
190
+ return @prep_stmts[:sheet_get_nam_by_id].execute!(sheet_xid).flatten[0]
191
+ end
192
+ end
193
+ def prep_ex(sym,p_ary=[])
194
+ return @prep_stmts[sym].execute!(p_ary)
195
+ end
196
+ def get_sheet_name_by_id(sheet_id)
197
+ return prep_ex(:sheet_get_nam_by_id,[sheet_id])[0]
198
+ end
199
+ def set_cell(sheet_id,row,col,value,type)
200
+ prep_ex(:cell_set_sheet_row_col_val_typ,[sheet_id,row,col,value,type])
201
+ end
202
+ def import_sheet(sheet_id,ss)
203
+ $Log.tlog({id: 'info1045'})
204
+ $Log.indent
205
+ #dputi("import all rows of sheet into cache")
206
+ #metadata = get_metadata
207
+ # CUR
208
+ row_a = ss.first_row
209
+ row_e = ss.last_row
210
+ col_a = ss.first_column
211
+ col_e = ss.last_column
212
+ @db.transaction{|dbi|
213
+ row_a.upto(row_e){|row_i|
214
+ col_a.upto(col_e){|col_i|
215
+ #pp ss
216
+ #puts row_i
217
+ #puts col_i
218
+ cell_value = ss.cell(row_i,col_i)
219
+ value = ''
220
+ # TODO use hash?
221
+ if(cell_value == nil)
222
+ # TODO
223
+ #dparn(117,"empty cell (#{@ss_pn}:#{sheet_id}:#{row_i}:#{col_i}) using default value:'#{@empty_cell_default_value}'")
224
+ if(@empty_cell_default_value==nil)
225
+ dparn(777,"no empty cell default value using builtin string of the form 'XXX_empty_cell(...)'")
226
+ value = "XXX_empty_cell(#{@ss_pn}:#{sheet_id}:#{row_i}:#{col_i})"
227
+ else
228
+ value = @empty_cell_default_value
229
+ end
230
+ elsif(cell_value.is_a?(String))
231
+ value = cell_value
232
+ elsif(cell_value.is_a?(Date))
233
+ value = cell_value.iso8601
234
+ elsif(cell_value.is_a?(Float))
235
+ value = cell_value
236
+ elsif(cell_value.is_a?(NilClass))
237
+ dperr(113,"NilClass in cell")
238
+ else
239
+ dpev cell_value.class
240
+ dperr(1375, "#{__FILE__} #{__LINE__}")
241
+ end
242
+ type = 1
243
+ set_cell(sheet_id,row_i,col_i,value,type)
244
+ }
245
+ print 'c'
246
+ }
247
+ #dput
248
+ $Log.undent
249
+ }
250
+ #dpun
251
+ $Log.undent
252
+ end
253
+ def get_sheet(sheet_xid)
254
+ sheet_id = get_sheet_id_from_xid(sheet_xid)
255
+ new_sheet = SsDbSheet.new(self,sheet_id)
256
+ return new_sheet
257
+ end
258
+ end
259
+
260
+ class SsDbCellValue
261
+ attr_accessor :value
262
+ attr_accessor :type_id
263
+ def initialize(value,type_id)
264
+ dperr(131,"'value' is not of type 'String' (type:'#{value.class}'") if !value.is_a?(String)
265
+ dperr(132,"'type_id' is not of type 'Fixnum' (type:'#{type_id.class}'") if !type_id.is_a?(Fixnum)
266
+ @value = value
267
+ @type_id = type_id
268
+ end
269
+ end
270
+
271
+ class SsDbSheet
272
+ def initialize(ss_db,sheet_id)
273
+ @ss_db = ss_db
274
+ @sheet_id = sheet_id
275
+ end
276
+ def prep_ex(sym,p_ary=[])
277
+ @ss_db.prep_ex(sym,p_ary)
278
+ end
279
+ def get_dims
280
+ {
281
+ col: {
282
+ min: prep_ex(:get_min_col,[@sheet_id])[0][0],
283
+ max: prep_ex(:get_max_col,[@sheet_id])[0][0],
284
+ },
285
+ row: {
286
+ min: prep_ex(:get_min_row,[@sheet_id])[0][0],
287
+ max: prep_ex(:get_max_row,[@sheet_id])[0][0],
288
+ },
289
+ }
290
+ end
291
+ def get_row(i,t=false)
292
+ q = if(t)
293
+ :get_col
294
+ else
295
+ :get_row
296
+ end
297
+ row = prep_ex(q,[@sheet_id,i]).inject({}){|memo,j|
298
+ memo[ j[0] ] = SsDbCellValue.new( j[1], j[2])
299
+ memo
300
+ }
301
+ return row
302
+ end
303
+ def get_cell(r,c,t=false) # row col transpose
304
+ r,c = c,r if t
305
+ value,type_id = *prep_ex(:cell_get,[@sheet_id,r,c])[0]
306
+ return SsDbCellValue.new(value,type_id)
307
+ end
308
+ def get_col(i,transpose=false)
309
+ return get_row(i,!transpose)
310
+ end
311
+
312
+ # if t is true rows and columns are transposed
313
+ def get_first_row(t=false)
314
+ return get_first_col if t
315
+ return prep_ex(:get_min_row)
316
+ end
317
+ def get_last_row(t=false)
318
+ return get_last_col if t
319
+ return prep_ex(:get_max_row)
320
+ end
321
+ def get_first_col(t=false)
322
+ return get_first_row if t
323
+ return prep_ex(:get_min_col)
324
+ end
325
+ def get_last_col(t=false)
326
+ return get_last_row if t
327
+ return prep_ex(:get_max_col)
328
+ end
329
+ end
330
+
331
+
332
+ end # module Refi
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spreadsheet_db_refi
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Robert Fey
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-26 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sqlite3-ruby
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - "="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 3
31
+ - 3
32
+ version: 1.3.3
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: store spreadsheet data in a sqilte db
36
+ email: feyrob@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/spreadsheet_db_refi.rb
45
+ has_rdoc: true
46
+ homepage: http://rubygems.org/gems/spreadsheet_db_refi
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project: nowarning
73
+ rubygems_version: 1.3.7
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: ""
77
+ test_files: []
78
+