nitro 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/{ChangeLog → CHANGELOG} +137 -0
  2. data/INSTALL +1 -2
  3. data/README +1 -1
  4. data/Rakefile +10 -61
  5. data/benchmark/{nitro/bench.rb → bench.rb} +1 -1
  6. data/benchmark/{nitro/simple-webrick-n-200.txt → simple-webrick-n-200.txt} +0 -0
  7. data/benchmark/{nitro/static-webrick-n-200.txt → static-webrick-n-200.txt} +0 -0
  8. data/benchmark/{nitro/tiny-lhttpd-n-200-c-5.txt → tiny-lhttpd-n-200-c-5.txt} +0 -0
  9. data/benchmark/{nitro/tiny-webrick-n-200-c-5.txt → tiny-webrick-n-200-c-5.txt} +0 -0
  10. data/benchmark/{nitro/tiny-webrick-n-200.txt → tiny-webrick-n-200.txt} +0 -0
  11. data/benchmark/{nitro/tiny2-webrick-n-200.txt → tiny2-webrick-n-200.txt} +0 -0
  12. data/doc/{ChangeLog.1 → CHANGELOG.1} +0 -0
  13. data/{RELEASES → doc/RELEASES} +46 -0
  14. data/doc/faq.txt +7 -0
  15. data/examples/README.windows +1 -1
  16. data/examples/ajax/controller.rb +21 -0
  17. data/examples/ajax/public/index.xhtml +70 -0
  18. data/examples/ajax/public/js/ajax.js +64 -0
  19. data/examples/ajax/run.rb +16 -0
  20. data/examples/blog/README +6 -3
  21. data/examples/blog/conf/apache.conf +2 -2
  22. data/examples/blog/conf/lhttpd.conf +2 -2
  23. data/examples/blog/log/apache.error_log +777 -0
  24. data/examples/blog/{root → public}/base.xsl +0 -0
  25. data/examples/blog/{root → public}/fcgi.rb +0 -0
  26. data/examples/blog/{root → public}/m/bubbles.gif +0 -0
  27. data/examples/blog/{root → public}/m/comments_curve.gif +0 -0
  28. data/examples/blog/{root → public}/m/down.gif +0 -0
  29. data/examples/blog/{root → public}/m/footer_bg.gif +0 -0
  30. data/examples/blog/{root → public}/m/garrow.gif +0 -0
  31. data/examples/blog/{root → public}/m/gbull.gif +0 -0
  32. data/examples/blog/{root → public}/m/grbull.gif +0 -0
  33. data/examples/blog/{root → public}/m/h1_bg.gif +0 -0
  34. data/examples/blog/{root → public}/m/header_bg.gif +0 -0
  35. data/examples/blog/{root → public}/m/nitro.gif +0 -0
  36. data/examples/blog/{root → public}/m/obull.gif +0 -0
  37. data/examples/blog/{root → public}/m/page_bg.gif +0 -0
  38. data/examples/blog/{root → public}/m/rss.gif +0 -0
  39. data/examples/blog/{root → public}/m/side_title_bg.gif +0 -0
  40. data/examples/blog/{root → public}/m/sidebar_bg.gif +0 -0
  41. data/examples/{no_xsl_blog/root → blog/public}/style.css +6 -0
  42. data/examples/blog/run.rb +10 -12
  43. data/examples/blog/{lib → src}/blog.rb +3 -3
  44. data/examples/blog/{lib/blog → src}/controller.rb +13 -2
  45. data/examples/blog/src/mailer.rb +23 -0
  46. data/examples/blog/{lib/blog/model.rb → src/models/blog.rb} +4 -7
  47. data/examples/blog/src/models/content.rb +52 -0
  48. data/examples/blog/src/views/blog_entry_email.xhtml +16 -0
  49. data/examples/blog/{root → src/views}/comments.xhtml +0 -0
  50. data/examples/blog/{root → src/views}/entry_form.xhtml +0 -0
  51. data/examples/blog/{root → src/views}/error.xhtml +0 -0
  52. data/examples/blog/{root → src/views}/index.xhtml +0 -0
  53. data/examples/blog/{root → src/views}/login.xhtml +0 -0
  54. data/examples/blog/{root → src/views}/recent_posts.xhtml +0 -0
  55. data/examples/blog/{root → src/views}/view_entry.xhtml +8 -0
  56. data/examples/blog/{root → src/views}/view_entry.xml +0 -0
  57. data/examples/blog/src/xsl/base.xsl +153 -0
  58. data/examples/blog/{root → src/xsl}/style.xsl +2 -2
  59. data/examples/no_xsl_blog/README +5 -1
  60. data/examples/no_xsl_blog/conf/apache.conf +2 -2
  61. data/examples/no_xsl_blog/conf/lhttpd.conf +2 -2
  62. data/examples/no_xsl_blog/lib/blog/model.rb +1 -1
  63. data/{lib/parts → examples/no_xsl_blog/lib}/content.rb +1 -11
  64. data/examples/no_xsl_blog/log/apache.error_log +405 -0
  65. data/examples/no_xsl_blog/{root → public}/comments.xhtml +0 -0
  66. data/examples/no_xsl_blog/{root → public}/entry_form.xhtml +0 -0
  67. data/examples/no_xsl_blog/{root → public}/fcgi.rb +0 -0
  68. data/examples/no_xsl_blog/{root → public}/index.xhtml +0 -0
  69. data/examples/no_xsl_blog/{root → public}/login.xhtml +0 -0
  70. data/examples/no_xsl_blog/{root → public}/m/bubbles.gif +0 -0
  71. data/examples/no_xsl_blog/{root → public}/m/comments_curve.gif +0 -0
  72. data/examples/no_xsl_blog/{root → public}/m/down.gif +0 -0
  73. data/examples/no_xsl_blog/{root → public}/m/footer_bg.gif +0 -0
  74. data/examples/no_xsl_blog/{root → public}/m/garrow.gif +0 -0
  75. data/examples/no_xsl_blog/{root → public}/m/gbull.gif +0 -0
  76. data/examples/no_xsl_blog/{root → public}/m/grbull.gif +0 -0
  77. data/examples/no_xsl_blog/{root → public}/m/h1_bg.gif +0 -0
  78. data/examples/no_xsl_blog/{root → public}/m/header_bg.gif +0 -0
  79. data/examples/no_xsl_blog/{root → public}/m/nitro.gif +0 -0
  80. data/examples/no_xsl_blog/{root → public}/m/obull.gif +0 -0
  81. data/examples/no_xsl_blog/{root → public}/m/page_bg.gif +0 -0
  82. data/examples/no_xsl_blog/{root → public}/m/rss.gif +0 -0
  83. data/examples/no_xsl_blog/{root → public}/m/side_title_bg.gif +0 -0
  84. data/examples/no_xsl_blog/{root → public}/m/sidebar_bg.gif +0 -0
  85. data/examples/no_xsl_blog/{root → public}/recent_posts.xhtml +0 -0
  86. data/examples/{blog/root → no_xsl_blog/public}/style.css +0 -0
  87. data/examples/no_xsl_blog/{root → public}/view_entry.xhtml +0 -0
  88. data/examples/no_xsl_blog/{root → public}/view_entry.xml +0 -0
  89. data/examples/tiny/conf/apache.conf +2 -2
  90. data/examples/tiny/log/apache.error_log +100 -0
  91. data/examples/tiny/{root → public}/fcgi.rb +0 -0
  92. data/examples/tiny/{root → public}/include.xhtml +0 -0
  93. data/examples/tiny/{root → public}/index.xhtml +0 -0
  94. data/{bin/proto/root/m → examples/tiny/public}/nitro.png +0 -0
  95. data/examples/tiny/{root → public}/upload.xhtml +0 -0
  96. data/examples/tiny/run.rb +1 -2
  97. data/examples/why_wiki/wiki.yml +1 -0
  98. data/install.rb +5 -2
  99. data/lib/nitro.rb +2 -6
  100. data/lib/nitro/adapters/fastcgi.rb +2 -2
  101. data/lib/nitro/adapters/webrick.rb +4 -4
  102. data/lib/nitro/conf.rb +5 -2
  103. data/lib/nitro/controller.rb +2 -2
  104. data/lib/nitro/dispatcher.rb +19 -8
  105. data/lib/nitro/mail.rb +252 -8
  106. data/lib/nitro/render.rb +24 -21
  107. data/lib/nitro/runner.rb +1 -1
  108. data/lib/nitro/scaffold.rb +2 -5
  109. data/lib/nitro/simple.rb +2 -1
  110. data/lib/nitro/template.rb +42 -2
  111. data/test/nitro/tc_controller.rb +9 -4
  112. data/test/nitro/tc_dispatcher.rb +4 -6
  113. data/test/nitro/tc_mail.rb +95 -0
  114. data/test/{root → public}/blog/list.xhtml +0 -0
  115. data/test/public/dummy_mailer/registration.xhtml +5 -0
  116. data/vendor/README +0 -1
  117. metadata +136 -181
  118. data/benchmark/og/bench.rb +0 -75
  119. data/benchmark/og/sqlite-no-prepare.1.txt +0 -13
  120. data/benchmark/og/sqlite-no-prepare.2.txt +0 -13
  121. data/benchmark/og/sqlite-prepare.1.txt +0 -13
  122. data/benchmark/og/sqlite-prepare.2.txt +0 -13
  123. data/bin/proto/README +0 -34
  124. data/bin/proto/conf/apache.conf +0 -1
  125. data/bin/proto/conf/app.conf.rb +0 -14
  126. data/bin/proto/conf/lhttpd.conf +0 -236
  127. data/bin/proto/ctl +0 -4
  128. data/bin/proto/lib/README +0 -5
  129. data/bin/proto/log/README +0 -3
  130. data/bin/proto/root/fcgi.rb +0 -6
  131. data/bin/proto/root/index.xhtml +0 -69
  132. data/bin/proto/root/style.css +0 -152
  133. data/bin/proto/root/style.xsl +0 -99
  134. data/doc/og_config.txt +0 -35
  135. data/doc/og_tutorial.txt +0 -595
  136. data/examples/og/README +0 -11
  137. data/examples/og/mock_example.rb +0 -50
  138. data/examples/og/mysql_to_psql.rb +0 -96
  139. data/examples/og/run.rb +0 -286
  140. data/examples/tiny/root/nitro.png +0 -0
  141. data/lib/glue.rb +0 -55
  142. data/lib/glue/array.rb +0 -61
  143. data/lib/glue/attribute.rb +0 -83
  144. data/lib/glue/cache.rb +0 -138
  145. data/lib/glue/flexob.rb +0 -12
  146. data/lib/glue/hash.rb +0 -122
  147. data/lib/glue/inflector.rb +0 -91
  148. data/lib/glue/logger.rb +0 -147
  149. data/lib/glue/misc.rb +0 -14
  150. data/lib/glue/mixins.rb +0 -36
  151. data/lib/glue/number.rb +0 -24
  152. data/lib/glue/object.rb +0 -32
  153. data/lib/glue/pool.rb +0 -60
  154. data/lib/glue/property.rb +0 -408
  155. data/lib/glue/string.rb +0 -162
  156. data/lib/glue/time.rb +0 -85
  157. data/lib/glue/validation.rb +0 -394
  158. data/lib/og.rb +0 -185
  159. data/lib/og/adapter.rb +0 -513
  160. data/lib/og/adapters/filesys.rb +0 -121
  161. data/lib/og/adapters/mysql.rb +0 -347
  162. data/lib/og/adapters/oracle.rb +0 -375
  163. data/lib/og/adapters/psql.rb +0 -273
  164. data/lib/og/adapters/sqlite.rb +0 -262
  165. data/lib/og/backend.rb +0 -297
  166. data/lib/og/connection.rb +0 -304
  167. data/lib/og/database.rb +0 -282
  168. data/lib/og/enchant.rb +0 -125
  169. data/lib/og/meta.rb +0 -373
  170. data/lib/og/mock.rb +0 -165
  171. data/lib/og/observer.rb +0 -53
  172. data/lib/og/typemacros.rb +0 -23
  173. data/lib/parts/README +0 -9
  174. data/test/glue/tc_attribute.rb +0 -22
  175. data/test/glue/tc_cache.rb +0 -45
  176. data/test/glue/tc_hash.rb +0 -38
  177. data/test/glue/tc_logger.rb +0 -39
  178. data/test/glue/tc_numbers.rb +0 -20
  179. data/test/glue/tc_property.rb +0 -89
  180. data/test/glue/tc_property_mixins.rb +0 -93
  181. data/test/glue/tc_property_type_checking.rb +0 -35
  182. data/test/glue/tc_strings.rb +0 -103
  183. data/test/glue/tc_validation.rb +0 -188
  184. data/test/og/tc_filesys.rb +0 -83
  185. data/test/og/tc_lifecycle.rb +0 -104
  186. data/test/og/tc_many_to_many.rb +0 -62
  187. data/test/og/tc_meta.rb +0 -55
  188. data/test/og/tc_observer.rb +0 -85
  189. data/test/og/tc_sqlite.rb +0 -87
  190. data/test/tc_og.rb +0 -355
  191. data/vendor/composite_sexp_processor.rb +0 -43
  192. data/vendor/parse_tree.rb +0 -745
  193. data/vendor/sexp_processor.rb +0 -453
@@ -1,375 +0,0 @@
1
- # * Matt Bowen <matt.bowen@farweststeel.com>
2
- # * George Moschovitis <gm@navel.gr>
3
- # (c) 2004-2005 Navel, all rights reserved.
4
- # $Id: oracle.rb 270 2005-03-07 17:52:16Z gmosx $
5
-
6
- require 'oracle'
7
-
8
- require 'og/adapter'
9
- require 'og/connection'
10
- require 'glue/attribute'
11
-
12
- module Og
13
-
14
- # The Oracle adapter. This adapter communicates with
15
- # an Oracle rdbms. For extra documentation see
16
- # lib/og/adapter.rb
17
-
18
- class OracleAdapter < Adapter
19
-
20
- def initialize
21
- super
22
- @typemap.update(
23
- Integer => 'number',
24
- Fixnum => 'number',
25
- String => 'varchar2(512)',
26
- TrueClass => 'number',
27
- Object => 'varchar2(1024)',
28
- Array => 'varchar2(1024)',
29
- Hash => 'varchar2(1024)'
30
- )
31
- @typecast.update(TrueClass => "#\{:s: ? \"1\" : 'NULL' \}")
32
- end
33
-
34
- def self.timestamp(time = Time.now)
35
- return nil unless time
36
- return time.strftime("%Y-%m-%d %H:%M:%S")
37
- end
38
-
39
- def self.date(date)
40
- return nil unless date
41
- return "#{date.year}-#{date.month}-#{date.mday}"
42
- end
43
-
44
- def write_prop(p)
45
- if p.klass.ancestors.include?(Integer)
46
- return "#\{@#{p.symbol} || 'NULL'\}"
47
- elsif p.klass.ancestors.include?(Float)
48
- return "#\{@#{p.symbol} || 'NULL'\}"
49
- elsif p.klass.ancestors.include?(String)
50
- return "'#\{#{self.class}.escape(@#{p.symbol})\}'"
51
- elsif p.klass.ancestors.include?(Time)
52
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
53
- elsif p.klass.ancestors.include?(Date)
54
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.date(@#{p.symbol})\}'" : 'NULL'\}|
55
- elsif p.klass.ancestors.include?(TrueClass)
56
- return "#\{@#{p.symbol} ? \"1\" : 'NULL' \}"
57
- else
58
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
59
- end
60
- end
61
-
62
- #--
63
- # mcb:
64
- # Unlike MySQL or Postgres, Oracle database/schema creation is a big deal.
65
- # I don't know how to do it from the command line. I use Oracle's Database
66
- # Configuration Assistant utility (dbca). I takes 30min - 1hr to create
67
- # a full blown schema. So, your FIXME comments are fine. I'm thinking you
68
- # won't be able to do this via Og, but once created, Og will be able to create
69
- # tables, indexes, and other objects.
70
- #++
71
-
72
- def create_db(database, user = nil, password = nil)
73
- # FIXME: what is appropriate for oracle?
74
- # `createdb #{database} -U #{user}`
75
- super
76
- end
77
-
78
- def drop_db(database, user = nil, password = nil)
79
- # FIXME: what is appropriate for oracle?
80
- # `dropdb #{database} -U #{user}`
81
- super
82
- end
83
-
84
- def insert_code(klass, db, pre_cb, post_cb)
85
- props = props_for_insert(klass)
86
- values = props.collect { |p| write_prop(p) }.join(',')
87
-
88
- sql = "INSERT INTO #{klass::DBTABLE} (#{props.collect {|p| p.name}.join(',')}) VALUES (#{values})"
89
-
90
- %{
91
- #{pre_cb}
92
- res = conn.store.exec("SELECT #{klass::DBSEQ}.nextval FROM DUAL")
93
- @oid = res.fetch[0].to_i
94
- res.close
95
- conn.exec "#{sql}"
96
- #{post_cb}
97
- }
98
- end
99
-
100
- def new_connection(db)
101
- return OracleConnection.new(db)
102
- end
103
-
104
- def calc_field_index(klass, db)
105
- # gmosx: This is incredible!!! argh!
106
- # res = db.query "SELECT * FROM #{klass::DBTABLE} # LIMIT 1"
107
- res = db.query "SELECT * FROM (SELECT * FROM #{klass::DBTABLE}) WHERE ROWNUM <= 1"
108
- meta = db.managed_classes[klass]
109
-
110
- columns = res.getColNames
111
-
112
- for idx in (0...columns.size)
113
- # mcb: Oracle will return column names in uppercase.
114
- meta.field_index[columns[idx].downcase] = idx
115
- end
116
-
117
- ensure
118
- res.close if res
119
- end
120
-
121
- def eval_og_oid(klass)
122
- klass.class_eval %{
123
- prop_accessor :oid, Fixnum, :sql => "number PRIMARY KEY"
124
- }
125
- end
126
-
127
- def create_table(klass, db)
128
- conn = db.get_connection
129
-
130
- fields = create_fields(klass)
131
-
132
- sql = "CREATE TABLE #{klass::DBTABLE} (#{fields.join(', ')}"
133
-
134
- # Create table constrains.
135
-
136
- if klass.__meta and constrains = klass.__meta[:sql_constrain]
137
- sql << ", #{constrains.join(', ')}"
138
- end
139
-
140
- # mcb: Oracle driver chokes on semicolon.
141
- sql << ")"
142
-
143
- # mcb:
144
- # Oracle driver appears to have problems executing multiple SQL
145
- # statements in single exec() call. Chokes with or without semicolon
146
- # delimiter. Solution: make separate calls for each statement.
147
-
148
- begin
149
- conn.store.exec(sql).close
150
- Logger.info "Created table '#{klass::DBTABLE}'."
151
-
152
- # Create indices.
153
-
154
- if klass.__meta and indices = klass.__meta[:sql_index]
155
- for data in indices
156
- idx, options = *data
157
- idx = idx.to_s
158
- pre_sql, post_sql = options[:pre], options[:post]
159
- idxname = idx.gsub(/ /, "").gsub(/,/, "_").gsub(/\(.*\)/, "")
160
- sql = " CREATE #{pre_sql} INDEX #{klass::DBTABLE}_#{idxname}_idx #{post_sql} ON #{klass::DBTABLE} (#{idx})"
161
- conn.store.exec(sql).close
162
- Logger.info "Created index '#{klass::DBTABLE}_#{idxname}_idx'."
163
- end
164
- end
165
- rescue Exception => ex
166
- # gmosx: any idea how to better test this?
167
- if ex.to_s =~ /ORA-00955/i
168
- Logger.debug 'Table or index already exists' if $DBG
169
- return
170
- else
171
- raise
172
- end
173
- end
174
-
175
- # Create the sequence for this table.
176
- begin
177
- conn.store.exec("CREATE SEQUENCE #{klass::DBSEQ}").close
178
- Logger.info "Created sequence '#{klass::DBSEQ}'."
179
- rescue Exception => ex
180
- # gmosx: any idea how to better test this?
181
- if ex.to_s =~ /ORA-00955/i
182
- Logger.debug "Sequence already exists" if $DBG
183
- else
184
- raise
185
- end
186
- end
187
-
188
- # Create join tables if needed. Join tables are used in
189
- # 'many_to_many' relations.
190
-
191
- if klass.__meta and joins = klass.__meta[:sql_join]
192
- for data in joins
193
- # the class to join to and some options.
194
- join_name, join_class, options = *data
195
-
196
- # gmosx: dont use DBTABLE here, perhaps the join class
197
- # is not managed yet.
198
- join_table = "#{self.class.join_table(klass, join_class, join_name)}"
199
- join_src = "#{self.class.encode(klass)}_oid"
200
- join_dst = "#{self.class.encode(join_class)}_oid"
201
- begin
202
- conn.store.exec("CREATE TABLE #{join_table} ( key1 integer NOT NULL, key2 integer NOT NULL )").close
203
- conn.store.exec("CREATE INDEX #{join_table}_key1_idx ON #{join_table} (key1)").close
204
- conn.store.exec("CREATE INDEX #{join_table}_key2_idx ON #{join_table} (key2)").close
205
- rescue Exception => ex
206
- # gmosx: any idea how to better test this?
207
- if ex.to_s =~ /ORA-00955/i
208
- Logger.debug "Join table already exists" if $DBG
209
- else
210
- raise
211
- end
212
- end
213
- end
214
- end
215
-
216
- ensure
217
- db.put_connection
218
- end
219
-
220
- def drop_table(klass)
221
- super
222
- exec "DROP SEQUENCE #{klass::DBSEQ}"
223
- end
224
-
225
- # Generate the property for oid.
226
-
227
- #--
228
- # mcb:
229
- # Oracle doesn't have a "serial" datatype. Replace with
230
- # integer (which is probably just a synonym for NUMBER(38,0))
231
- # A sequence is created automatically by Og.
232
- #++
233
-
234
- def eval_og_oid(klass)
235
- klass.class_eval %{
236
- prop_accessor :oid, Fixnum, :sql => 'integer PRIMARY KEY'
237
- }
238
- end
239
- end
240
-
241
- # The Oracle connection.
242
-
243
- class OracleConnection < Connection
244
-
245
- # mcb:
246
- # The database connection details are tucked away in a
247
- # TNS entry (Transparent Network Substrate) which specifies host,
248
- # port, protocol, and database instance. Here is a sample TNS
249
- # entry:
250
- #
251
- # File: tns_names.ora
252
- #
253
- # KBSID =
254
- # (DESCRIPTION =
255
- # (ADDRESS_LIST =
256
- # (ADDRESS = (PROTOCOL = TCP)(HOST = keebler.farweststeel.com)(PORT = 1521))
257
- # )
258
- # (CONNECT_DATA =
259
- # (SID = KBSID)
260
- # )
261
- # )
262
-
263
- def initialize(db)
264
- super
265
- config = db.config
266
-
267
- begin
268
- # FIXME: how to pass address etc?
269
- @store = Oracle.new(config[:user], config[:password], config[:database])
270
- # gmosx: better use this???
271
- # @store = Oracle.new(config[:tns])
272
-
273
- # gmosx: does this work?
274
- @store.autocommit = true
275
- rescue Exception => ex
276
- # mcb:
277
- # Oracle will raise a ORA-01017 if username, password, or
278
- # SID aren't valid. I verified this for all three.
279
- # irb(main):002:0> conn = Oracle.new('keebler', 'dfdfd', 'kbsid')
280
- # /usr/local/lib/ruby/site_ruby/1.8/oracle.rb:27:in `logon': ORA-01017: invalid username/password; logon denied (OCIError)
281
- # gmosx:
282
- # any idea how to better test this? an integer error id?
283
- if ex.to_s =~ /ORA-01017/i
284
- Logger.info "Database '#{config[:database]}' not found!"
285
- @db.adapter.create_db(config[:database], config[:user])
286
- retry
287
- end
288
- raise
289
- end
290
- end
291
-
292
- def close
293
- @store.logoff
294
- super
295
- end
296
-
297
- def query(sql)
298
- Logger.debug sql if $DBG
299
- begin
300
- return @store.exec(sql)
301
- rescue Exception => ex
302
- Logger.error "DB error #{ex}, [#{sql}]"
303
- Logger.error ex.backtrace.join("\n")
304
- raise
305
- # return nil
306
- end
307
- end
308
-
309
- def exec(sql)
310
- Logger.debug sql if $DBG
311
- begin
312
- @store.exec(sql)
313
- rescue Exception => ex
314
- Logger.error "DB error #{ex}, [#{sql}]"
315
- Logger.error ex.backtrace.join("\n")
316
- raise
317
- end
318
- end
319
-
320
- def start
321
- @store.autocommit = false
322
- end
323
-
324
- def commit
325
- @store.commit
326
- ensure
327
- @store.autocommit = true
328
- end
329
-
330
- def rollback
331
- @store.rollback
332
- ensure
333
- @store.autocommit = true
334
- end
335
-
336
- def valid_res?(res)
337
- return !(res.nil?)
338
- end
339
-
340
- def read_one(res, klass)
341
- return nil unless valid_res?(res)
342
-
343
- row = res.fetch
344
- return nil unless row
345
-
346
- obj = klass.new
347
- obj.og_read(row)
348
-
349
- res.close
350
- return obj
351
- end
352
-
353
- def read_all(res, klass)
354
- return [] unless valid_res?(res)
355
- objects = []
356
-
357
- while row = res.fetch
358
- obj = klass.new
359
- obj.og_read(row)
360
- objects << obj
361
- end
362
-
363
- res.close
364
- return objects
365
- end
366
-
367
- def read_int(res, idx = 0)
368
- val = res.fetch[idx].to_i
369
- res.close
370
- return val
371
- end
372
-
373
- end
374
-
375
- end
@@ -1,273 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: psql.rb 270 2005-03-07 17:52:16Z gmosx $
4
-
5
- require 'postgres'
6
-
7
- require 'og/adapter'
8
- require 'og/connection'
9
- require 'glue/attribute'
10
-
11
- module Og
12
-
13
- # The PostgreSQL adapter. This adapter communicates with
14
- # an PostgreSQL rdbms. For extra documentation see
15
- # lib/og/adapter.rb
16
-
17
- class PsqlAdapter < Adapter
18
-
19
- def self.escape(str)
20
- return nil unless str
21
- return PGconn.escape(str)
22
- end
23
-
24
- def self.timestamp(time = Time.now)
25
- return nil unless time
26
- return time.strftime("%Y-%m-%d %H:%M:%S")
27
- end
28
-
29
- def self.date(date)
30
- return nil unless date
31
- return "#{date.year}-#{date.month}-#{date.mday}"
32
- end
33
-
34
- def read_prop(p, idx)
35
- if p.klass.ancestors.include?(Integer)
36
- return "res.getvalue(tuple, #{idx}).to_i()"
37
- elsif p.klass.ancestors.include?(Float)
38
- return "res.getvalue(tuple, #{idx}).to_f()"
39
- elsif p.klass.ancestors.include?(String)
40
- return "res.getvalue(tuple, #{idx})"
41
- elsif p.klass.ancestors.include?(Time)
42
- return "#{self.class}.parse_timestamp(res.getvalue(tuple, #{idx}))"
43
- elsif p.klass.ancestors.include?(Date)
44
- return "#{self.class}.parse_date(res.getvalue(tuple, #{idx}))"
45
- elsif p.klass.ancestors.include?(TrueClass)
46
- return %|('t' == res.getvalue(tuple, #{idx}))|
47
- else
48
- return "YAML::load(res.getvalue(tuple, #{idx}))"
49
- end
50
- end
51
-
52
- def create_db(database, user = nil, password = nil)
53
- `createdb #{database} -U #{user}`
54
- super
55
- end
56
-
57
- def drop_db(database, user = nil, password = nil)
58
- `dropdb #{database} -U #{user}`
59
- super
60
- end
61
-
62
- def insert_code(klass, db, pre_cb, post_cb)
63
- props = props_for_insert(klass)
64
- values = props.collect { |p| write_prop(p) }.join(',')
65
-
66
- sql = "INSERT INTO #{klass::DBTABLE} (#{props.collect {|p| p.name}.join(',')}) VALUES (#{values})"
67
-
68
- %{
69
- #{pre_cb}
70
- res = conn.store.exec("SELECT nextval('#{klass::DBSEQ}')")
71
- @oid = res.getvalue(0, 0).to_i
72
- res.clear
73
- conn.exec "#{sql}"
74
- #{post_cb}
75
- }
76
- end
77
-
78
- def new_connection(db)
79
- return PsqlConnection.new(db)
80
- end
81
-
82
- def calc_field_index(klass, db)
83
- res = db.query "SELECT * FROM #{klass::DBTABLE} LIMIT 1"
84
- meta = db.managed_classes[klass]
85
-
86
- for field in res.fields
87
- meta.field_index[field] = res.fieldnum(field)
88
- end
89
-
90
- ensure
91
- res.clear if res
92
- end
93
-
94
- def create_table(klass, db)
95
- conn = db.get_connection
96
-
97
- fields = create_fields(klass)
98
-
99
- sql = "CREATE TABLE #{klass::DBTABLE} (#{fields.join(', ')}"
100
-
101
- # Create table constrains.
102
-
103
- if klass.__meta and constrains = klass.__meta[:sql_constrain]
104
- sql << ", #{constrains.join(', ')}"
105
- end
106
-
107
- sql << ") WITHOUT OIDS;"
108
-
109
- # Create indices.
110
-
111
- if klass.__meta and indices = klass.__meta[:sql_index]
112
- for data in indices
113
- idx, options = *data
114
- idx = idx.to_s
115
- pre_sql, post_sql = options[:pre], options[:post]
116
- idxname = idx.gsub(/ /, "").gsub(/,/, "_").gsub(/\(.*\)/, "")
117
- sql << " CREATE #{pre_sql} INDEX #{klass::DBTABLE}_#{idxname}_idx #{post_sql} ON #{klass::DBTABLE} (#{idx});"
118
- end
119
- end
120
-
121
- begin
122
- conn.store.exec(sql).clear
123
- Logger.info "Created table '#{klass::DBTABLE}'."
124
- rescue => ex
125
- # gmosx: any idea how to better test this?
126
- if ex.to_s =~ /relation .* already exists/i
127
- Logger.debug 'Table already exists' if $DBG
128
- return
129
- else
130
- raise
131
- end
132
- end
133
-
134
- # Create join tables if needed. Join tables are used in
135
- # 'many_to_many' relations.
136
-
137
- if klass.__meta and joins = klass.__meta[:sql_join]
138
- for data in joins
139
- # the class to join to and some options.
140
- join_name, join_class, options = *data
141
-
142
- # gmosx: dont use DBTABLE here, perhaps the join class
143
- # is not managed yet.
144
- join_table = "#{self.class.join_table(klass, join_class, join_name)}"
145
- join_src = "#{self.class.encode(klass)}_oid"
146
- join_dst = "#{self.class.encode(join_class)}_oid"
147
- begin
148
- conn.store.exec("CREATE TABLE #{join_table} ( key1 integer NOT NULL, key2 integer NOT NULL )").clear
149
- conn.store.exec("CREATE INDEX #{join_table}_key1_idx ON #{join_table} (key1)").clear
150
- conn.store.exec("CREATE INDEX #{join_table}_key2_idx ON #{join_table} (key2)").clear
151
- rescue => ex
152
- # gmosx: any idea how to better test this?
153
- if ex.to_s =~ /relation .* already exists/i
154
- Logger.debug "Join table already exists" if $DBG
155
- else
156
- raise
157
- end
158
- end
159
- end
160
- end
161
-
162
- ensure
163
- db.put_connection
164
- end
165
-
166
- def drop_table(klass)
167
- super
168
- exec "DROP SEQUENCE #{klass::DBSEQ}"
169
- end
170
-
171
- # Generate the property for oid.
172
-
173
- def eval_og_oid(klass)
174
- klass.class_eval %{
175
- prop_accessor :oid, Fixnum, :sql => 'serial PRIMARY KEY'
176
- }
177
- end
178
-
179
- end
180
-
181
- # The PostgreSQL connection.
182
-
183
- class PsqlConnection < Connection
184
-
185
- def initialize(db)
186
- super
187
-
188
- config = db.config
189
-
190
- begin
191
- @store = PGconn.connect(
192
- config[:address],
193
- config[:port],
194
- nil,
195
- nil,
196
- config[:database],
197
- config[:user].to_s,
198
- config[:password].to_s
199
- )
200
- rescue => ex
201
- # gmosx: any idea how to better test this?
202
- if ex.to_s =~ /database .* does not exist/i
203
- Logger.info "Database '#{config[:database]}' not found!"
204
- @db.adapter.create_db(config[:database], config[:user])
205
- retry
206
- end
207
- raise
208
- end
209
- end
210
-
211
- def close
212
- @store.close
213
- super
214
- end
215
-
216
- def query(sql)
217
- Logger.debug sql if $DBG
218
- begin
219
- return @store.exec(sql)
220
- rescue => ex
221
- Logger.error "DB error #{ex}, [#{sql}]"
222
- Logger.error ex.backtrace.join("\n")
223
- return nil
224
- end
225
- end
226
-
227
- def exec(sql)
228
- Logger.debug sql if $DBG
229
- begin
230
- @store.exec(sql).clear
231
- rescue => ex
232
- Logger.error "DB error #{ex}, [#{sql}]"
233
- Logger.error ex.backtrace.join("\n")
234
- end
235
- end
236
-
237
- def valid_res?(res)
238
- return !(res.nil? or 0 == res.num_tuples)
239
- end
240
-
241
- def read_one(res, klass)
242
- return nil unless valid_res?(res)
243
-
244
- obj = klass.new
245
- obj.og_read(res, 0)
246
-
247
- res.clear
248
- return obj
249
- end
250
-
251
- def read_all(res, klass)
252
- return [] unless valid_res?(res)
253
- objects = []
254
-
255
- for tuple in (0...res.num_tuples)
256
- obj = klass.new
257
- obj.og_read(res, tuple)
258
- objects << obj
259
- end
260
-
261
- res.clear
262
- return objects
263
- end
264
-
265
- def read_int(res, idx = 0)
266
- val = res.getvalue(0, idx).to_i
267
- res.clear
268
- return val
269
- end
270
-
271
- end
272
-
273
- end