spiderfw 0.6.23 → 0.6.24
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -1
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/apps/config_editor/_init.rb +1 -2
- data/apps/config_editor/controllers/config_editor_controller.rb +1 -7
- data/apps/core/admin/controllers/admin_controller.rb +1 -1
- data/apps/core/admin/public/css/sass/admin.css +35 -31
- data/apps/core/admin/public/sass/admin.scss +6 -1
- data/apps/core/components/widgets/crud/crud.shtml +2 -2
- data/apps/core/components/widgets/table/table.rb +5 -5
- data/apps/core/forms/tags/element_row.erb +15 -10
- data/apps/core/forms/widgets/form/form.rb +35 -22
- data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +2 -2
- data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +2 -2
- data/apps/core/forms/widgets/inputs/file_input/file_input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/input/input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/password/password.shtml +2 -2
- data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +1 -1
- data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text/text.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/time_span/time_span.shtml +1 -1
- data/blueprints/home/config.ru +8 -0
- data/lib/spiderfw/app.rb +416 -224
- data/lib/spiderfw/cmd/commands/app.rb +243 -239
- data/lib/spiderfw/cmd/commands/cert.rb +421 -417
- data/lib/spiderfw/cmd/commands/config.rb +85 -82
- data/lib/spiderfw/cmd/commands/console.rb +64 -40
- data/lib/spiderfw/cmd/commands/content.rb +29 -25
- data/lib/spiderfw/cmd/commands/create.rb +58 -54
- data/lib/spiderfw/cmd/commands/model.rb +118 -114
- data/lib/spiderfw/cmd/commands/setup.rb +55 -51
- data/lib/spiderfw/cmd/commands/test.rb +63 -59
- data/lib/spiderfw/cmd/commands/webserver.rb +56 -51
- data/lib/spiderfw/config/options/spider.rb +4 -3
- data/lib/spiderfw/controller/controller.rb +2 -0
- data/lib/spiderfw/controller/http_controller.rb +1 -2
- data/lib/spiderfw/controller/mixins/static_content.rb +3 -3
- data/lib/spiderfw/controller/mixins/visual.rb +30 -15
- data/lib/spiderfw/controller/response.rb +84 -0
- data/lib/spiderfw/controller/session/file_session.rb +2 -2
- data/lib/spiderfw/http/adapters/rack.rb +12 -13
- data/lib/spiderfw/http/server.rb +80 -46
- data/lib/spiderfw/i18n/cldr.rb +6 -9
- data/lib/spiderfw/model/base_model.rb +103 -23
- data/lib/spiderfw/model/condition.rb +110 -25
- data/lib/spiderfw/model/mappers/db_mapper.rb +14 -6
- data/lib/spiderfw/model/mappers/mapper.rb +440 -197
- data/lib/spiderfw/model/model.rb +105 -21
- data/lib/spiderfw/model/model_hash.rb +9 -1
- data/lib/spiderfw/model/query.rb +50 -9
- data/lib/spiderfw/model/query_set.rb +211 -44
- data/lib/spiderfw/model/request.rb +28 -21
- data/lib/spiderfw/model/storage/base_storage.rb +125 -10
- data/lib/spiderfw/model/storage/db/db_storage.rb +7 -4
- data/lib/spiderfw/model/storage.rb +8 -1
- data/lib/spiderfw/setup/spider_setup_wizard.rb +9 -7
- data/lib/spiderfw/spider.rb +270 -43
- data/lib/spiderfw/templates/layout.rb +9 -4
- data/lib/spiderfw/templates/resources/sass.rb +3 -2
- data/lib/spiderfw/templates/template.rb +1 -0
- data/lib/spiderfw/utils/annotations.rb +3 -1
- data/lib/spiderfw/utils/logger.rb +1 -1
- data/lib/spiderfw/utils/monkey/symbol.rb +4 -2
- data/lib/spiderfw/utils/shared_store/file_shared_store.rb +2 -2
- data/lib/spiderfw/utils/thread_out.rb +3 -1
- data/public/css/error_page.css +83 -0
- data/public/js/error_page.js +5 -0
- data/spider.gemspec +4 -1
- data/templates/email/error.erb +9 -0
- metadata +28 -12
- data/apps/config_editor/widgets/edit_bool/edit_bool.rb +0 -8
- data/apps/config_editor/widgets/edit_bool/edit_bool.shtml +0 -5
@@ -6,13 +6,16 @@ module Spider; module Model
|
|
6
6
|
# the SELECT ... part of an SQL query.
|
7
7
|
|
8
8
|
class Request < ModelHash
|
9
|
-
#
|
9
|
+
# @return [bool] if true, the total number of rows returned by the query is requested.
|
10
10
|
attr_accessor :total_rows
|
11
|
-
#
|
11
|
+
# @return [bool] find also the given subclasses of the queried model.
|
12
12
|
attr_reader :polymorphs
|
13
|
-
#
|
13
|
+
# @return [bool] if true, the request will be expanded with lazy groups on load
|
14
14
|
attr_accessor :expandable
|
15
15
|
|
16
|
+
# @param [Array|Hash] value Value to initialize the Request with. May be a Hash, or an Array of elements.
|
17
|
+
# @param [Hash] params Params may have:
|
18
|
+
# * :total_rows Request the total rows corresponding to the Query from the storage
|
16
19
|
def initialize(val=nil, params={})
|
17
20
|
if (val.is_a?(Array))
|
18
21
|
super()
|
@@ -25,13 +28,18 @@ module Spider; module Model
|
|
25
28
|
@expandable = true
|
26
29
|
end
|
27
30
|
|
31
|
+
# Initializes a Request that should not be expanded by the Mapper
|
32
|
+
# @param [Array|Hash] val
|
33
|
+
# @param [Hash] params
|
34
|
+
# @return [Request]
|
28
35
|
def self.strict(val=nil, params={})
|
29
36
|
r = self.new(val, params)
|
30
37
|
r.expandable = false
|
31
38
|
r
|
32
39
|
end
|
33
40
|
|
34
|
-
#
|
41
|
+
# @param [Element|String|Symbol] Element to request
|
42
|
+
# @return [void]
|
35
43
|
def request(element) # :nodoc:
|
36
44
|
if element.is_a?(Element)
|
37
45
|
self[element.name.to_s] = true
|
@@ -43,48 +51,47 @@ module Spider; module Model
|
|
43
51
|
self[element] = true
|
44
52
|
end
|
45
53
|
end
|
46
|
-
|
47
|
-
# Requests all base types
|
48
|
-
def load_all_simple
|
49
|
-
@load_all_simple = true
|
50
|
-
end
|
51
|
-
|
52
|
-
def load_all_simple?
|
53
|
-
@load_all_simple
|
54
|
-
end
|
55
54
|
|
56
|
-
#
|
55
|
+
# Requests that the mapper looks for subclasses of the given type, loading
|
56
|
+
# additional subclass specific elements specified in the request
|
57
|
+
# @param [Class<BaseModel] type The subclass
|
58
|
+
# @param [Request] request Request for subclass specific elements
|
57
59
|
def with_polymorphs(type, request)
|
58
60
|
@polymorphs[type] = request
|
59
61
|
end
|
60
62
|
|
63
|
+
# @return [bool] True if there are requested polymorphs
|
61
64
|
def polymorphs?
|
62
65
|
@polymorphs.empty? ? false : true
|
63
66
|
end
|
64
67
|
|
65
|
-
# Requests only subclasses
|
68
|
+
# Requests that only the subclasses requested with {#with_polymorphs} are returned,
|
69
|
+
# not the mapper's base class
|
70
|
+
# @return [self]
|
66
71
|
def only_polymorphs
|
67
72
|
@only_polymorphs = true
|
68
73
|
return self
|
69
74
|
end
|
70
|
-
|
75
|
+
|
76
|
+
# @return [bool] True if only polymorphs should be returned
|
71
77
|
def only_polymorphs?
|
72
78
|
@only_polymorphs
|
73
79
|
end
|
74
80
|
|
81
|
+
# Requests that the mapper retrieves also objects belonging to the model's superclass
|
82
|
+
# @return [self]
|
75
83
|
def with_superclass
|
76
84
|
@with_superclass = true
|
77
85
|
return self
|
78
86
|
end
|
79
87
|
|
80
|
-
|
81
|
-
@with_superclass = val
|
82
|
-
end
|
83
|
-
|
88
|
+
# @return [bool] true if the superclass was requested with {#with_superclass}
|
84
89
|
def with_superclass?
|
85
90
|
@with_superclass
|
86
91
|
end
|
87
|
-
|
92
|
+
|
93
|
+
|
94
|
+
# @return [bool] true if the Request can be expanded by the mapper (using lazy groups)
|
88
95
|
def expandable?
|
89
96
|
@expandable
|
90
97
|
end
|
@@ -2,6 +2,9 @@ require 'spiderfw/model/storage/connection_pool'
|
|
2
2
|
|
3
3
|
module Spider; module Model; module Storage
|
4
4
|
|
5
|
+
# @abstract
|
6
|
+
# This class is subclassed by classes that interact with different storage backends.
|
7
|
+
# See also {Db::DbStorage}, {Document::DocumentStorage}.
|
5
8
|
class BaseStorage
|
6
9
|
include Spider::Logger
|
7
10
|
attr_reader :url
|
@@ -15,38 +18,48 @@ module Spider; module Model; module Storage
|
|
15
18
|
# An Hash of storage capabilities. The default for db storages is
|
16
19
|
# {:autoincrement => false, :sequences => true, :transactions => true}
|
17
20
|
# (The BaseStorage class provides file sequences in case the subclass does not support them.)
|
21
|
+
# @return [Hash]
|
18
22
|
attr_reader :capabilities
|
19
23
|
|
24
|
+
# @return [Symbol] A label for the storage's class.
|
20
25
|
def storage_type
|
21
26
|
:none
|
22
27
|
end
|
23
28
|
|
29
|
+
# @return [Sync] A Sync object to use for sequences
|
24
30
|
def sequence_sync
|
25
31
|
@sequence_sync ||= ::Sync.new
|
26
32
|
end
|
27
33
|
|
34
|
+
# @return [Array] Base types supported by the backend.
|
28
35
|
def base_types
|
29
36
|
Model.base_types
|
30
37
|
end
|
31
38
|
|
32
|
-
# True if given named capability is supported by the
|
39
|
+
# @return [bool] True if given named capability is supported by the backend.
|
33
40
|
def supports?(capability)
|
34
41
|
@capabilities[capability]
|
35
42
|
end
|
36
43
|
|
37
|
-
#
|
44
|
+
# @abstract
|
45
|
+
# @return [Object] Returns a new connection. Must be implemented by the subclasses; args are implementation specific.
|
38
46
|
def new_connection(*args)
|
39
47
|
raise "Unimplemented"
|
40
48
|
end
|
41
49
|
|
50
|
+
# @abstract
|
51
|
+
# @return [Fixnum|nil] Maximum number of connections possible for this backend (or nil if unlimited)
|
42
52
|
def max_connections
|
43
53
|
nil
|
44
54
|
end
|
45
55
|
|
56
|
+
# @return [Hash] An Hash of connection pools for each backend.
|
46
57
|
def connection_pools
|
47
58
|
@pools ||= {}
|
48
59
|
end
|
49
60
|
|
61
|
+
# @param [*args] Storage specific arguments
|
62
|
+
# @return [Object] Retrieves a native connection to the backend from the {ConnectionPool}.
|
50
63
|
def get_connection(*args)
|
51
64
|
@pools ||= {}
|
52
65
|
@pools[args] ||= ConnectionPool.new(args, self)
|
@@ -54,6 +67,9 @@ module Spider; module Model; module Storage
|
|
54
67
|
end
|
55
68
|
|
56
69
|
# Frees a connection, relasing it to the pool
|
70
|
+
# @param [Object] conn The connection
|
71
|
+
# @param [Array] conn_params An array of connection params that were used to create the connection.
|
72
|
+
# @return [void]
|
57
73
|
def release_connection(conn, conn_params)
|
58
74
|
return unless conn
|
59
75
|
return unless @pools && @pools[conn_params]
|
@@ -61,50 +77,77 @@ module Spider; module Model; module Storage
|
|
61
77
|
end
|
62
78
|
|
63
79
|
# Removes a connection from the pool.
|
80
|
+
# @param [Object] conn The connection
|
81
|
+
# @param [Array] conn_params An array of connection params that were used to create the connection.
|
82
|
+
# @return [void]
|
64
83
|
def remove_connection(conn, conn_params)
|
65
84
|
return unless conn
|
66
85
|
return unless @pools && @pools[conn_params]
|
67
86
|
@pools[conn_params].remove(conn)
|
68
87
|
end
|
69
88
|
|
89
|
+
# @abstract
|
90
|
+
# Closes the native connection to the backend.
|
91
|
+
# @param [Object] conn The native connection
|
92
|
+
# @return [void]
|
70
93
|
def disconnect(conn)
|
71
94
|
raise "Virtual"
|
72
95
|
end
|
73
96
|
|
97
|
+
# @abstract
|
74
98
|
# Checks whether a connection is still alive. Must be implemented by subclasses.
|
99
|
+
# @param [Object] conn The native connection
|
100
|
+
# @return [void]
|
75
101
|
def connection_alive?(conn)
|
76
102
|
raise "Virtual"
|
77
103
|
end
|
78
104
|
|
105
|
+
# Copies capabilities on subclasses
|
106
|
+
# @param [Class<BaseStorage] subclass
|
107
|
+
# @return [void]
|
79
108
|
def inherited(subclass)
|
80
109
|
subclass.instance_variable_set("@capabilities", @capabilities)
|
81
110
|
end
|
82
111
|
|
83
112
|
end
|
84
113
|
|
85
|
-
|
114
|
+
# Creates a new storage instance.
|
115
|
+
# @param [String] url The backend-specific url for the connection
|
86
116
|
def initialize(url)
|
87
117
|
@url = url
|
88
118
|
@configuration = {}
|
89
119
|
parse_url(url)
|
90
120
|
end
|
91
121
|
|
122
|
+
# Sets configuration for the Storage
|
123
|
+
# @param [Hash] conf The configuration
|
124
|
+
# @return [void]
|
92
125
|
def configure(conf)
|
93
126
|
@configuration.merge!(conf.to_hash)
|
94
127
|
end
|
95
128
|
|
129
|
+
# @abstract
|
130
|
+
# Splits a backend-specific connection url into parts
|
131
|
+
# @param [String] url
|
132
|
+
# @return [Array]
|
96
133
|
def parse_url(url)
|
97
134
|
raise StorageException, "Unimplemented"
|
98
135
|
end
|
99
136
|
|
137
|
+
# @abstact
|
138
|
+
# @param [Class<BaseModel]
|
139
|
+
# @return [Mapper] Returns the instance of a mapper for the storage and the given model
|
100
140
|
def get_mapper(model)
|
101
141
|
raise StorageException, "Unimplemented"
|
102
142
|
end
|
103
143
|
|
144
|
+
# @param [Symbol] capability
|
145
|
+
# @return [bool] True if the backend supports the given capability
|
104
146
|
def supports?(capability)
|
105
147
|
self.class.supports?(capability)
|
106
148
|
end
|
107
149
|
|
150
|
+
# @return [Hash] An hash of thread-local values for this connection
|
108
151
|
def curr
|
109
152
|
var = nil
|
110
153
|
if Spider.conf.get('storage.shared_connection')
|
@@ -120,17 +163,19 @@ module Spider; module Model; module Storage
|
|
120
163
|
}
|
121
164
|
end
|
122
165
|
|
166
|
+
# @return [ConnectionPool|nil] The ConnectionPool managing the current connection params
|
123
167
|
def connection_pool
|
124
168
|
self.class.connection_pools[@connection_params]
|
125
169
|
end
|
126
170
|
|
127
171
|
# Instantiates a new connection with current connection params.
|
172
|
+
# @return [void]
|
128
173
|
def connect
|
129
174
|
return self.class.get_connection(*@connection_params)
|
130
175
|
#Spider::Logger.debug("#{self.class.name} in thread #{Thread.current} acquired connection #{@conn}")
|
131
176
|
end
|
132
177
|
|
133
|
-
# True if currently connected.
|
178
|
+
# @return [bool] True if currently connected.
|
134
179
|
def connected?
|
135
180
|
curr[:conn] != nil
|
136
181
|
end
|
@@ -138,6 +183,8 @@ module Spider; module Model; module Storage
|
|
138
183
|
|
139
184
|
# Returns the current connection, or creates a new one.
|
140
185
|
# If a block is given, will release the connection after yielding.
|
186
|
+
# @yield [Object] If a block is given, it is passed the connection, which is released after the block ends.
|
187
|
+
# @return [Object] The connection
|
141
188
|
def connection
|
142
189
|
curr[:conn] = connect
|
143
190
|
if block_given?
|
@@ -149,15 +196,18 @@ module Spider; module Model; module Storage
|
|
149
196
|
end
|
150
197
|
end
|
151
198
|
|
199
|
+
# @return [Hash] current connection attributes
|
152
200
|
def self.connection_attributes
|
153
201
|
@connection_attributes ||= {}
|
154
202
|
end
|
155
203
|
|
204
|
+
# @return [Hash] current connection attributes
|
156
205
|
def connection_attributes
|
157
206
|
self.class.connection_attributes[connection] ||= {}
|
158
207
|
end
|
159
208
|
|
160
209
|
# Releases the current connection to the pool.
|
210
|
+
# @return [void]
|
161
211
|
def release
|
162
212
|
# The subclass should check if the connection is alive, and if it is not call remove_connection instead
|
163
213
|
c = curr[:conn]
|
@@ -169,40 +219,59 @@ module Spider; module Model; module Storage
|
|
169
219
|
#@conn = nil
|
170
220
|
end
|
171
221
|
|
172
|
-
# Prepares a value
|
222
|
+
# Prepares a value which will be saved into the backend.
|
223
|
+
# @param [Class] type
|
224
|
+
# @param [Object] value
|
225
|
+
# @param [Symbol] save_mode :insert or :update or generic :save
|
226
|
+
# @return [Object] The prepared value
|
173
227
|
def value_for_save(type, value, save_mode)
|
174
228
|
return prepare_value(type, value)
|
175
229
|
end
|
176
230
|
|
177
|
-
# Prepares a value that will be used in a condition.
|
231
|
+
# Prepares a value that will be used in a condition on the backend.
|
232
|
+
# @param [Class] type
|
233
|
+
# @param [Object] value
|
234
|
+
# @return [Object] The prepared value
|
178
235
|
def value_for_condition(type, value)
|
179
236
|
return prepare_value(type, value)
|
180
237
|
end
|
181
238
|
|
239
|
+
# Prepares a value coming from the backend for the mapper
|
240
|
+
# @param [Class] type
|
241
|
+
# @param [Object] value
|
242
|
+
# @return [Object] The prepared value
|
182
243
|
def value_to_mapper(type, value)
|
183
244
|
value
|
184
245
|
end
|
185
246
|
|
186
|
-
|
247
|
+
# Prepares a value that will be used by the backend (see also {#value_for_save} and {#value_for_condition},
|
248
|
+
# which by default call this method, but can be override to do more specific processiong).
|
249
|
+
# @param [Class] type
|
250
|
+
# @param [Object] value
|
251
|
+
# @return [Object] The prepared value
|
187
252
|
def prepare_value(type, value)
|
188
253
|
return value
|
189
254
|
end
|
190
255
|
|
256
|
+
# @return [bool] True if the other storage is of the same class, and has the same connection url
|
191
257
|
def ==(storage)
|
192
258
|
return false unless self.class == storage.class
|
193
259
|
return false unless self.url == storage.url
|
194
260
|
return true
|
195
261
|
end
|
196
262
|
|
197
|
-
|
263
|
+
# @return [bool] True if the backend support stransaction
|
198
264
|
def supports_transactions?
|
199
265
|
return self.class.supports?(:transactions)
|
200
266
|
end
|
201
267
|
|
268
|
+
# @return [bool] True if transactions are supported by the backend and enabled in the storage's configuration.
|
202
269
|
def transactions_enabled?
|
203
270
|
@configuration['enable_transactions'] && supports_transactions?
|
204
271
|
end
|
205
272
|
|
273
|
+
# Starts a new transaction on the backend
|
274
|
+
# @return [bool] True if a new transaction was started, false otherwise
|
206
275
|
def start_transaction
|
207
276
|
return unless transactions_enabled?
|
208
277
|
curr[:transaction_nesting] += 1
|
@@ -213,11 +282,14 @@ module Spider; module Model; module Storage
|
|
213
282
|
return true
|
214
283
|
end
|
215
284
|
|
216
|
-
#
|
285
|
+
# @abstract
|
286
|
+
# Implemented by subclasses to interact with the backend
|
217
287
|
def do_start_transaction
|
218
288
|
raise StorageException, "The current storage does not support transactions"
|
219
289
|
end
|
220
290
|
|
291
|
+
# Starts a transaction, or increases transaction nesting.
|
292
|
+
# @return [bool] True if a transaction was already active, false otherwise
|
221
293
|
def in_transaction
|
222
294
|
if in_transaction?
|
223
295
|
curr[:transaction_nesting] += 1
|
@@ -228,11 +300,15 @@ module Spider; module Model; module Storage
|
|
228
300
|
end
|
229
301
|
end
|
230
302
|
|
303
|
+
# @return [bool] True if a transaction is currently active
|
231
304
|
def in_transaction?
|
232
305
|
return false
|
233
306
|
end
|
234
307
|
|
235
308
|
|
309
|
+
# Commits the current transaction
|
310
|
+
# @return [bool] True if the transaction was successfully committed, false if transactions are not enabled
|
311
|
+
# (Raises a StorageException if transactions are supported but were not started)
|
236
312
|
def commit
|
237
313
|
return false unless transactions_enabled?
|
238
314
|
raise StorageException, "Commit without a transaction" unless in_transaction?
|
@@ -240,6 +316,9 @@ module Spider; module Model; module Storage
|
|
240
316
|
commit!
|
241
317
|
end
|
242
318
|
|
319
|
+
# Commits the current transaction, or decreases transaction nesting.
|
320
|
+
# @return [bool] True if the transaction was successfully committed, false if transactions are not enabled
|
321
|
+
# (Raises a StorageException if transactions are supported but were not started)
|
243
322
|
def commit_or_continue
|
244
323
|
return false unless transactions_enabled?
|
245
324
|
raise StorageException, "Commit without a transaction" unless in_transaction?
|
@@ -252,6 +331,8 @@ module Spider; module Model; module Storage
|
|
252
331
|
end
|
253
332
|
end
|
254
333
|
|
334
|
+
# Commits current transaction, resets transaction nesting, and releases the connection.
|
335
|
+
# @return [void]
|
255
336
|
def commit!
|
256
337
|
Spider.logger.debug("#{self.class.name} commit connection #{curr[:conn].object_id}")
|
257
338
|
curr[:transaction_nesting] = 0
|
@@ -259,16 +340,23 @@ module Spider; module Model; module Storage
|
|
259
340
|
release
|
260
341
|
end
|
261
342
|
|
343
|
+
# @abstract
|
344
|
+
# Implemented by subclasses to interact with the backend
|
345
|
+
# @return [void]
|
262
346
|
def do_commit
|
263
347
|
raise StorageException, "The current storage does not support transactions"
|
264
348
|
end
|
265
349
|
|
350
|
+
# Rolls back the current transaction. Raises an error if in a nested transaction.
|
351
|
+
# @return [void]
|
266
352
|
def rollback
|
267
353
|
raise "Can't rollback in a nested transaction" if curr[:transaction_nesting] > 1
|
268
354
|
return rollback_savepoint(curr[:savepoints].last) unless curr[:savepoints].empty?
|
269
355
|
rollback!
|
270
356
|
end
|
271
357
|
|
358
|
+
# Rolls back the current transaction, regardless of transaction nesting, and releases the connection
|
359
|
+
# @return [void]
|
272
360
|
def rollback!
|
273
361
|
curr[:transaction_nesting] = 0
|
274
362
|
Spider.logger.debug("#{self.class.name} rollback")
|
@@ -277,14 +365,23 @@ module Spider; module Model; module Storage
|
|
277
365
|
release
|
278
366
|
end
|
279
367
|
|
368
|
+
# @abstract
|
369
|
+
# Implemented by subclasses to interact with the backend
|
370
|
+
# @return [void]
|
280
371
|
def do_rollback
|
281
372
|
raise StorageException, "The current storage does not support transactions"
|
282
373
|
end
|
283
374
|
|
375
|
+
# Creates a new savepoint
|
376
|
+
# @param [String] name
|
377
|
+
# @return [void]
|
284
378
|
def savepoint(name)
|
285
379
|
curr[:savepoints] << name
|
286
380
|
end
|
287
381
|
|
382
|
+
# Rolls back a savepoint
|
383
|
+
# @param [String] name
|
384
|
+
# @return [void]
|
288
385
|
def rollback_savepoint(name=nil)
|
289
386
|
if name
|
290
387
|
curr[:savepoints] = curr[:savepoints][0,(curr[:savepoints].index(name))]
|
@@ -296,30 +393,47 @@ module Spider; module Model; module Storage
|
|
296
393
|
|
297
394
|
# Utility methods
|
298
395
|
|
396
|
+
# @param [String] name Sequence name
|
397
|
+
# @return [String] Path to the sequence file
|
299
398
|
def sequence_file_path(name)
|
300
399
|
path = File.join(Spider.paths[:var], 'sequences', name)
|
301
400
|
return path
|
302
401
|
end
|
303
402
|
|
403
|
+
# @param [String] name Sequence name
|
404
|
+
# @return [bool] True if the sequence file exists
|
304
405
|
def sequence_exists?(name)
|
305
406
|
File.exist?(sequence_file_path(name))
|
306
407
|
end
|
307
408
|
|
409
|
+
# Creates a new sequence
|
410
|
+
# @param [String] name Sequence name
|
411
|
+
# @param [Fixnum] start
|
412
|
+
# @param [Fixnum] increment
|
413
|
+
# @return [void]
|
308
414
|
def create_sequence(name, start=1, increment=1)
|
309
415
|
sequence_next(name, start-1, increment)
|
310
416
|
end
|
311
417
|
|
418
|
+
# @return [String] A new UUID
|
312
419
|
def generate_uuid
|
313
420
|
Spider::DataTypes::UUID.generate
|
314
421
|
end
|
315
422
|
|
316
|
-
|
423
|
+
# Updates a sequence
|
424
|
+
# @param [String] name Sequence name
|
425
|
+
# @param [Fixnum] val New value for the sequence
|
426
|
+
# @return [Fixnum] New value for the sequence
|
317
427
|
def update_sequence(name, val)
|
318
428
|
# not an alias because the set value behaviour of next_sequence isn't expected in subclasses
|
319
429
|
sequence_next(name, val)
|
320
430
|
end
|
321
431
|
|
322
432
|
# Increments a named sequence and returns the new value
|
433
|
+
# @param [String] name Sequence name
|
434
|
+
# @param [Fixnum] newval New value for the sequence
|
435
|
+
# @param [Fixnum] increment
|
436
|
+
# @return [Fixnum] New value for the sequence
|
323
437
|
def sequence_next(name, newval=nil, increment=1)
|
324
438
|
path = sequence_file_path(name)
|
325
439
|
FileUtils.mkpath(File.dirname(path))
|
@@ -360,6 +474,7 @@ module Spider; module Model; module Storage
|
|
360
474
|
# Exceptions #
|
361
475
|
###############################
|
362
476
|
|
477
|
+
# Exception for Storage related errors
|
363
478
|
class StorageException < RuntimeError
|
364
479
|
end
|
365
480
|
|
@@ -6,8 +6,7 @@ module Spider; module Model; module Storage; module Db
|
|
6
6
|
|
7
7
|
# Represents a DB connection, and provides methods to execute structured queries on it.
|
8
8
|
# This is the class that generates the actual SQL; vendor specific extensions may override the
|
9
|
-
# generic SQL methods.
|
10
|
-
|
9
|
+
# generic SQL methods.
|
11
10
|
class DbStorage < Storage::BaseStorage
|
12
11
|
@reserved_keywords = ['from', 'order', 'where', 'to']
|
13
12
|
@type_synonyms = {}
|
@@ -26,15 +25,19 @@ module Spider; module Model; module Storage; module Db
|
|
26
25
|
|
27
26
|
class << self
|
28
27
|
# An Array of keywords that can not be used in schema names.
|
28
|
+
# @return [Array]
|
29
29
|
attr_reader :reserved_keywords
|
30
30
|
# An Hash of DB type equivalents.
|
31
|
+
# @return [Hash]
|
31
32
|
attr_reader :type_synonyms
|
32
|
-
# Type conversions which do not lose data. See also #safe_schema_conversion?
|
33
|
+
# Type conversions which do not lose data. See also {#safe_schema_conversion?}
|
34
|
+
# @return [Hash]
|
33
35
|
attr_reader :safe_conversions
|
34
36
|
# Types for which we can safely ignore length in conversions
|
37
|
+
# @return [Array]
|
35
38
|
attr_reader :fixed_length_types
|
36
39
|
|
37
|
-
|
40
|
+
# @return [Symbol] A label for the storage's class.
|
38
41
|
def storage_type
|
39
42
|
:db
|
40
43
|
end
|
@@ -1,10 +1,17 @@
|
|
1
1
|
#require 'spiderfw/model/storage/db/connectors/odbc'
|
2
2
|
|
3
3
|
module Spider; module Model
|
4
|
-
|
4
|
+
|
5
|
+
# The namespace for classes related to storage.
|
6
|
+
#
|
7
|
+
# See {BaseStorage}.
|
5
8
|
module Storage
|
6
9
|
|
7
10
|
|
11
|
+
# Returns an instance of a BaseStorage subclass, according to type and type-specific url
|
12
|
+
# @param [String] type The type of storage. Can be 'db' (for DataBase storages),
|
13
|
+
# 'doc' (for Document storages), or 'stub' (for a Test stub).
|
14
|
+
# @param [String] url A connection url, specific to the storage.
|
8
15
|
def self.get_storage(type, url)
|
9
16
|
Thread.current[:storages] ||= {}
|
10
17
|
Thread.current[:storages][type] ||= {}
|
@@ -195,15 +195,17 @@ module Spider
|
|
195
195
|
url_db_type = $1
|
196
196
|
end
|
197
197
|
end
|
198
|
-
ask _("Database type: "), :db_type, :choices => ['mysql', 'oracle'], \
|
198
|
+
ask _("Database type: "), :db_type, :choices => ['sqlite', 'mysql', 'oracle'], \
|
199
199
|
:default => url_db_type
|
200
200
|
break unless @db_type
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
201
|
+
unless @db_type == 'sqlite'
|
202
|
+
db = wizard_instance(get_db_wizard(@db_type))
|
203
|
+
db.parse_url(conf["url"]) if conf && conf["url"] && @db_type == url_db_type
|
204
|
+
db.run
|
205
|
+
editor = Spider.config.get_editor
|
206
|
+
editor.set('storages', @db_label, 'url', db.get_url)
|
207
|
+
editor.save
|
208
|
+
end
|
207
209
|
puts _("Configuration saved.")
|
208
210
|
end
|
209
211
|
|