spiderfw 0.6.23 → 0.6.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|