baza 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ source "http://rubygems.org"
6
6
  gem "datet"
7
7
  gem "wref"
8
8
  gem "knjrbfw"
9
+ gem "array_enumerator"
9
10
 
10
11
  # Add dependencies to develop your gem here.
11
12
  # Include everything needed to run rake, tests, features, etc.
@@ -1,6 +1,7 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ array_enumerator (0.0.3)
4
5
  datet (0.0.25)
5
6
  diff-lcs (1.1.3)
6
7
  git (1.2.5)
@@ -46,6 +47,7 @@ PLATFORMS
46
47
  ruby
47
48
 
48
49
  DEPENDENCIES
50
+ array_enumerator
49
51
  bundler (>= 1.0.0)
50
52
  datet
51
53
  jeweler (~> 1.8.4)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.5
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "baza"
8
- s.version = "0.0.4"
8
+ s.version = "0.0.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
@@ -56,6 +56,7 @@ Gem::Specification.new do |s|
56
56
  "spec/db_spec_encoding_test_file.txt",
57
57
  "spec/info_mysql_example.rb",
58
58
  "spec/info_sqlite3.rb",
59
+ "spec/model_handler_spec.rb",
59
60
  "spec/spec_helper.rb"
60
61
  ]
61
62
  s.homepage = "http://github.com/kaspernj/baza"
@@ -71,6 +72,7 @@ Gem::Specification.new do |s|
71
72
  s.add_runtime_dependency(%q<datet>, [">= 0"])
72
73
  s.add_runtime_dependency(%q<wref>, [">= 0"])
73
74
  s.add_runtime_dependency(%q<knjrbfw>, [">= 0"])
75
+ s.add_runtime_dependency(%q<array_enumerator>, [">= 0"])
74
76
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
75
77
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
76
78
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
@@ -81,6 +83,7 @@ Gem::Specification.new do |s|
81
83
  s.add_dependency(%q<datet>, [">= 0"])
82
84
  s.add_dependency(%q<wref>, [">= 0"])
83
85
  s.add_dependency(%q<knjrbfw>, [">= 0"])
86
+ s.add_dependency(%q<array_enumerator>, [">= 0"])
84
87
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
85
88
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
86
89
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -92,6 +95,7 @@ Gem::Specification.new do |s|
92
95
  s.add_dependency(%q<datet>, [">= 0"])
93
96
  s.add_dependency(%q<wref>, [">= 0"])
94
97
  s.add_dependency(%q<knjrbfw>, [">= 0"])
98
+ s.add_dependency(%q<array_enumerator>, [">= 0"])
95
99
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
96
100
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
97
101
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -421,11 +421,11 @@ class Baza::Driver::Sqlite3::Tables::Table
421
421
  end
422
422
 
423
423
  index_arr.each do |index_data|
424
- if index_data.is_a?(String)
424
+ if index_data.is_a?(String) or index_data.is_a?(Symbol)
425
425
  index_data = {:name => index_data, :columns => [index_data]}
426
426
  end
427
427
 
428
- raise "No name was given in data: '#{index_data}'." if !index_data.key?(:name) or index_data[:name].strip.empty?
428
+ raise "No name was given in data: '#{index_data}'." if !index_data.key?(:name) or index_data[:name].to_s.strip.empty?
429
429
  raise "No columns was given on index #{index_data[:name]}." if index_data[:columns].empty?
430
430
 
431
431
  name = index_data[:name]
@@ -1,3 +1,5 @@
1
+ require "#{File.dirname(__FILE__)}/model_handler_sqlhelper.rb"
2
+
1
3
  class Baza::ModelHandler
2
4
  attr_reader :args, :events, :data, :ids_cache, :ids_cache_should
3
5
 
@@ -47,6 +47,8 @@ class Baza::QueryBuffer
47
47
  def update(table, update, terms)
48
48
  STDOUT.puts "Update called on table #{table}." if @debug
49
49
  self.query(@args[:db].update(table, update, terms, :return_sql => true))
50
+ self.flush if @queries_count >= 1000
51
+ return nil
50
52
  end
51
53
 
52
54
  #Shortcut to doing upsert through the buffer instead of through the db-object with the buffer as an argument.
@@ -54,18 +56,15 @@ class Baza::QueryBuffer
54
56
  # buffer.upsert(:users, {:id => 5}, {:name => "Kasper"})
55
57
  def upsert(table, data, terms)
56
58
  @args[:db].upsert(table, data, terms, :buffer => self)
59
+ self.flush if @queries_count >= 1000
60
+ return nil
57
61
  end
58
62
 
59
63
  #Plans to inset a hash into a table. It will only be inserted when flush is called.
60
64
  #===Examples
61
65
  # buffer.insert(:users, {:name => "John Doe"})
62
66
  def insert(table, data)
63
- @lock.synchronize do
64
- @inserts[table] = [] if !@inserts.key?(table)
65
- @inserts[table] << data
66
- @queries_count += 1
67
- end
68
-
67
+ self.query(@args[:db].insert(table, data, :return_sql => true))
69
68
  self.flush if @queries_count >= 1000
70
69
  return nil
71
70
  end
@@ -0,0 +1,394 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require "tmpdir"
3
+
4
+ describe "Objects" do
5
+ it "should be able to cache rows" do
6
+ begin
7
+ require "#{File.dirname(__FILE__)}/../../array_enumerator/lib/array_enumerator"
8
+ rescue LoadError
9
+ require "array_enumerator"
10
+ end
11
+
12
+ require "sqlite3" if RUBY_ENGINE != "jruby"
13
+
14
+ $db_path = "#{Dir.tmpdir}/knjrbfw_objects_cache_test.sqlite3"
15
+ File.unlink($db_path) if File.exists?($db_path)
16
+ $db = Baza::Db.new(:type => :sqlite3, :path => $db_path, :return_keys => "symbols", :debug => false)
17
+
18
+ schema = {
19
+ :tables => {
20
+ "Group" => {
21
+ :columns => [
22
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
23
+ {:name => :groupname, :type => :varchar}
24
+ ]
25
+ },
26
+ "User" => {
27
+ :columns => [
28
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
29
+ {:name => :username, :type => :varchar}
30
+ ]
31
+ }
32
+ }
33
+ }
34
+ Baza::Revision.new.init_db(:schema => schema, :db => $db)
35
+
36
+ class User < Baza::Model; end
37
+
38
+ $ob = Baza::ModelHandler.new(
39
+ :db => $db,
40
+ :datarow => true,
41
+ :require => false,
42
+ :array_enum => true,
43
+ :models => {
44
+ :User => {
45
+ :cache_ids => true
46
+ }
47
+ }
48
+ )
49
+
50
+ $ob.adds(:User, [
51
+ {:username => "User 1"},
52
+ {:username => "User 2"},
53
+ {:username => "User 3"},
54
+ {:username => "User 4"},
55
+ {:username => "User 5"}
56
+ ])
57
+
58
+ raise "Expected user-ID-cache to be 5 but it wasnt: #{$ob.ids_cache[:User].length}" if $ob.ids_cache[:User].length != 5
59
+
60
+ user = $ob.get(:User, 4)
61
+ raise "No user returned." if !user
62
+ $ob.delete(user)
63
+ raise "Expected user-ID-cache to be 4 but it wasnt: #{$ob.ids_cache[:User].length} #{$ob.ids_cache}" if $ob.ids_cache[:User].length != 4
64
+
65
+ $ob.deletes([$ob.get(:User, 1), $ob.get(:User, 2)])
66
+ raise "Expected user-ID-cache to be 2 but it wasnt: #{$ob.ids_cache[:User].length} #{$ob.ids_cache}" if $ob.ids_cache[:User].length != 2
67
+ end
68
+
69
+ it "should be able to do 'select_col_as_array'" do
70
+ res = $ob.list(:User, {"select_col_as_array" => "id"}).to_a
71
+ raise "Expected length of 2 but got: #{res.length}" if res.length != 2
72
+ end
73
+
74
+ it "should work even though stressed by threads (thread-safe)." do
75
+ userd = []
76
+ 10.upto(25) do |i|
77
+ userd << {:username => "User #{i}"}
78
+ end
79
+
80
+ $ob.adds(:User, userd)
81
+ users = $ob.list(:User).to_a
82
+
83
+ #Stress it to test threadsafety...
84
+ threads = []
85
+ 0.upto(5) do |tc|
86
+ threads << Knj::Thread.new do
87
+ 0.upto(5) do |ic|
88
+ user = $ob.add(:User, {:username => "User #{tc}-#{ic}"})
89
+ raise "No user returned." if !user
90
+ $ob.delete(user)
91
+
92
+ user1 = $ob.add(:User, {:username => "User #{tc}-#{ic}-1"})
93
+ user2 = $ob.add(:User, {:username => "User #{tc}-#{ic}-2"})
94
+ user3 = $ob.add(:User, {:username => "User #{tc}-#{ic}-3"})
95
+
96
+ raise "Missing user?" if !user1 or !user2 or !user3 or user1.deleted? or user2.deleted? or user3.deleted?
97
+ $ob.deletes([user1, user2, user3])
98
+
99
+ count = 0
100
+ users.each do |user|
101
+ count += 1
102
+ user[:username] = "#{user[:username]}." if !user.deleted?
103
+ end
104
+
105
+ raise "Expected at least 15 users but got #{count}." if count != 18
106
+ end
107
+ end
108
+ end
109
+
110
+ threads.each do |thread|
111
+ thread.join
112
+ end
113
+ end
114
+
115
+ it "should be able to skip queries when adding" do
116
+ class Group < Baza::Model; end
117
+
118
+ $ob2 = Baza::ModelHandler.new(
119
+ :db => $db,
120
+ :datarow => true,
121
+ :require => false
122
+ )
123
+
124
+ threads = []
125
+ 0.upto(5) do
126
+ threads << Knj::Thread.new do
127
+ 0.upto(5) do
128
+ ret = $ob2.add(:Group, {:groupname => "User 1"}, {:skip_ret => true})
129
+ raise "Expected empty return but got something: #{ret}" if ret
130
+ end
131
+ end
132
+ end
133
+
134
+ threads.each do |thread|
135
+ thread.join
136
+ end
137
+ end
138
+
139
+ it "should delete the temporary database." do
140
+ File.unlink($db_path) if File.exists?($db_path)
141
+ end
142
+
143
+ #Moved from "knjrbfw_spec.rb"
144
+ it "should be able to generate a sample SQLite database and add a sample table, with sample columns and with a sample index to it" do
145
+ $db_path = "#{Knj::Os.tmpdir}/knjrbfw_test_sqlite3.sqlite3"
146
+ $db = Baza::Db.new(
147
+ :type => :sqlite3,
148
+ :path => $db_path,
149
+ :index_append_table_name => true
150
+ )
151
+
152
+ $db.tables.create("Project", {
153
+ :columns => [
154
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
155
+ {:name => :category_id, :type => :int},
156
+ {:name => :name, :type => :varchar}
157
+ ],
158
+ :indexes => [
159
+ {:name => :category_id, :columns => [:category_id]}
160
+ ]
161
+ })
162
+
163
+ $db.tables.create("Task", {
164
+ :columns => [
165
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
166
+ {:name => :project_id, :type => :int},
167
+ {:name => :person_id, :type => :int},
168
+ {:name => :name, :type => :varchar}
169
+ ],
170
+ :indexes => [
171
+ {:name => :project_id, :columns => [:project_id]}
172
+ ]
173
+ })
174
+
175
+ $db.tables.create("Person", {
176
+ :columns => [
177
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
178
+ {:name => :name, :type => :varchar}
179
+ ]
180
+ })
181
+
182
+ $db.tables.create("Timelog", {
183
+ :columns => [
184
+ {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
185
+ {:name => :person_id, :type => :int}
186
+ ],
187
+ :indexes => [
188
+ :person_id
189
+ ]
190
+ })
191
+
192
+ table = $db.tables[:Project]
193
+
194
+ indexes = table.indexes
195
+ raise "Could not find the sample-index 'category_id' that should have been created." if !indexes[:Project__category_id]
196
+
197
+
198
+ #If we insert a row the ID should increase and the name should be the same as inserted (or something is very very wrong)...
199
+ $db.insert("Project", {
200
+ "name" => "Test project"
201
+ })
202
+
203
+ count = 0
204
+ $db.q("SELECT * FROM Project") do |d|
205
+ raise "Somehow name was not 'Test project'" if d[:name] != "Test project"
206
+ raise "ID was not set?" if d[:id].to_i <= 0
207
+ count += 1
208
+ end
209
+
210
+ raise "Expected count of 1 but it wasnt: #{count}" if count != 1
211
+ end
212
+
213
+ it "should be able to automatic generate methods on datarow-classes (has_many, has_one)." do
214
+ class Project < Baza::Model
215
+ has_many [
216
+ {:class => :Task, :col => :project_id, :depends => true}
217
+ ]
218
+ end
219
+
220
+ class Task < Baza::Model
221
+ has_one [
222
+ {:class => :Person, :required => true},
223
+ :Project
224
+ ]
225
+ end
226
+
227
+ class Person < Baza::Model
228
+ has_one [:Project]
229
+
230
+ has_many [
231
+ {:class => :Timelog, :autozero => true}
232
+ ]
233
+
234
+ def html
235
+ return self[:name]
236
+ end
237
+ end
238
+
239
+ class Timelog < Baza::Model
240
+
241
+ end
242
+
243
+ $ob = Baza::ModelHandler.new(:db => $db, :datarow => true, :require => false)
244
+
245
+ $ob.add(:Person, {
246
+ :name => "Kasper"
247
+ })
248
+ $ob.add(:Task, {
249
+ :name => "Test task",
250
+ :person_id => 1,
251
+ :project_id => 1
252
+ })
253
+
254
+ begin
255
+ $obb.add(:Task, {:name => "Test task"})
256
+ raise "Method should fail but didnt."
257
+ rescue
258
+ #ignore.
259
+ end
260
+
261
+
262
+ #Test 'list_invalid_required'.
263
+ $db.insert(:Task, :name => "Invalid require")
264
+ id = $db.last_id
265
+ found = false
266
+
267
+ $ob.list_invalid_required(:class => :Task) do |d|
268
+ raise "Expected object ID to be #{id} but it wasnt: #{d[:obj].id}" if d[:obj].id.to_i != id.to_i
269
+ $ob.delete(d[:obj])
270
+ found = true
271
+ end
272
+
273
+ raise "Expected to find a task but didnt." if !found
274
+
275
+
276
+ ret_proc = []
277
+ $ob.list(:Task) do |task|
278
+ ret_proc << task
279
+ end
280
+
281
+ raise "list with proc should return one task but didnt." if ret_proc.length != 1
282
+
283
+
284
+ project = $ob.get(:Project, 1)
285
+
286
+ tasks = project.tasks
287
+ raise "No tasks were found on project?" if tasks.empty?
288
+
289
+
290
+ ret_proc = []
291
+ ret_test = project.tasks do |task|
292
+ ret_proc << task
293
+ end
294
+
295
+ raise "When given a block the return should be nil so it doesnt hold weak-ref-objects in memory but it didnt return nil." if ret_test != nil
296
+ raise "list for project with proc should return one task but didnt (#{ret_proc.length})." if ret_proc.length != 1
297
+
298
+ person = tasks.first.person
299
+ project_second = tasks.first.project
300
+
301
+ raise "Returned object was not a person on task." if !person.is_a?(Person)
302
+ raise "Returned object was not a project on task." if !project_second.is_a?(Project)
303
+
304
+
305
+ #Check that has_many-depending is actually working.
306
+ begin
307
+ $ob.delete(project)
308
+ raise "It was possible to delete project 1 even though task 1 depended on it!"
309
+ rescue
310
+ #this should happen - it should not possible to delete project 1 because task 1 depends on it."
311
+ end
312
+ end
313
+
314
+ it "should be able to generate lists for inputs" do
315
+ Knj::Web.inputs([{
316
+ :title => "Test 3",
317
+ :name => :seltest3,
318
+ :type => :select,
319
+ :default => 1,
320
+ :opts => $ob.list_optshash(:Task)
321
+ }])
322
+ end
323
+
324
+ it "should be able to connect to objects 'no-html' callback and test it." do
325
+ task = $ob.get(:Task, 1)
326
+ $ob.events.connect(:no_html) do |event, classname|
327
+ "[no #{classname.to_s.downcase}]"
328
+ end
329
+
330
+ raise "Unexpected person_html from task (should have been 'Kasper'): '#{task.person_html}'." if task.person_html != "Kasper"
331
+ task.update(:person_id => 0)
332
+ raise "Unexpected person_html from task (should have been '[no person]')." if task.person_html != "[no person]"
333
+ end
334
+
335
+ it "should be able to to multiple additions and delete objects through a buffer" do
336
+ objs = []
337
+ 0.upto(500) do
338
+ objs << {:name => :Kasper}
339
+ end
340
+
341
+ $ob.adds(:Person, objs)
342
+ pers_length = $ob.list(:Person, "count" => true)
343
+
344
+ count = 0
345
+ $db.q_buffer do |buffer|
346
+ $ob.list(:Person) do |person|
347
+ count += 1
348
+ $ob.delete(person, :db_buffer => buffer)
349
+ end
350
+
351
+ buffer.flush
352
+ end
353
+
354
+ raise "Expected count to be #{pers_length} but it wasnt: #{count}" if count != pers_length
355
+
356
+ persons = $ob.list(:Person).to_a
357
+ raise "Expected persons count to be 0 but it wasnt: #{persons.map{|e| e.data} }" if persons.length > 0
358
+ end
359
+
360
+ it "should do autozero when deleting objects" do
361
+ person1 = $ob.add(:Person, {
362
+ :name => "Kasper"
363
+ })
364
+ person2 = $ob.add(:Person, {
365
+ :name => "Charlotte"
366
+ })
367
+
368
+ timelog1 = $ob.add(:Timelog, {
369
+ :person_id => person1.id
370
+ })
371
+ timelog2 = $ob.add(:Timelog, {
372
+ :person_id => person2.id
373
+ })
374
+
375
+ $ob.delete(person1)
376
+
377
+ raise "Expected timelog1's person-ID to be zero but it wasnt: '#{timelog1[:person_id]}'." if timelog1[:person_id].to_i != 0
378
+ raise "Expected timelog2's person-ID to be #{person2.id} but it wasnt: '#{timelog2[:person_id]}'." if timelog2[:person_id].to_i != person2.id.to_i
379
+ end
380
+
381
+ it "should be able to do multiple deletes from ids" do
382
+ ids = []
383
+ 1.upto(10) do |count|
384
+ ids << $ob.add(:Person).id
385
+ end
386
+
387
+ $ob.delete_ids(:class => :Person, :ids => ids)
388
+ end
389
+
390
+ it "should delete the temp database again." do
391
+ db_path = "#{Knj::Os.tmpdir}/knjrbfw_test_sqlite3.sqlite3"
392
+ File.unlink(db_path) if File.exists?(db_path)
393
+ end
394
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baza
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: array_enumerator
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: rspec
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -202,6 +218,7 @@ files:
202
218
  - spec/db_spec_encoding_test_file.txt
203
219
  - spec/info_mysql_example.rb
204
220
  - spec/info_sqlite3.rb
221
+ - spec/model_handler_spec.rb
205
222
  - spec/spec_helper.rb
206
223
  homepage: http://github.com/kaspernj/baza
207
224
  licenses:
@@ -218,7 +235,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
235
  version: '0'
219
236
  segments:
220
237
  - 0
221
- hash: 3400246052753672673
238
+ hash: -3065201151015911898
222
239
  required_rubygems_version: !ruby/object:Gem::Requirement
223
240
  none: false
224
241
  requirements: