imparcial 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/History.txt +2 -5
  2. data/Manifest.txt +79 -5
  3. data/README.txt +71 -7
  4. data/Rakefile +1 -1
  5. data/lib/imparcial/driver/abstract/expression/column.rb +313 -0
  6. data/lib/imparcial/driver/abstract/expression/constraint.rb +149 -0
  7. data/lib/imparcial/driver/abstract/expression/delete.rb +88 -0
  8. data/lib/imparcial/driver/abstract/expression/index.rb +206 -0
  9. data/lib/imparcial/driver/abstract/expression/insert.rb +49 -0
  10. data/lib/imparcial/driver/abstract/expression/lock.rb +11 -0
  11. data/lib/imparcial/driver/abstract/expression/record.rb +41 -0
  12. data/lib/imparcial/driver/abstract/expression/select.rb +38 -0
  13. data/lib/imparcial/driver/abstract/expression/sequence.rb +260 -0
  14. data/lib/imparcial/driver/abstract/expression/statement.rb +128 -0
  15. data/lib/imparcial/driver/abstract/expression/table.rb +416 -0
  16. data/lib/imparcial/driver/abstract/expression/transaction.rb +143 -0
  17. data/lib/imparcial/driver/abstract/expression/update.rb +50 -0
  18. data/lib/imparcial/driver/abstract/expression.rb +23 -0
  19. data/lib/imparcial/driver/abstract/result.rb +95 -0
  20. data/lib/imparcial/driver/abstract/sql/column.rb +103 -0
  21. data/lib/imparcial/driver/abstract/sql/constraint.rb +42 -0
  22. data/lib/imparcial/driver/abstract/sql/delete.rb +22 -0
  23. data/lib/imparcial/driver/abstract/sql/index.rb +45 -0
  24. data/lib/imparcial/driver/abstract/sql/insert.rb +63 -0
  25. data/lib/imparcial/driver/abstract/sql/record.rb +19 -0
  26. data/lib/imparcial/driver/abstract/sql/select.rb +101 -0
  27. data/lib/imparcial/driver/abstract/sql/sequence.rb +55 -0
  28. data/lib/imparcial/driver/abstract/sql/table.rb +42 -0
  29. data/lib/imparcial/driver/abstract/sql/transaction.rb +43 -0
  30. data/lib/imparcial/driver/abstract/sql/update.rb +29 -0
  31. data/lib/imparcial/driver/abstract/sql.rb +21 -0
  32. data/lib/imparcial/driver/abstract/typemap.rb +168 -0
  33. data/lib/imparcial/driver/abstract/util.rb +53 -0
  34. data/lib/imparcial/driver/abstract.rb +255 -0
  35. data/lib/imparcial/driver/mysql/expression/table.rb +17 -0
  36. data/lib/imparcial/driver/mysql/expression.rb +11 -0
  37. data/lib/imparcial/driver/mysql/result.rb +33 -0
  38. data/lib/imparcial/driver/mysql/sql/column.rb +59 -0
  39. data/lib/imparcial/driver/mysql/sql/constraint.rb +39 -0
  40. data/lib/imparcial/driver/mysql/sql/index.rb +42 -0
  41. data/lib/imparcial/driver/mysql/sql/sequence.rb +39 -0
  42. data/lib/imparcial/driver/mysql/sql/table.rb +67 -0
  43. data/lib/imparcial/driver/mysql/sql.rb +15 -0
  44. data/lib/imparcial/driver/mysql/typemap.rb +13 -0
  45. data/lib/imparcial/driver/mysql/util.rb +13 -0
  46. data/lib/imparcial/driver/mysql.rb +49 -0
  47. data/lib/imparcial/driver/postgre/expression.rb +32 -0
  48. data/lib/imparcial/driver/postgre/result.rb +35 -0
  49. data/lib/imparcial/driver/postgre/sql/column.rb +53 -0
  50. data/lib/imparcial/driver/postgre/sql/constraint.rb +37 -0
  51. data/lib/imparcial/driver/postgre/sql/index.rb +53 -0
  52. data/lib/imparcial/driver/postgre/sql/sequence.rb +30 -0
  53. data/lib/imparcial/driver/postgre/sql/table.rb +46 -0
  54. data/lib/imparcial/driver/postgre/sql.rb +15 -0
  55. data/lib/imparcial/driver/postgre/typemap.rb +36 -0
  56. data/lib/imparcial/driver/postgre/util.rb +19 -0
  57. data/lib/imparcial/driver/postgre.rb +43 -0
  58. data/lib/imparcial/driver.rb +1 -0
  59. data/lib/imparcial/exception.rb +71 -0
  60. data/lib/imparcial/extension.rb +90 -0
  61. data/lib/imparcial/initializer.rb +30 -0
  62. data/lib/imparcial.rb +1 -1
  63. data/test/unit/base/common/tc_quote.rb +30 -0
  64. data/test/unit/base/expression/tc_column.rb +84 -0
  65. data/test/unit/base/expression/tc_constraint.rb +39 -0
  66. data/test/unit/base/expression/tc_delete.rb +51 -0
  67. data/test/unit/base/expression/tc_index.rb +43 -0
  68. data/test/unit/base/expression/tc_insert.rb +44 -0
  69. data/test/unit/base/expression/tc_select.rb +142 -0
  70. data/test/unit/base/expression/tc_sequence.rb +48 -0
  71. data/test/unit/base/expression/tc_table.rb +68 -0
  72. data/test/unit/base/expression/tc_table_diff.rb +41 -0
  73. data/test/unit/base/expression/tc_transaction.rb +46 -0
  74. data/test/unit/base/expression/tc_update.rb +29 -0
  75. data/test/unit/base/statement/tc_conditions.rb +84 -0
  76. data/test/unit/base/statement/tc_limit.rb +25 -0
  77. data/test/unit/base/statement/tc_order.rb +25 -0
  78. data/test/unit/helper.rb +64 -0
  79. data/test/unit/mysql/tc_sequence.rb +41 -0
  80. metadata +102 -10
@@ -0,0 +1,29 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractSQL
4
+ module Update
5
+
6
+ private
7
+
8
+ def sql_for_updating ( options )
9
+
10
+ syntax = 'UPDATE ' + quote(options[:table_name]) + ' SET '
11
+
12
+ options[:values].each do |name, value|
13
+
14
+ syntax += quote(name) + ' = ' + quote_value(value) + ','
15
+
16
+ end
17
+
18
+ syntax.chop!
19
+
20
+ syntax += parse_conditions options[:conditions]
21
+
22
+ syntax
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ FileList[File.dirname(__FILE__) + '/sql/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module AbstractSQL
8
+ include Table
9
+ include Sequence
10
+ include Transaction
11
+ include Index
12
+ include Insert
13
+ include Delete
14
+ include Select
15
+ include Update
16
+ include Column
17
+ include Constraint
18
+ include Record
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,168 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractTypemap
4
+
5
+ public
6
+
7
+ # === Description
8
+ # Those are types shared among all databases.
9
+ # Of course they are not enough. Feel free to override them
10
+ # if necessary.
11
+
12
+ def regular_types
13
+
14
+ {
15
+ :integer => 'INTEGER',
16
+ :string => 'VARCHAR',
17
+ :float => 'FLOAT',
18
+ :datetime => 'DATETIME',
19
+ :time => 'TIME',
20
+ :date => 'DATE',
21
+ :text => 'TEXT',
22
+ :boolean => 'TINYINT',
23
+ :serial => 'SERIAL'
24
+ }
25
+
26
+ end
27
+
28
+ # === Description
29
+ # The opposite of regular_types.
30
+
31
+ def sql_types
32
+
33
+ regular_types.invert
34
+
35
+ end
36
+
37
+ # === Description
38
+ # Default size can be very handy when users are lazy to supply them
39
+ # or they expect a given type to be in a default size.
40
+
41
+ def default_size_for_types
42
+
43
+ {
44
+ :string => 255,
45
+ :boolean => 1
46
+ }
47
+
48
+ end
49
+
50
+ public
51
+
52
+ # === Description
53
+ # Validate a field.
54
+
55
+ def parse_field ( field )
56
+
57
+ # No name? error!
58
+
59
+ if not field[:name]
60
+
61
+ raise OptionError.new('A name must be supplied')
62
+
63
+ end
64
+
65
+ # No type? error!
66
+
67
+ if not field[:type]
68
+
69
+ raise OptionError.new('A type must be supplied')
70
+
71
+ end
72
+
73
+ # Simple conversions.
74
+
75
+ field[:name] = field[:name].to_s
76
+ field[:type] = field[:type].to_sym
77
+
78
+ regular_types[field[:type]].length == 0 rescue raise OptionError.new("#{field[:type]} cannot be found")
79
+
80
+ # Set default size if nothing has been supplied.
81
+
82
+ field[:size] = default_size_for_types[field[:type]] unless field[:size]
83
+
84
+ end
85
+
86
+ # === Description
87
+ # In order to work with fields in RDBAL, you have to provide
88
+ # field datas in hashes.
89
+ # This function is basically evaluate them and pass into a block.
90
+
91
+ def parse_fields ( fields = [], &block )
92
+
93
+ # At least a field must be supplied.
94
+
95
+ raise OptionError.new unless fields
96
+ raise OptionError.new if fields.length < 1
97
+
98
+ for field in fields
99
+
100
+ parse_field field
101
+ yield field
102
+
103
+ end
104
+
105
+ end
106
+
107
+ # === Description
108
+ # Transform a regular SQL column into Imparcial's hash.
109
+
110
+ def column_to_field ( column = {} )
111
+
112
+ field = {}
113
+
114
+ # Apply the appropriate type.
115
+
116
+ type = sql_types[column[:type].upcase]
117
+
118
+ if not type
119
+
120
+ raise OptionError.new('Cannot map column type: ' + column[:type].to_s)
121
+
122
+ end
123
+
124
+ field[:name] = column[:name]
125
+ field[:type] = type
126
+
127
+ if column[:size]
128
+
129
+ field[:size] = unquote_value(column[:size])
130
+
131
+ end
132
+
133
+ field
134
+
135
+ end
136
+
137
+ # === Description
138
+ # Make an Imparcial's hash into SQl's
139
+
140
+ def field_to_column ( field = {} )
141
+
142
+ column = {}
143
+
144
+ column[:name] = quote(field[:name])
145
+ column[:type] = regular_types[field[:type]]
146
+ column[:size] = field[:size]
147
+
148
+ column
149
+
150
+ end
151
+
152
+ # === Description
153
+ # Transform a regular field into SQL syntax.
154
+
155
+ def field_to_column_sql ( field = {} )
156
+
157
+ column = field_to_column field
158
+
159
+ syntax = "#{column[:name]} #{column[:type]}"
160
+ syntax += "(#{column[:size]})" if column[:size]
161
+
162
+ syntax
163
+
164
+ end
165
+
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,53 @@
1
+ module Imparcial
2
+ module Driver
3
+ module AbstractUtil
4
+
5
+ # === Description
6
+ # Apply default database value quoting system.
7
+
8
+ def quote_value ( val )
9
+
10
+ if val.class == String || val.class == Symbol
11
+
12
+ "\"#{val}\""
13
+
14
+ else
15
+
16
+ val.to_s
17
+
18
+ end
19
+
20
+ end
21
+
22
+ # === Description
23
+ # Apply default database value unquoting system.
24
+
25
+ def unquote_value ( val )
26
+
27
+ return nil if val == nil
28
+ return 0 if val == '0'
29
+
30
+ if val.match(/[0-9]\.[0-9]*/)
31
+
32
+ val.to_f
33
+
34
+ else
35
+
36
+ val.to_i == 0 ? val : val.to_i
37
+
38
+ end
39
+
40
+ end
41
+
42
+ # === Description
43
+ # Apply default database quoting system.
44
+
45
+ def quote ( val )
46
+
47
+ raise FeatureNotFound
48
+
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,255 @@
1
+ require 'logger'
2
+
3
+ require 'imparcial/driver/abstract/util'
4
+ require 'imparcial/driver/abstract/result'
5
+ require 'imparcial/driver/abstract/typemap'
6
+ require 'imparcial/driver/abstract/sql'
7
+ require 'imparcial/driver/abstract/expression'
8
+
9
+ module Imparcial
10
+ module Driver
11
+
12
+ # You have seriously to pay attention on this class.
13
+ # Basically speaking, it servers as abstraction for all new drivers.
14
+ # The idea behind Imparcial is to keep an abstract interface without
15
+ # exposing any dataabstract-specific-features.
16
+ # Of course, it's an impossible mission anyhow. There are so many
17
+ # dataabases out there and there are so many cool features that
18
+ # make impossible not to expose them.
19
+ # We recommend you to obey the interface as much as possible.
20
+ # However you may develop some specific features.
21
+ # Please, keep an eye on specification(can be found in the website).
22
+
23
+ class AbstractAdapter
24
+
25
+ # Include SQL syntax generation.
26
+ # Here where all SQL syntax lies on.
27
+
28
+ include AbstractSQL
29
+
30
+ # Include the expression mechanism.
31
+ # Things like create table, drop table, select and so forth.
32
+ # They all come from this module.
33
+
34
+ include AbstractExpression
35
+
36
+ # Include some util methods.
37
+ # Things like quoting, unquoting.
38
+
39
+ include AbstractUtil
40
+
41
+ # Include Typemap mechanism.
42
+
43
+ include AbstractTypemap
44
+
45
+ # Let's also keep a track of the connection.
46
+
47
+ attr_accessor :conn
48
+ alias_method :connection, :conn
49
+
50
+ # A logger is also required.
51
+
52
+ attr_accessor :logger
53
+
54
+ attr_accessor :host, :adapter, :port, :username, :password, :socket, :database
55
+
56
+ #####################################################
57
+ # #
58
+ # Those are methods shared among all databases. #
59
+ # Hardly, one will need to override them. #
60
+ # #
61
+ #####################################################
62
+
63
+ # === Description
64
+ # Display connection handle.
65
+ #
66
+ # === Returning
67
+ # a handle.
68
+
69
+ def conn
70
+
71
+ raise AdapterConnectionError.new('Have you connected already?') unless @conn
72
+ @conn
73
+
74
+ end
75
+
76
+ # === Description
77
+ # Terminate a connection.
78
+ #
79
+ # === Returning
80
+ # nothing.
81
+
82
+ def close
83
+
84
+ conn.close
85
+
86
+ end
87
+
88
+ # === Description
89
+ # After executing a statement, the method query will bring a result.
90
+ #
91
+ # === Returning
92
+ # result to a query.
93
+
94
+ def result
95
+
96
+ raise ResultError.new('Have you made any query?') unless @result
97
+ @result
98
+
99
+ end
100
+
101
+ #####################################################
102
+ # #
103
+ # Subclasses must override those following methods. #
104
+ # They are driver-specific. #
105
+ # #
106
+ #####################################################
107
+
108
+ # === Description
109
+ # Stablish a connection.
110
+ #
111
+ # === Returning
112
+ # nothing.
113
+
114
+ def connect
115
+
116
+ raise FeatureNotFound
117
+
118
+ end
119
+
120
+ # === Description
121
+ # Execute a statement directly to the adapter.
122
+ #
123
+ # === Returning
124
+ # The method result will be avaliable.
125
+
126
+ def query ( sql )
127
+
128
+ raise FeatureNotFound
129
+
130
+ end
131
+
132
+ # === Description
133
+ # get the adapter specific's exception.
134
+ #
135
+ # === Returning
136
+ # an exception class.
137
+
138
+ def adapter_specific_exception
139
+
140
+ raise FeatureNotFound
141
+
142
+ end
143
+
144
+ def last_insert_id
145
+
146
+ raise FeatureNotFound
147
+
148
+ end
149
+
150
+ public
151
+
152
+ #####################################################
153
+ # #
154
+ # Logging mechanism #
155
+ # #
156
+ #####################################################
157
+
158
+ def enable_table_logging
159
+
160
+ @table_logging = true
161
+
162
+ end
163
+
164
+ def disable_table_logging
165
+
166
+ @table_logging = false
167
+
168
+ end
169
+
170
+ def enable_column_logging
171
+
172
+ @column_logging = true
173
+
174
+ end
175
+
176
+ def disable_column_logging
177
+
178
+ @column_logging = false
179
+
180
+ end
181
+
182
+ def enable_index_logging
183
+
184
+ @index_logging = true
185
+
186
+ end
187
+
188
+ def disable_index_logging
189
+
190
+ @index_logging = false
191
+
192
+ end
193
+
194
+ def enable_select_logging
195
+
196
+ @select_logging = true
197
+
198
+ end
199
+
200
+ def disable_select_logging
201
+
202
+ @select_logging = false
203
+
204
+ end
205
+
206
+ def enable_update_logging
207
+
208
+ @update_logging = true
209
+
210
+ end
211
+
212
+ def disable_update_logging
213
+
214
+ @update_logging = false
215
+
216
+ end
217
+
218
+ def enable_insert_logging
219
+
220
+ @insert_logging = true
221
+
222
+ end
223
+
224
+ def disable_insert_logging
225
+
226
+ @insert_logging = false
227
+
228
+ end
229
+
230
+ def enable_sequence_logging
231
+
232
+ @sequence_logging = true
233
+
234
+ end
235
+
236
+ def disable_sequence_logging
237
+
238
+ @sequence_logging = false
239
+
240
+ end
241
+
242
+ def enable_record_logging
243
+
244
+ @record_logging = true
245
+
246
+ end
247
+
248
+ def disable_record_logging
249
+
250
+ @record_logging = false
251
+
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,17 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlExpression
4
+ module Table
5
+
6
+ private
7
+
8
+ def expected_options_for_creating_table
9
+
10
+ super.merge :engine => :optional
11
+
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ FileList[File.dirname(__FILE__) + '/expression/*.rb'].each do |f|
2
+ require f
3
+ end
4
+
5
+ module Imparcial
6
+ module Driver
7
+ module MysqlExpression
8
+ include Table
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ module Imparcial
2
+ module Driver
3
+ class MysqlResult < AbstractResult
4
+
5
+ def rows
6
+
7
+ @specific.num_rows
8
+
9
+ end
10
+
11
+ def fetch
12
+
13
+ fields = @specific.fetch_fields
14
+
15
+ @specific.each do |row|
16
+
17
+ v = []
18
+
19
+ row.each_with_index do |r, index|
20
+
21
+ v << Row.new(fields[index].name, r)
22
+
23
+ end
24
+
25
+ yield(*v)
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,59 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlSQL
4
+ module Column
5
+
6
+ private
7
+
8
+ def sql_for_modifying_columns ( options )
9
+
10
+ syntax = ''
11
+
12
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
13
+
14
+ options[:fields].each do |field|
15
+
16
+ column = field_to_column field
17
+
18
+ syntax += "MODIFY COLUMN #{column[:name]} #{column[:type]}"
19
+ syntax += "(#{column[:size]})" if column[:size]
20
+
21
+ syntax += ','
22
+
23
+ end
24
+
25
+ syntax.chop!
26
+
27
+ syntax
28
+
29
+ end
30
+
31
+ def sql_for_renaming_column ( options )
32
+
33
+ old_name = options[:field].keys.first
34
+ new_name = options[:field].values.first
35
+
36
+ field = get_column_information :table_name => options[:table_name], :field_name => old_name
37
+
38
+ column = field_to_column field
39
+
40
+ syntax = ''
41
+
42
+ syntax += 'ALTER TABLE ' + quote(options[:table_name]) + ' '
43
+
44
+ syntax += "CHANGE COLUMN #{column[:name]}"
45
+ syntax += " #{quote(new_name)}"
46
+ syntax += " #{column[:type]}"
47
+ syntax += "(#{column[:size]})" if column[:size]
48
+ syntax += ','
49
+
50
+ syntax.chop!
51
+
52
+ syntax
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+ module Imparcial
2
+ module Driver
3
+ module MysqlSQL
4
+ module Constraint
5
+
6
+ private
7
+
8
+ def sql_for_adding_auto_increment ( options )
9
+
10
+ syntax = 'ALTER TABLE ' + quote(options[:table_name]) + ' '
11
+
12
+ syntax += "MODIFY COLUMN #{quote(options[:field])} INTEGER NOT NULL AUTO_INCREMENT"
13
+
14
+ syntax
15
+
16
+ end
17
+
18
+ def sql_for_adding_default_value ( options )
19
+
20
+ syntax = 'ALTER TABLE ' + quote(options[:table_name]) + ' '
21
+
22
+ for field, value in options[:fields]
23
+
24
+ syntax += "ALTER COLUMN #{quote(field)} SET DEFAULT #{quote_value(value)},"
25
+
26
+ end
27
+
28
+ syntax.chop!
29
+
30
+ syntax
31
+
32
+ end
33
+
34
+
35
+
36
+ end
37
+ end
38
+ end
39
+ end