nitro 0.9.5 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/ChangeLog +260 -0
  2. data/INSTALL +60 -0
  3. data/LICENSE +1 -0
  4. data/README +19 -20
  5. data/RELEASES +48 -0
  6. data/Rakefile +102 -92
  7. data/benchmark/og/bench.rb +74 -0
  8. data/benchmark/og/sqlite-no-prepare.1.txt +13 -0
  9. data/benchmark/og/sqlite-no-prepare.2.txt +13 -0
  10. data/benchmark/og/sqlite-prepare.1.txt +13 -0
  11. data/benchmark/og/sqlite-prepare.2.txt +13 -0
  12. data/bin/cluster +1 -1
  13. data/bin/nitro +3 -0
  14. data/bin/proto/conf/app.conf.rb +2 -10
  15. data/examples/README.windows +9 -0
  16. data/examples/blog/README +16 -4
  17. data/examples/blog/lib/blog.rb +3 -3
  18. data/examples/blog/lib/blog/controller.rb +7 -9
  19. data/examples/blog/root/fcgi.rb +2 -4
  20. data/examples/blog/root/style.xsl +4 -6
  21. data/examples/blog/run.rb +41 -0
  22. data/examples/flash/run.rb +9 -0
  23. data/examples/no_xsl_blog/README +0 -1
  24. data/examples/no_xsl_blog/conf/app.conf.rb +6 -13
  25. data/examples/no_xsl_blog/lib/blog.rb +2 -2
  26. data/examples/no_xsl_blog/lib/blog/controller.rb +6 -6
  27. data/examples/no_xsl_blog/root/fcgi.rb +2 -4
  28. data/examples/no_xsl_blog/run.rb +38 -0
  29. data/examples/og/mock_example.rb +0 -2
  30. data/examples/og/mysql_to_psql.rb +0 -2
  31. data/examples/og/run.rb +23 -22
  32. data/examples/tiny/root/fcgi.rb +2 -4
  33. data/examples/tiny/root/index.xhtml +21 -5
  34. data/examples/tiny/root/upload.xhtml +23 -0
  35. data/examples/tiny/run.rb +9 -0
  36. data/examples/wee_style/{wee.rb → run.rb} +13 -13
  37. data/install.rb +44 -0
  38. data/lib/glue/array.rb +6 -10
  39. data/lib/glue/attribute.rb +0 -3
  40. data/lib/glue/cache.rb +1 -1
  41. data/lib/glue/inflector.rb +5 -5
  42. data/lib/glue/mixins.rb +3 -12
  43. data/lib/glue/number.rb +1 -1
  44. data/lib/glue/object.rb +7 -1
  45. data/lib/glue/property.rb +32 -22
  46. data/lib/glue/string.rb +13 -75
  47. data/lib/glue/time.rb +2 -2
  48. data/lib/glue/validation.rb +7 -11
  49. data/lib/nitro.rb +16 -1
  50. data/lib/nitro/{adaptors → adapters}/cgi.rb +101 -20
  51. data/lib/nitro/{adaptors → adapters}/fastcgi.rb +3 -2
  52. data/lib/nitro/{adaptors → adapters}/webrick.rb +4 -4
  53. data/lib/nitro/builders/rss.rb +1 -1
  54. data/lib/nitro/builders/xml.rb +8 -10
  55. data/lib/nitro/cluster.rb +1 -1
  56. data/lib/nitro/conf.rb +34 -0
  57. data/lib/nitro/controller.rb +8 -9
  58. data/lib/nitro/dispatcher.rb +38 -11
  59. data/lib/nitro/filters.rb +1 -1
  60. data/lib/nitro/markup.rb +14 -1
  61. data/lib/nitro/render.rb +7 -10
  62. data/lib/nitro/runner.rb +232 -0
  63. data/lib/nitro/ui/pager.rb +2 -6
  64. data/lib/nitro/uri.rb +7 -11
  65. data/lib/og.rb +27 -261
  66. data/lib/og/adapter.rb +352 -0
  67. data/lib/og/adapters/mysql.rb +304 -0
  68. data/lib/og/adapters/psql.rb +286 -0
  69. data/lib/og/adapters/sqlite.rb +262 -0
  70. data/lib/og/backend.rb +1 -1
  71. data/lib/og/connection.rb +123 -87
  72. data/lib/og/database.rb +268 -0
  73. data/lib/og/meta.rb +23 -22
  74. data/lib/og/mock.rb +2 -3
  75. data/lib/xsl/base.xsl +1 -55
  76. data/test/glue/tc_property.rb +2 -0
  77. data/test/glue/tc_property_type_checking.rb +32 -0
  78. data/test/glue/tc_strings.rb +2 -2
  79. data/test/glue/tc_validation.rb +2 -0
  80. data/test/nitro/adapters/raw_post1.bin +0 -0
  81. data/test/nitro/{adaptors → adapters}/tc_cgi.rb +11 -2
  82. data/test/nitro/{adaptors → adapters}/tc_webrick.rb +3 -3
  83. data/test/nitro/builders/tc_xml.rb +14 -5
  84. data/test/nitro/tc_dispatcher.rb +3 -3
  85. data/test/nitro/tc_uri.rb +2 -4
  86. data/test/og/tc_lifecycle.rb +22 -25
  87. data/test/og/tc_sqlite.rb +87 -0
  88. data/test/tc_og.rb +61 -42
  89. metadata +67 -33
  90. data/examples/blog/conf/app.conf.rb +0 -52
  91. data/examples/blog/ctl +0 -4
  92. data/examples/flash/conf/app.conf.rb +0 -21
  93. data/examples/flash/ctl +0 -4
  94. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  95. data/examples/no_xsl_blog/ctl +0 -4
  96. data/examples/tiny/conf/app.conf.rb +0 -17
  97. data/examples/tiny/ctl +0 -4
  98. data/lib/glue/macro.rb +0 -56
  99. data/lib/nitro/adaptors/runner.rb +0 -123
  100. data/lib/nitro/version.rb +0 -15
  101. data/lib/og/backends/mysql.rb +0 -370
  102. data/lib/og/backends/psql.rb +0 -386
  103. data/lib/og/backends/sqlite.rb +0 -383
  104. data/lib/og/version.rb +0 -9
@@ -1,383 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id$
4
-
5
- require 'sqlite'
6
-
7
- require 'og/backend'
8
-
9
- class Og
10
-
11
- # Implements an SQLite powered backend.
12
-
13
- class SqliteBackend < Backend
14
-
15
- # A mapping between Ruby and SQL types.
16
-
17
- TYPEMAP = {
18
- Integer => 'integer',
19
- Fixnum => 'integer',
20
- Float => 'float',
21
- String => 'text',
22
- Time => 'timestamp',
23
- Date => 'date',
24
- TrueClass => 'boolean',
25
- Object => 'text',
26
- Array => 'text',
27
- Hash => 'text'
28
- }
29
-
30
- # Intitialize the connection to the RDBMS.
31
-
32
- def initialize(config)
33
- begin
34
- @conn = SQLite::Database.new(config[:database])
35
- rescue => ex
36
- # gmosx: any idea how to better test this?
37
- if ex.to_s =~ /database .* does not exist/i
38
- Logger.info "Database '#{config[:database]}' not found!"
39
- SqliteBackend.create_db(config[:database], config[:user])
40
- retry
41
- end
42
- raise
43
- end
44
- end
45
-
46
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47
- # Utilities
48
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49
-
50
- # Escape an SQL string
51
-
52
- def self.escape(str)
53
- return nil unless str
54
- return str.gsub( /'/, "''" )
55
- end
56
-
57
- # Convert a ruby time to an sql timestamp.
58
- # TODO: Optimize this
59
-
60
- def self.timestamp(time = Time.now)
61
- return nil unless time
62
- return time.strftime("%Y-%m-%d %H:%M:%S")
63
- end
64
-
65
- # Output YYY-mm-dd
66
- # TODO: Optimize this
67
-
68
- def self.date(date)
69
- return nil unless date
70
- return "#{date.year}-#{date.month}-#{date.mday}"
71
- end
72
-
73
- # Parse sql datetime
74
- # TODO: Optimize this
75
-
76
- def self.parse_timestamp(str)
77
- return Time.parse(str)
78
- end
79
-
80
- # Input YYYY-mm-dd
81
- # TODO: Optimize this
82
-
83
- def self.parse_date(str)
84
- return nil unless str
85
- return Date.strptime(str)
86
- end
87
-
88
- # Return an sql string evaluator for the property.
89
- # No need to optimize this, used only to precalculate code.
90
- # YAML is used to store general Ruby objects to be more
91
- # portable.
92
- #
93
- # FIXME: add extra handling for float.
94
-
95
- def self.write_prop(p)
96
- if p.klass.ancestors.include?(Integer)
97
- return "#\{@#{p.symbol} || 'NULL'\}"
98
- elsif p.klass.ancestors.include?(Float)
99
- return "#\{@#{p.symbol} || 'NULL'\}"
100
- elsif p.klass.ancestors.include?(String)
101
- return "'#\{SqliteBackend.escape(@#{p.symbol})\}'"
102
- elsif p.klass.ancestors.include?(Time)
103
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
104
- elsif p.klass.ancestors.include?(Date)
105
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.date(@#{p.symbol})\}'" : 'NULL'\}|
106
- elsif p.klass.ancestors.include?(TrueClass)
107
- return "#\{@#{p.symbol} ? \"'t'\" : 'NULL' \}"
108
- else
109
- return %|#\{@#{p.symbol} ? "'#\{SqliteBackend.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
110
- end
111
- end
112
-
113
- # Return an evaluator for reading the property.
114
- # No need to optimize this, used only to precalculate code.
115
-
116
- def self.read_prop(p, idx)
117
- if p.klass.ancestors.include?(Integer)
118
- return "res.getvalue(tuple, #{idx}).to_i()"
119
- elsif p.klass.ancestors.include?(Float)
120
- return "res.getvalue(tuple, #{idx}).to_f()"
121
- elsif p.klass.ancestors.include?(String)
122
- return "res.getvalue(tuple, #{idx})"
123
- elsif p.klass.ancestors.include?(Time)
124
- return "PsqlBackend.parse_timestamp(res.getvalue(tuple, #{idx}))"
125
- elsif p.klass.ancestors.include?(Date)
126
- return "PsqlBackend.parse_date(res.getvalue(tuple, #{idx}))"
127
- elsif p.klass.ancestors.include?(TrueClass)
128
- return %|('t' == res.getvalue(tuple, #{idx}))|
129
- else
130
- return "YAML::load(res.getvalue(tuple, #{idx}))"
131
- end
132
- end
133
-
134
- # Returns the code that actually inserts the object into the
135
- # database. Returns the code as String.
136
-
137
- def self.insert_code(klass, sql, pre_cb, post_cb)
138
- %{
139
- #{pre_cb}
140
- res = conn.db.query("SELECT nextval('#{klass::DBSEQ}')")
141
- @oid = res.getvalue(0, 0).to_i
142
- conn.exec "#{sql}"
143
- #{post_cb}
144
- }
145
- end
146
-
147
- # generate the mapping of the database fields to the
148
- # object properties.
149
-
150
- def self.calc_field_index(klass, og)
151
- res = og.query "SELECT * FROM #{klass::DBTABLE} LIMIT 1"
152
- meta = og.managed_classes[klass]
153
-
154
- for field in res.fields
155
- meta.field_index[field] = res.fieldnum(field)
156
- end
157
- end
158
-
159
- # Generate the property for oid
160
-
161
- def self.eval_og_oid(klass)
162
- klass.class_eval %{
163
- prop_accessor :oid, Fixnum, :sql => "integer PRIMARY KEY"
164
- }
165
- end
166
-
167
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168
- # Connection methods.
169
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170
-
171
- # Create the database.
172
-
173
- def self.create_db(database, user = nil, password = nil)
174
- Logger.info "Creating database '#{database}'."
175
- `createdb #{database} -U #{user}`
176
- end
177
-
178
- # Drop the database.
179
-
180
- def self.drop_db(database, user = nil, password = nil)
181
- Logger.info "Dropping database '#{database}'."
182
- `dropdb #{database} -U #{user}`
183
- end
184
-
185
- # Execute an SQL query and return the result.
186
-
187
- def query(sql)
188
- Logger.debug sql if $DBG
189
- return @conn.exec(sql)
190
- end
191
-
192
- # Execute an SQL query, no result returned.
193
-
194
- def exec(sql)
195
- Logger.debug sql if $DBG
196
- res = @conn.exec(sql)
197
- res.clear()
198
- end
199
-
200
- # Execute an SQL query and return the result. Wrapped in a rescue
201
- # block.
202
-
203
- def safe_query(sql)
204
- Logger.debug sql if $DBG
205
- begin
206
- return @conn.exec(sql)
207
- rescue => ex
208
- Logger.error "DB error #{ex}, [#{sql}]"
209
- Logger.error ex.backtrace
210
- return nil
211
- end
212
- end
213
-
214
- # Execute an SQL query, no result returned. Wrapped in a rescue
215
- # block.
216
-
217
- def safe_exec(sql)
218
- Logger.debug sql if $DBG
219
- begin
220
- res = @conn.exec(sql)
221
- res.clear()
222
- rescue => ex
223
- Logger.error "DB error #{ex}, [#{sql}]"
224
- Logger.error ex.backtrace
225
- end
226
- end
227
-
228
- # Check if it is a valid resultset.
229
-
230
- def valid?(res)
231
- return !(res.nil? or 0 == res.num_tuples)
232
- end
233
-
234
- # Create the managed object table. The properties of the
235
- # object are mapped to the table columns. Additional sql relations
236
- # and constrains are created (indicices, sequences, etc).
237
-
238
- def create_table(klass)
239
- fields = create_fields(klass, TYPEMAP)
240
-
241
- sql = "CREATE TABLE #{klass::DBTABLE} (#{fields.join(', ')}"
242
-
243
- # Create table constrains
244
-
245
- if klass.__meta and constrains = klass.__meta[:sql_constrain]
246
- sql << ", #{constrains.join(', ')}"
247
- end
248
-
249
- sql << ") WITHOUT OIDS;"
250
-
251
- # Create indices
252
-
253
- if klass.__meta and indices = klass.__meta[:sql_index]
254
- for data in indices
255
- idx, options = *data
256
- idx = idx.to_s
257
- pre_sql, post_sql = options[:pre], options[:post]
258
- idxname = idx.gsub(/ /, "").gsub(/,/, "_").gsub(/\(.*\)/, "")
259
- sql << " CREATE #{pre_sql} INDEX #{klass::DBTABLE}_#{idxname}_idx #{post_sql} ON #{klass::DBTABLE} (#{idx});"
260
- end
261
- end
262
-
263
- begin
264
- exec(sql)
265
- Logger.info "Created table '#{klass::DBTABLE}'."
266
- rescue => ex
267
- # gmosx: any idea how to better test this?
268
- if ex.to_s =~ /relation .* already exists/i
269
- Logger.debug "Table already exists" if $DBG
270
- else
271
- raise
272
- end
273
- end
274
-
275
- # create the sequence for this table. Even if the table
276
- # uses the oids_seq, attempt to create it. This makes
277
- # the system more fault tolerant.
278
-
279
- begin
280
- exec "CREATE SEQUENCE #{klass::DBSEQ}"
281
- Logger.info "Created sequence '#{klass::DBSEQ}'."
282
- rescue => ex
283
- # gmosx: any idea how to better test this?
284
- if ex.to_s =~ /relation .* already exists/i
285
- Logger.debug "Sequence already exists" if $DBG
286
- else
287
- raise
288
- end
289
- end
290
-
291
- # Create join tables if needed. Join tables are used in
292
- # 'many_to_many' relations.
293
-
294
- if klass.__meta and joins = klass.__meta[:sql_join]
295
- for data in joins
296
- # the class to join to and some options.
297
- join_class, options = *data
298
-
299
- # gmosx: dont use DBTABLE here, perhaps the join class
300
- # is not managed yet.
301
- join_table = "#{self.class.join_table(klass, join_class)}"
302
- join_src = "#{self.class.encode(klass)}_oid"
303
- join_dst = "#{self.class.encode(join_class)}_oid"
304
- begin
305
- exec "CREATE TABLE #{join_table} ( key1 integer NOT NULL, key2 integer NOT NULL )"
306
- exec "CREATE INDEX #{join_table}_key1_idx ON #{join_table} (key1)"
307
- exec "CREATE INDEX #{join_table}_key2_idx ON #{join_table} (key2)"
308
- rescue => ex
309
- # gmosx: any idea how to better test this?
310
- if ex.to_s =~ /relation .* already exists/i
311
- Logger.debug "Join table already exists" if $DBG
312
- else
313
- raise
314
- end
315
- end
316
- end
317
- end
318
-
319
- begin
320
- exec(sql)
321
- Logger.info "Created join table '#{join_table}'."
322
- rescue => ex
323
- # gmosx: any idea how to better test this?
324
- if ex.to_s =~ /relation .* already exists/i
325
- Logger.debug "Join table already exists" if $DBG
326
- else
327
- raise
328
- end
329
- end
330
-
331
- end
332
-
333
- # Drop the managed object table.
334
-
335
- def drop_table(klass)
336
- super
337
- exec "DROP SEQUENCE #{klass::DBSEQ}"
338
- end
339
-
340
- # Deserialize one row of the resultset.
341
-
342
- def deserialize_one(res, klass)
343
- return nil unless valid?(res)
344
-
345
- # gmosx: Managed objects should have no params constructor.
346
- entity = klass.new()
347
- entity.og_deserialize(res, 0)
348
-
349
- # get_join_fields(res, 0, entity, join_fields) if join_fields
350
-
351
- res.clear()
352
- return entity
353
- end
354
-
355
- # Deserialize all rows of the resultset.
356
-
357
- def deserialize_all(res, klass)
358
- return [] unless valid?(res)
359
-
360
- entities = []
361
-
362
- for tuple in (0...res.num_tuples)
363
- entity = klass.new()
364
- entity.og_deserialize(res, tuple)
365
-
366
- # get_join_fields(res, tuple, entity, join_fields) if join_fields
367
-
368
- entities << entity
369
- end
370
-
371
- res.clear()
372
- return entities
373
- end
374
-
375
- # Return a single integer value from the resultset.
376
-
377
- def get_int(res, idx = 0)
378
- return res.getvalue(0, idx).to_i
379
- end
380
-
381
- end
382
-
383
- end
data/lib/og/version.rb DELETED
@@ -1,9 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: version.rb 248 2005-01-31 13:38:34Z gmosx $
4
-
5
- class Og
6
- # The version of Og.
7
-
8
- Version = '0.9.5'
9
- end