Rubernate 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -32,8 +32,7 @@ module Callbacks
32
32
  end
33
33
 
34
34
  # Invoked if object referred by this one has been deleted
35
- # TODO: implement invokations
36
- def on_lose_ref refered_by
35
+ def on_lose_ref ref_prop, ref_obj
37
36
  end
38
37
  end
39
38
 
@@ -21,6 +21,16 @@ module DBI
21
21
  HASH_TIME_REF = (PARAM_FLAG_HASH | PARAM_FLAG_TIME).to_i
22
22
  HASH_DATE_REF = (PARAM_FLAG_HASH | PARAM_FLAG_DATE).to_i
23
23
 
24
+ # Indexes of columns of R_PARAMS table
25
+ P_PK = 0
26
+ P_NAME = 1
27
+ P_FLAGS = 2
28
+ P_INT = 3
29
+ P_FLT = 4
30
+ P_STR = 5
31
+ P_TIME = 6
32
+ P_REF = 7
33
+
24
34
  # Holds configuration information and serves as factory for Runtime objects.
25
35
  class Configuration
26
36
  # Accepts Runtime impl class, db initializer class, database url, user name, and user password
@@ -69,6 +79,9 @@ module DBI
69
79
  DELETE_OBJECT = <<-SQL
70
80
  DELETE FROM R_OBJECTS WHERE OBJECT_PK = ?
71
81
  SQL
82
+ CREATE_PEER = <<-SQL
83
+ INSERT INTO R_OBJECTS (OBJECT_PK, OBJECT_CLASS) values (?, ?)
84
+ SQL
72
85
  SAVE_PARAMS = <<-SQL
73
86
  INSERT INTO R_PARAMS VALUES (?, ?, ?, ?, ?, ?, ?, ?)
74
87
  SQL
@@ -87,17 +100,9 @@ module DBI
87
100
  WHERE O.OBJECT_PK = ?
88
101
  SQL
89
102
 
90
- # R_PARAMS table's column's indexes
91
- P_PK = 0
92
- P_NAME = 1
93
- P_FLAGS = 2
94
- P_INT = 3
95
- P_FLT = 4
96
- P_STR = 5
97
- P_TIME = 6
98
- P_REF = 7 # Refered object PK
99
- P_REF_CLASS = 8 # Refered object Class
100
- P_CLASS = 9 # Self object Class
103
+ # Adition columns for R_PARAMS table joined ...
104
+ P_REF_CLASS = 8 # with REF_VALUE
105
+ P_CLASS = 9 # with OBJECT_PK
101
106
 
102
107
  attr :dbh, false
103
108
 
@@ -116,7 +121,7 @@ module DBI
116
121
  @dbh.prepare SAVE_PARAMS do |sth|
117
122
  for object in objects
118
123
  object.peer.each {|name, param|
119
- save_param sth, object.primary_key, name.to_s, param
124
+ save_param sth, object, name.to_s, param
120
125
  }
121
126
  end
122
127
  end
@@ -184,16 +189,16 @@ module DBI
184
189
  @dbh.disconnect rescue Log.error 'Error during disconnect in session failed state'
185
190
  end
186
191
  private
187
- def save_param sth, pk, name, param
192
+ def save_param sth, obj, name, param
188
193
  case param
189
- when Persistent: save_ref sth, pk, name, param
190
- when Hash: save_hash sth, pk, name, param
191
- when Array: save_array sth, pk, name, param
192
- when Integer: save_int sth, pk, name, param
193
- when Float: save_float sth, pk, name, param
194
- when Time: save_time sth, pk, name, param
195
- when Date: save_date sth, pk, name, param
196
- else save_str sth, pk, name, param.to_s
194
+ when Persistent: save_ref sth, obj, name, param
195
+ when Hash: save_hash sth, obj, name, param
196
+ when Array: save_array sth, obj, name, param
197
+ when Integer: save_int sth, obj.primary_key, name, param
198
+ when Float: save_float sth, obj.primary_key, name, param
199
+ when Time: save_time sth, obj.primary_key, name, param
200
+ when Date: save_date sth, obj.primary_key, name, param
201
+ else save_str sth, obj.primary_key, name, param.to_s
197
202
  end
198
203
  end
199
204
 
@@ -217,16 +222,17 @@ module DBI
217
222
  sth.execute pk, name, PARAM_FLAG_DATE, nil, nil, nil, TimeType.new(date), nil
218
223
  end
219
224
 
220
- def save_ref sth, pk, name, ref
221
- sth.execute pk, name, PARAM_FLAG_REF, nil, nil, nil, nil, ref.primary_key unless ref.removed?
225
+ def save_ref sth, obj, name, ref
226
+ sth.execute obj.primary_key, name, PARAM_FLAG_REF, nil, nil, nil, nil,
227
+ ref.primary_key unless ref_lost? obj, name, ref
222
228
  end
223
229
 
224
- def save_hash sth, pk, name, hash
225
- hash.delete_if {|key, ref| ref.removed?} # Discard removed objects
230
+ def save_hash sth, obj, name, hash
231
+ ref_lost_hash obj, name, hash
226
232
  if hash.empty?
227
- sth.execute pk, name, PARAM_FLAG_HASH, 0, nil, nil, nil, nil
233
+ sth.execute obj.primary_key, name, PARAM_FLAG_HASH, 0, nil, nil, nil, nil
228
234
  else
229
- hash.each {|key, ref| save_key_value sth, pk, name, key, ref.primary_key}
235
+ hash.each {|key, ref| save_key_value sth, obj.primary_key, name, key, ref.primary_key}
230
236
  end
231
237
  end
232
238
 
@@ -235,20 +241,20 @@ module DBI
235
241
  when Integer: sth.execute pk, name, HASH_INT_REF, key, nil, nil, nil, ref
236
242
  when Float: sth.execute pk, name, HASH_FLOAT_REF, nil, key, nil, nil, ref
237
243
  when String: sth.execute pk, name, HASH_STRING_REF, nil, nil, key, nil, ref
238
- when ::Date: sth.execute pk, name, HASH_DATE_REF, nil, nil, nil, TimeType.new(key), ref
239
- when ::Time: sth.execute pk, name, HASH_TIME_REF, nil, nil, nil, TimeType.new(key), ref
244
+ when ::Date: sth.execute pk, name, HASH_DATE_REF, nil, nil, nil, TimeType.new(key), ref
245
+ when ::Time: sth.execute pk, name, HASH_TIME_REF, nil, nil, nil, TimeType.new(key), ref
240
246
  when nil: sth.execute pk, name, PARAM_FLAG_HASH, nil, nil, nil, nil, ref
241
247
  else
242
248
  raise "invalid hash key value #{key}"
243
249
  end
244
250
  end
245
251
 
246
- def save_array sth, pk, name, array
247
- array.delete_if {|ref| !ref or ref.removed?} # Discard removed and nil items
252
+ def save_array sth, obj, name, array
253
+ ref_lost_array obj, name, array
248
254
  if array.empty? # Empty arrays should also be stored
249
- sth.execute pk, name, ARRAY_INT_REF, 0, nil, nil, nil, nil
255
+ sth.execute obj.primary_key, name, ARRAY_INT_REF, 0, nil, nil, nil, nil
250
256
  else
251
- array.each_index {|idx| sth.execute pk, name,
257
+ array.each_index {|idx| sth.execute obj.primary_key, name,
252
258
  ARRAY_INT_REF, idx, nil, nil, nil, array[idx].primary_key}
253
259
  end
254
260
  end
@@ -1,4 +1,5 @@
1
1
  require 'dbi'
2
+ require 'rubernate/impl/dbi_generic'
2
3
 
3
4
  module Rubernate
4
5
  module DBI
@@ -1,4 +1,5 @@
1
1
  require 'dbi'
2
+ require 'rubernate/impl/dbi_generic'
2
3
 
3
4
  module Rubernate
4
5
  module DBI
@@ -6,9 +7,6 @@ module DBI
6
7
  SELECT_NEXT_PK = <<-SQL
7
8
  SELECT R_PK_SEQUENCE.NEXTVAL FROM DUAL
8
9
  SQL
9
- CREATE_PEER = <<-SQL
10
- INSERT INTO R_OBJECTS (OBJECT_PK, OBJECT_CLASS) values (?, ?)
11
- SQL
12
10
 
13
11
  # Creates record in r_objects for specified object
14
12
  def create object
@@ -0,0 +1,33 @@
1
+ require 'dbi'
2
+ require 'rubernate/impl/dbi_generic'
3
+
4
+ module Rubernate
5
+ module DBI
6
+ class PgRuntime < Runtime
7
+ SELECT_NEXT_PK = <<-SQL
8
+ SELECT NEXTVAL('R_PK_SEQUENCE')
9
+ SQL
10
+
11
+ # Invokes super and then issues 'BEGIN'
12
+ def initialize dbh
13
+ super
14
+ dbh.do 'BEGIN'
15
+ end
16
+
17
+ # Creates record in r_objects for specified object
18
+ def create object
19
+ object.peer = Rubernate::Peer.new
20
+ object.primary_key = @dbh.select_one(SELECT_NEXT_PK)[0].to_i
21
+ @dbh.do CREATE_PEER, object.primary_key, object.class.name
22
+ object.peer.dirty = true
23
+ object.primary_key
24
+ end
25
+
26
+ # Issues 'COMMIT' against database.
27
+ def close
28
+ dbh.do 'COMMIT'
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,9 +1,11 @@
1
1
  require 'rubernate/queries'
2
2
 
3
3
  module Rubernate
4
+ # This module contains implementation of Runtime that operates with memory instead database.
5
+ # It is intended only of testing.
4
6
  module Memory
5
7
  module Queries
6
- class Query < Rubernate::Queries::Generic::Expr
8
+ class Query < Rubernate::Queries::Expr
7
9
  def params v
8
10
  case v
9
11
  when Array: v
@@ -12,6 +14,7 @@ module Memory
12
14
  end
13
15
  end
14
16
  end
17
+
15
18
  class Factory < Rubernate::Queries::Factory
16
19
  def initialize
17
20
  super
@@ -19,6 +22,7 @@ module Memory
19
22
  end
20
23
  end
21
24
  end
25
+
22
26
  class Reference
23
27
  attr_reader :primary_key, :object_class
24
28
  def initialize pk, klass
@@ -101,24 +105,26 @@ module Memory
101
105
  def save objects
102
106
  objects = [objects] unless objects.kind_of? Array
103
107
  for object in objects
104
- @database[object.primary_key] = [object.class, save_peer(object.peer)]
108
+ @database[object.primary_key] = [object.class, save_peer(object)]
105
109
  object.peer.dirty = false
106
110
  end
107
111
  end
108
112
 
109
- def save_peer peer
113
+ def save_peer obj
110
114
  result = {}
111
- peer.each {|key, value| result[key] = save_param value }
115
+ obj.peer.each {|key, value| result[key] = save_param obj, key, value}
112
116
  result
113
117
  end
114
118
 
115
- def save_param value
119
+ def save_param obj, param, value
116
120
  case value
117
- when Persistent:
118
- Reference.new value.primary_key, value.class
121
+ when Persistent:
122
+ Reference.new value.primary_key, value.class unless ref_lost? obj, param, value
119
123
  when Array:
124
+ ref_lost_array obj, param, value
120
125
  value.collect{ |item| Reference.new item.primary_key, item.class }
121
126
  when Hash:
127
+ ref_lost_hash obj, param, value
122
128
  result = {}
123
129
  value.each {|key, value|
124
130
  result[key] = Reference.new value.primary_key, value.class
@@ -0,0 +1,25 @@
1
+ require 'erb'
2
+
3
+ module Rubernate
4
+ module DBI
5
+ # Base class for all database intitalizators
6
+ class GenericInit
7
+ # Used to remove leading spaces in scripts
8
+ INDENT = /^ /
9
+
10
+ # Prints initialization script and tryes to initialize databaes database if dbh is given.
11
+ # Must be implemented by subclasses.
12
+ def init_db dbh=nil
13
+ raise 'Not implemented...'
14
+ end
15
+
16
+ private
17
+ def exec_ddl dbh, stat
18
+ dbh.do stat
19
+ 'done'
20
+ rescue Exception => e
21
+ "failed: #{e}"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,13 +1,14 @@
1
1
  require 'erb'
2
+ require 'rubernate/init/init_generic'
2
3
 
3
4
  module Rubernate
4
5
  module DBI
5
- class MySqlInit
6
+ class MySqlInit < GenericInit
6
7
  CREATE_R_OBJECTS = %q{
7
8
  CREATE TABLE R_OBJECTS (
8
9
  OBJECT_PK INTEGER(20) PRIMARY KEY AUTO_INCREMENT,
9
10
  OBJECT_CLASS VARCHAR(100) NOT NULL) ENGINE=InnoDB;
10
- }.gsub(/^ /, '')
11
+ }.gsub(INDENT, '')
11
12
 
12
13
  CREATE_R_PARAMS = %q{
13
14
  CREATE TABLE R_PARAMS (
@@ -21,13 +22,13 @@ module DBI
21
22
  REF_VALUE INTEGER(20),
22
23
  CONSTRAINT R_PARAM_FK FOREIGN KEY (OBJECT_PK) REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE,
23
24
  CONSTRAINT R_REF_FK FOREIGN KEY (REF_VALUE) REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE) ENGINE=InnoDB;
24
- }.gsub(/^ /, '')
25
+ }.gsub(INDENT, '')
25
26
  CREATE_INDEX_O_PK_CLASS = %q{
26
27
  CREATE INDEX R_O_PK_CLASS ON R_OBJECTS (OBJECT_PK ASC, OBJECT_CLASS);
27
- }.gsub(/^ /, '')
28
+ }.gsub(INDENT, '')
28
29
  CREATE_INDEX_P_PK_NAME = %q{
29
30
  CREATE INDEX R_P_PK_NAME ON R_PARAMS (OBJECT_PK ASC, NAME);
30
- }.gsub(/^ /, '')
31
+ }.gsub(INDENT, '')
31
32
 
32
33
  TEMPLATE = %q{
33
34
  #
@@ -46,10 +47,10 @@ module DBI
46
47
  #
47
48
  # End
48
49
  #
49
- }.gsub(/^ /, '')
50
+ }.gsub(INDENT, '')
50
51
 
51
52
  # Prints initialization script and tryes to initialize databaes database if dbh is given.
52
- def self.init_db dbh=nil
53
+ def init_db dbh=nil
53
54
  puts ERB.new(TEMPLATE).result(binding)
54
55
  if dbh
55
56
  puts "\nInitializing database ... "
@@ -59,13 +60,6 @@ module DBI
59
60
  puts "Creation of index on r_params - #{exec_ddl dbh, CREATE_INDEX_P_PK_NAME}"
60
61
  end
61
62
  end
62
-
63
- def self.exec_ddl dbh, stat
64
- dbh.do stat
65
- 'done'
66
- rescue Exception => e
67
- "failed: #{e}"
68
- end
69
63
  end
70
64
  end
71
65
  end
@@ -1,13 +1,14 @@
1
1
  require 'erb'
2
+ require 'rubernate/init/init_generic'
2
3
 
3
4
  module Rubernate
4
5
  module DBI
5
- class OracleInit
6
+ class OracleInit < GenericInit
6
7
  CREATE_R_OBJECTS = %q{
7
8
  CREATE TABLE R_OBJECTS (
8
9
  OBJECT_PK NUMBER(20) PRIMARY KEY,
9
10
  OBJECT_CLASS VARCHAR2(100) NOT NULL)
10
- }.gsub(/^ /, '')
11
+ }.gsub(INDENT, '')
11
12
 
12
13
  CREATE_R_PARAMS = %q{
13
14
  CREATE TABLE R_PARAMS (
@@ -21,16 +22,16 @@ module DBI
21
22
  REF_VALUE NUMBER(20),
22
23
  CONSTRAINT R_PARAM_FK FOREIGN KEY (OBJECT_PK) REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE,
23
24
  CONSTRAINT R_REF_FK FOREIGN KEY (REF_VALUE) REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE)
24
- }.gsub(/^ /, '')
25
+ }.gsub(INDENT, '')
25
26
  CREATE_INDEX_O_PK_CLASS = %q{
26
27
  CREATE INDEX R_O_PK_CLASS ON R_OBJECTS (OBJECT_PK ASC, OBJECT_CLASS)
27
- }.gsub(/^ /, '')
28
+ }.gsub(INDENT, '')
28
29
  CREATE_INDEX_P_PK_NAME = %q{
29
30
  CREATE INDEX R_P_PK_NAME ON R_PARAMS (OBJECT_PK ASC, NAME)
30
- }.gsub(/^ /, '')
31
+ }.gsub(INDENT, '')
31
32
  CREATE_R_PK_SEQUENCE = %q{
32
33
  CREATE SEQUENCE R_PK_SEQUENCE START WITH 1001 INCREMENT BY 1
33
- }.gsub(/^ /, '')
34
+ }.gsub(INDENT, '')
34
35
 
35
36
  TEMPLATE = %q{
36
37
  /**
@@ -57,15 +58,14 @@ module DBI
57
58
  /**
58
59
  * Create primary key sequence
59
60
  */ <%= CREATE_R_PK_SEQUENCE %>/
60
-
61
61
 
62
62
  /**
63
63
  * End
64
64
  */
65
- }.gsub(/^ /, '')
65
+ }.gsub(INDENT, '')
66
66
 
67
67
  # Prints initialization script and tryes to initialize databaes database if dbh is given.
68
- def self.init_db dbh=nil
68
+ def init_db dbh
69
69
  puts ERB.new(TEMPLATE).result(binding)
70
70
  if dbh
71
71
  puts "\nInitializing database ... "
@@ -76,13 +76,6 @@ module DBI
76
76
  puts "Creation of pk sequence - #{exec_ddl dbh, CREATE_R_PK_SEQUENCE}"
77
77
  end
78
78
  end
79
-
80
- def self.exec_ddl dbh, stat
81
- dbh.do stat
82
- 'done'
83
- rescue Exception => e
84
- "failed: #{e}"
85
- end
86
79
  end
87
80
  end
88
81
  end
@@ -0,0 +1,78 @@
1
+ require 'erb'
2
+ require 'rubernate/init/init_generic'
3
+
4
+ module Rubernate
5
+ module DBI
6
+ class PgInit < GenericInit
7
+ CREATE_R_OBJECTS = %q{
8
+ CREATE TABLE R_OBJECTS (
9
+ OBJECT_PK INTEGER PRIMARY KEY,
10
+ OBJECT_CLASS VARCHAR(100))
11
+ }.gsub(INDENT, '')
12
+ CREATE_R_PARAMS = %q{
13
+ CREATE TABLE R_PARAMS (
14
+ OBJECT_PK INTEGER NOT NULL REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE,
15
+ NAME VARCHAR NOT NULL,
16
+ FLAGS INTEGER NOT NULL,
17
+ INT_VALUE INTEGER,
18
+ FLT_VALUE FLOAT,
19
+ STR_VALUE VARCHAR,
20
+ DAT_VALUE TIMESTAMP WITH TIME ZONE,
21
+ REF_VALUE INTEGER REFERENCES R_OBJECTS(OBJECT_PK) ON DELETE CASCADE)
22
+ }.gsub(INDENT, '')
23
+ CREATE_INDEX_O_PK_CLASS = %q{
24
+ CREATE INDEX R_O_PK_CLASS ON R_OBJECTS (OBJECT_PK, OBJECT_CLASS)
25
+ }.gsub(INDENT, '')
26
+ CREATE_INDEX_P_PK_NAME = %q{
27
+ CREATE INDEX R_O_CLASS ON R_OBJECTS (OBJECT_CLASS)
28
+ }.gsub(INDENT, '')
29
+ CREATE_R_PK_SEQUENCE = %q{
30
+ CREATE SEQUENCE R_PK_SEQUENCE;
31
+ }.gsub(INDENT, '')
32
+
33
+ TEMPLATE = %q{
34
+ /**
35
+ * Creates Rubernate tables for PostgreSQL database.
36
+ * Copyright (C) 2006 Andrey Ryabov <andrey_ryabov@bk.ru>
37
+ */
38
+
39
+ /**
40
+ * Create r_objects table
41
+ */ <%= CREATE_R_OBJECTS %>/
42
+
43
+ /**
44
+ * Create r_params table
45
+ */ <%= CREATE_R_PARAMS %>/
46
+
47
+ /**
48
+ * Create index on r_objects
49
+ */ <%= CREATE_INDEX_O_PK_CLASS %>/
50
+
51
+ /**
52
+ * Create index on r_params
53
+ */ <%= CREATE_INDEX_P_PK_NAME %>/
54
+
55
+ /**
56
+ * Create primary key sequence
57
+ */ <%= CREATE_R_PK_SEQUENCE %>/
58
+
59
+ /**
60
+ * End
61
+ */
62
+ }.gsub(INDENT, '')
63
+
64
+ # Prints initialization script and tryes to initialize databaes database if dbh is given.
65
+ def init_db dbh=nil
66
+ puts ERB.new(TEMPLATE).result(binding)
67
+ if dbh
68
+ puts "\nInitializing database ... "
69
+ puts "Creation of r_objects - #{exec_ddl dbh, CREATE_R_OBJECTS}"
70
+ puts "Creation of r_params - #{exec_ddl dbh, CREATE_R_PARAMS}"
71
+ puts "Creation of pk sequence - #{exec_ddl dbh, CREATE_R_PK_SEQUENCE}"
72
+ puts "Creation of index on r_objects - #{exec_ddl dbh, CREATE_INDEX_O_PK_CLASS}"
73
+ puts "Creation of index on r_params - #{exec_ddl dbh, CREATE_INDEX_P_PK_NAME}"
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end