# # $Id: odbcext_virtuoso.rb,v 1.1 2006/12/06 14:42:11 source Exp $ # # OpenLink ODBC Adapter for Ruby on Rails # Copyright (C) 2006 OpenLink Software # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject # to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # module ODBCExt # ------------------------------------------------------------------------ # Mandatory methods # # #last_insert_id must be implemented for any database which returns # false from #prefetch_primary_key? def last_insert_id(table, sequence_name, stmt = nil) @logger.unknown("ODBCAdapter#last_insert_id>") if @trace # 1049 (SQL_LASTSERIAL) is an ODBC extension for SQLGetStmtOption stmt.get_option(1049) end # ------------------------------------------------------------------------ # Optional methods # # These are supplied for a DBMS only if necessary. # ODBCAdapter tests for optional methods using Object#respond_to? # Pre action for ODBCAdapter#insert # def pre_insert(sql, name, pk, id_value, sequence_name) # end # Post action for ODBCAdapter#insert # def post_insert(sql, name, pk, id_value, sequence_name) # end def set_sequence(table_name, pk) begin stmt = @connection.run("select max(#{pk}) + 1 from #{table_name}") next_pk_val = stmt.fetch stmt.drop flds = table_name.split('.') @connection.do("sequence_set('#{flds[0]}.#{flds[1]}.#{table_name}.#{pk}', #{next_pk_val}, 0)") return true rescue Exception => e @logger.unknown("exception=#{e}") if @trace end return false end # ------------------------------------------------------------------------ # Method redefinitions # # DBMS specific methods which override the default implementation # provided by the ODBCAdapter core. def quote_string(s) s.gsub(/\\/, '\&\&').gsub(/'/, "''") end def quoted_date(value) @logger.unknown("ODBCAdapter#quoted_date>") if @trace @logger.unknown("args=[#{value}]") if @trace case value # Ruby Time class includes a date component and so must be # mapped to a Virtuoso DateTime type, not a Virtuoso Time type. when Time, DateTime %Q!stringdate('#{value.strftime("%Y-%m-%d %H:%M:%S")}')! when Date %Q!d('#{value.strftime("%Y-%m-%d")}')! end end def rename_table(name, new_name) @logger.unknown("ODBCAdapter#rename_table>") if @trace @logger.unknown("args=[#{name}|#{new_name}]") if @trace execute "ALTER TABLE #{name} RENAME #{new_name}" rescue Exception => e @logger.unknown("exception=#{e}") if @trace raise ActiveRecord::ActiveRecordError, e.message end def change_column(table_name, column_name, type, options = {}) @logger.unknown("ODBCAdapter#change_column>") if @trace @logger.unknown("args=[#{table_name}|#{column_name}|#{type}]") if @trace change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} " + "#{type_to_sql(type)}" # Add any :null and :default options add_column_options!(change_column_sql, options) execute(change_column_sql) rescue Exception => e @logger.unknown("exception=#{e}") if @trace raise ActiveRecord::ActiveRecordError, e.message end def change_column_default(table_name, column_name, default) @logger.unknown("ODBCAdapter#change_column_default>") if @trace @logger.unknown("args=[#{table_name}|#{column_name}]") if @trace change_column(table_name, column_name, nil, {:default => default}) rescue Exception => e @logger.unknown("exception=#{e}") if @trace raise ActiveRecord::ActiveRecordError, e.message end def remove_index(table_name, options = {}) @logger.unknown("ODBCAdapter#remove_index>") if @trace @logger.unknown("args=[#{table_name}]") if @trace execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} #{table_name}" rescue Exception => e @logger.unknown("exception=#{e}") if @trace raise ActiveRecord::ActiveRecordError, e.message end def indexes(table_name, name = nil) # Virtuoso creates a unique index for a table's primary key. # Hide any such index. The index name matches the table name. # # If this isn't done... # Rails' 'rake test_units' attempts to create this index explicitly, # but Virtuoso rejects this as the index has already been created # automatically when the table was defined. super(table_name, name).delete_if { |i| i.unique && i.name == table_name } end end