spreadsheet_db_refi 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+