nitro 0.12.0 → 0.13.0

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.
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