The Oracle adapter. This adapter communicates with an Oracle rdbms. For extra documentation see lib/og/adapter.rb

Connects to Oracle by config[:user], config[:password], config[:database], config[:privilege]. If you need DBA privilege, please set privilege as :SYSDBA or :SYSOPER.

Contents
Methods
Included Modules
Public Class methods
new()
    # File lib/og/adapter/oracle/old.rb, line 20
20:   def initialize
21:     super
22:     
23:     @typemap.update(
24:       Integer => 'number',
25:       Fixnum => 'number',
26:       String => 'varchar2(1024)', # max might be 4000 (Oracle 8)
27:       TrueClass => 'char(1)',
28:       Numeric => 'number',
29:       Object => 'varchar2(1024)',
30:       Array => 'varchar2(1024)',
31:       Hash => 'varchar2(1024)'
32:     )
33:     
34:     # TODO: how to pass address etc?
35:     @store = Oracle.new(config[:user], config[:password], config[:database])
36:     # gmosx: better use this???
37:     # @store = Oracle.new(config[:tns])
38: 
39:     # gmosx: does this work?
40:     @store.autocommit = true
41:   rescue Exception => ex
42:     # mcb:
43:       # Oracle will raise a ORA-01017 if username, password, or 
44:     # SID aren't valid. I verified this for all three.
45:     # irb(main):002:0> conn = Oracle.new('keebler', 'dfdfd', 'kbsid')
46:     # /usr/local/lib/ruby/site_ruby/1.8/oracle.rb:27:in `logon': ORA-01017: invalid username/password; logon denied (OCIError)
47:     if database_does_not_exist_exception? ex
48:       Logger.info "Database '#{options[:name]}' not found!"
49:       create_db(options)
50:       retry
51:     end
52:     raise
53:   end
Public Instance methods
close()
    # File lib/og/adapter/oracle/old.rb, line 55
55:   def close
56:     @store.logoff
57:     super
58:   end
create_db(database, user = nil, password = nil)
    # File lib/og/adapter/oracle/old.rb, line 70
70:   def create_db(database, user = nil, password = nil)
71:     # FIXME: what is appropriate for oracle?
72:     # `createdb #{database} -U #{user}`
73:     super
74:     raise NotImplementedError, "Oracle Database/Schema creation n/a"
75:   end
drop_db(database, user = nil, password = nil)
    # File lib/og/adapter/oracle/old.rb, line 77
77:   def drop_db(database, user = nil, password = nil)
78:     # FIXME: what is appropriate for oracle?
79:     # `dropdb #{database} -U #{user}`
80:     super
81:     raise NotImplementedError, "Oracle Database/Schema dropping n/a"
82:   end
enchant(klass, manager)
     # File lib/og/adapter/oracle/old.rb, line 90
 90:   def enchant(klass, manager)
 91:     pk = klass.primary_key
 92:     
 93:     seq = if klass.schema_inheritance_child?
 94:       "#{table(klass.schema_inheritance_root_class)}_#{pk}_seq"
 95:     else
 96:       "#{table(klass)}_#{pk}_seq"
 97:     end
 98:     
 99:     pkann = klass.ann[pk]
100:     
101:     pkann[:sequence] = seq unless pkann[:sequence] == false
102:     
103:     super
104:   end
exec_statement(sql)
     # File lib/og/adapter/oracle/old.rb, line 110
110:   def exec_statement(sql)
111:     @conn.exec(sql).clear
112:   end
insert_sql(sql, klass)

The insert sql statements.

     # File lib/og/adapter/oracle/old.rb, line 136
136:   def insert_sql(sql, klass)
137:     str = ''
138:     
139:     if klass.ann[klass.primary_key][:sequence]
140:       str << "@#{klass.primary_key} = store.last_insert_id(#{klass})\n"
141:     end
142:     
143:     str << "store.exec \"#{sql}\""
144:     
145:     return str
146:   end
last_insert_id(klass)

Return the last inserted row id.

     # File lib/og/adapter/oracle/old.rb, line 124
124:   def last_insert_id(klass)
125:     seq = klass.ann[klass.primary_key][:sequence]
126:     
127:     res = query_statement("SELECT #{seq}.nextval FROM DUAL")
128:     lid = Integer(res.first_value)
129:     res.close
130:     
131:     return lid
132:   end
primary_key_type()

The type used for default primary keys.

    # File lib/og/adapter/oracle/old.rb, line 86
86:   def primary_key_type
87:     'integer PRIMARY KEY'
88:   end
query_statement(sql)
     # File lib/og/adapter/oracle/old.rb, line 106
106:   def query_statement(sql)
107:     return @conn.exec(sql)
108:   end
sql_update(sql)
     # File lib/og/adapter/oracle/old.rb, line 114
114:   def sql_update(sql)
115:     Logger.debug sql if $DBG  
116:     res = @conn.exec(sql)
117:     changed = res.cmdtuples
118:     res.clear
119:     return changed
120:   end
Public Class methods
new(config)
    # File lib/og/adapter/oracle.rb, line 20
20:   def initialize(config)
21:     super
22:     
23:     @typemap.update(
24:       Integer => 'number',
25:       Fixnum => 'number',
26:       String => 'varchar2(1024)', # max might be 4000 (Oracle 8)
27:       TrueClass => 'char(1)',
28:       Numeric => 'number',
29:       Object => 'varchar2(1024)',
30:       Array => 'varchar2(1024)',
31:       Hash => 'varchar2(1024)',
32:       Time => 'TIMESTAMP',
33:       Date => 'DATE',
34:       DateTime => 'TIMESTAMP'
35:     )
36:     
37:     # TODO: how to pass address etc?
38:     @conn = OCI8.new(
39:       config[:user],
40:       config[:password],
41:       config[:name], 
42:       config[:privilege]
43:     )
44: 
45:     # gmosx: does this work?
46:     @conn.autocommit = true
47:   rescue OCIException => ex
48:     #---
49:     # mcb:
50:       # Oracle will raise a ORA-01017 if username, password, or 
51:     # SID aren't valid. I verified this for all three.
52:     # irb(main):002:0> conn = Oracle.new('keebler', 'dfdfd', 'kbsid')
53:     # /usr/local/lib/ruby/site_ruby/1.8/oracle.rb:27:in `logon': ORA-01017:
54:     # invalid username/password; logon denied (OCIError)
55:     #+++
56:     if database_does_not_exist_exception? ex
57:       Logger.info "Database '#{options[:name]}' not found!"
58:       create_db(options)
59:       retry
60:     end
61:     raise
62:   end
Public Instance methods
close()
    # File lib/og/adapter/oracle.rb, line 64
64:   def close
65:     @conn.logoff
66:     super
67:   end
commit()

Commit a transaction.

     # File lib/og/adapter/oracle/old.rb, line 160
160:   def commit
161:     @transaction_nesting -= 1
162:     @store.commit if @transaction_nesting < 1
163:   ensure
164:     @store.autocommit = true
165:   end
create_db(database, user = nil, password = nil)
    # File lib/og/adapter/oracle.rb, line 79
79:   def create_db(database, user = nil, password = nil)
80:     # FIXME: what is appropriate for oracle?
81:     # `createdb #{database} -U #{user}`
82:     super
83:     raise NotImplementedError, "Oracle Database/Schema creation n/a"
84:   end
create_table(klass)
     # File lib/og/adapter/oracle/old.rb, line 177
177:   def create_table(klass)
178:     super
179:     
180:     seq = klass.ann[klass.primary_key][:sequence]
181:     # Create the sequence for this table. 
182:     begin
183:       exec_statement("CREATE SEQUENCE #{seq}")
184:       Logger.info "Created sequence '#{seq}'."       
185:     rescue Exception => ex
186:       # gmosx: any idea how to better test this?
187:       if table_already_exists_exception?(ex)
188:         Logger.debug "Sequence #{seq} already exists" if $DBG
189:       else
190:         raise
191:       end
192:     end
193:     
194:   end
drop_db(database, user = nil, password = nil)
    # File lib/og/adapter/oracle.rb, line 86
86:   def drop_db(database, user = nil, password = nil)
87:     # FIXME: what is appropriate for oracle?
88:     # `dropdb #{database} -U #{user}`
89:     super
90:     raise NotImplementedError, "Oracle Database/Schema dropping n/a"
91:   end
drop_table(klass)
     # File lib/og/adapter/oracle/old.rb, line 196
196:   def drop_table(klass)
197:     super
198:     exec_statement("DROP SEQUENCE #{klass.ann[klass.primary_key][:sequence]}")
199:   end
enchant(klass, manager)
     # File lib/og/adapter/oracle.rb, line 99
 99:   def enchant(klass, manager)
100:     pk = klass.primary_key
101:     
102:     seq = if klass.schema_inheritance_child?
103:       "#{table(klass.schema_inheritance_root_class)}_#{pk}_seq"
104:     else
105:       "#{table(klass)}_#{pk}_seq"
106:     end
107:     
108:     pkann = klass.ann(pk)
109:     
110:     pkann[:sequence] = OracleUtils.shorten_string(seq) unless pkann[:sequence] == false
111:     
112:     super
113:   end
exec_statement(sql)
     # File lib/og/adapter/oracle.rb, line 119
119:   def exec_statement(sql)
120:     Logger.debug "ORACLE "+sql
121:     @conn.exec(sql)
122:   end
insert_sql(sql, klass)

The insert sql statements.

     # File lib/og/adapter/oracle.rb, line 144
144:   def insert_sql(sql, klass)
145:     str = ''
146:     
147:     if klass.ann(klass.primary_key, :sequence)
148:       str << "@#{klass.primary_key} = store.last_insert_id(#{klass})\n"
149:     end
150:     
151:     str << "store.exec \"#{sql}\""
152:     
153:     return str
154:   end
last_insert_id(klass)

Return the last inserted row id.

     # File lib/og/adapter/oracle.rb, line 132
132:   def last_insert_id(klass)
133:     seq = klass.ann(klass.primary_key, :sequence)
134:     
135:     res = query_statement("SELECT #{seq}.nextval FROM DUAL")
136:     lid = Integer(res.first_value)
137:     res.close
138:     
139:     return lid
140:   end
primary_key_type()

The type used for default primary keys.

    # File lib/og/adapter/oracle.rb, line 95
95:   def primary_key_type
96:     'integer PRIMARY KEY'
97:   end
query_statement(sql)
     # File lib/og/adapter/oracle.rb, line 115
115:   def query_statement(sql)
116:     @conn.exec(sql)
117:   end
read_attr(s, a, col)
     # File lib/og/adapter/oracle/old.rb, line 201
201:   def read_attr(s, a, col)
202:     store = self.class
203:     {
204:       String    => nil,
205:       Integer   => :parse_int,
206:       Float     => :parse_float,
207:       Time      => :parse_timestamp,
208:       Date      => :parse_date,
209:       TrueClass => :parse_boolean,
210:       Og::Blob  => :parse_blob
211:     }.each do |klass, meth|
212:       if a.class.ancestor? klass
213:         return meth ? 
214:           "#{store}.#{meth}(res[#{col} + offset])" : "res[#{col} + offset]"
215:       end
216:     end
217: 
218:     # else try to load it via YAML
219:     "YAML::load(res[#{col} + offset])"
220:   end
rollback()

Rollback a transaction.

     # File lib/og/adapter/oracle/old.rb, line 169
169:   def rollback
170:     @transaction_nesting -= 1
171:     @store.rollbackif @transaction_nesting < 1
172:   ensure
173:     @store.autocommit = true
174:   end
sql_update(sql)
     # File lib/og/adapter/oracle.rb, line 124
124:   def sql_update(sql)
125:     Logger.debug sql if $DBG  
126:     res = @conn.exec(sql)
127:     return res.to_i
128:   end
start()

Start a new transaction.

     # File lib/og/adapter/oracle/old.rb, line 152
152:   def start  
153:     @store.autocommit = false
154:     
155:     @transaction_nesting += 1
156:   end
Public Instance methods
commit()

Commit a transaction.

     # File lib/og/adapter/oracle.rb, line 168
168:   def commit
169:     @transaction_nesting -= 1
170:     @conn.commit if @transaction_nesting < 1
171:   ensure
172:     @conn.autocommit = true
173:   end
rollback()

Rollback a transaction.

     # File lib/og/adapter/oracle.rb, line 177
177:   def rollback
178:     @transaction_nesting -= 1
179:     @conn.rollbackif @transaction_nesting < 1
180:   ensure
181:     @conn.autocommit = true
182:   end
start()

Start a new transaction.

     # File lib/og/adapter/oracle.rb, line 160
160:   def start  
161:     @conn.autocommit = false
162:     
163:     @transaction_nesting += 1
164:   end
Public Instance methods
create_table(klass)

Create the SQL table where instances of the given class will be serialized.

     # File lib/og/adapter/oracle.rb, line 189
189:   def create_table(klass)
190:     fields = fields_for_class(klass)
191:     
192:     # Oracle hard limit
193:     OracleUtils.shorten_table_name(klass) if klass.table.size > 30
194:     raise "ORACLE TOO LONG! #{klass.table.size}" if klass.table.size > 30
195: 
196:     sql = "CREATE TABLE #{klass.table} (#{fields.join(', ')}"
197: 
198:     # Create table constraints.
199: 
200:     if constraints = klass.ann(:self, :sql_constraint)
201:       sql << ", #{constraints.join(', ')}"
202:     end
203: 
204:     sql << ")"
205: 
206:     begin
207:       exec(sql, false)
208:       Logger.info "Created table '#{klass.table}'."
209:     rescue Object => ex
210:       if table_already_exists_exception? ex
211:         # Don't return yet. Fall trough to also check for the 
212:         # join table.
213:       else
214:         handle_sql_exception(ex, sql)
215:       end
216:     end
217:     
218:     seq = klass.ann[klass.primary_key][:sequence]
219:     # Create the sequence for this table. 
220:     begin
221:       exec_statement("CREATE SEQUENCE #{seq} INCREMENT BY 1 START WITH 1 NOMAXVALUE NOMINVALUE NOCYCLE")
222:       Logger.info "Created sequence '#{seq}'."       
223:     rescue OCIError => ex
224:       if table_already_exists_exception?(ex)
225:         Logger.debug "Sequence #{seq} already exists" if $DBG
226:       else
227:         raise
228:       end
229:     end
230:     
231:   end
drop_table(klass)
     # File lib/og/adapter/oracle.rb, line 233
233:   def drop_table(klass)
234:     super
235:     
236:     seq = klass.ann[klass.primary_key][:sequence]
237:     # Create the sequence for this table. 
238:     begin
239:       exec_statement("DROP SEQUENCE #{seq}")
240:       Logger.info "Dropped sequence '#{seq}'."       
241:     rescue OCIError => ex
242:       if sequence_does_not_exist_exception?(ex)
243:         Logger.debug "Sequence #{seq} didn't exist" if $DBG
244:       else
245:         raise
246:       end
247:     end
248:     
249:   end
read_attr(s, a, col)
     # File lib/og/adapter/oracle.rb, line 264
264:   def read_attr(s, a, col)
265:     store = self.class
266:     {
267:       String    => nil,
268:       Integer   => :parse_int,
269:       Float     => :parse_float,
270:       Time      => :parse_timestamp,
271:       Date      => :parse_date,
272:       TrueClass => :parse_boolean,
273:       Og::Blob  => :parse_blob
274:     }.each do |klass, meth|
275:       if a.class.ancestor? klass
276:         return meth ? 
277:           "#{store}.#{meth}(res[#{col} + offset])" : "res[#{col} + offset]"
278:       end
279:     end
280: 
281:     # else try to load it via YAML
282:     "YAML::load(res[#{col} + offset])"
283:   end
resolve_limit_options(options, sql)
     # File lib/og/adapter/oracle.rb, line 251
251:   def resolve_limit_options(options, sql)
252:     from = options[:offset] || 1
253:     to = from + options[:limit] if options[:limit]
254:     sql.replace "SELECT * FROM (#{sql}) WHERE ROWNUM "
255:     if to && from
256:       sql << "BETWEEN #{from} AND #{to}"
257:     elsif to
258:       sql << "<= #{options[:limit]}"
259:     elsif from
260:       sql << ">= #{from}"
261:     end
262:   end