Skip to content

Instantly share code, notes, and snippets.

@mattantonelli
Last active October 1, 2024 16:39
Show Gist options
  • Save mattantonelli/b5e85f059e5e1b7fa2b4c8a023d0e263 to your computer and use it in GitHub Desktop.
Save mattantonelli/b5e85f059e5e1b7fa2b4c8a023d0e263 to your computer and use it in GitHub Desktop.
Snowflake in Ruby on Rails with the odbc_adapter gem
# Place in config/initializers
require 'active_record/connection_adapters/odbc_adapter'
require 'odbc_adapter/adapters/postgresql_odbc_adapter'
# Patch the Postgres adapter to remove the unsupported RETURNING clause from inserts
class ODBCAdapter::Adapters::PostgreSQLODBCAdapter
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
super
end
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
[sql, binds]
end
end
ODBCAdapter.register(/snowflake/, ODBCAdapter::Adapters::PostgreSQLODBCAdapter) do
# Explicitly turning off prepared statements as they are not yet working with
# snowflake + the ODBC ActiveRecord adapter
def prepared_statements
false
end
# Quoting needs to be changed for snowflake
def quote_column_name(name)
name.to_s
end
private
# Override dbms_type_cast to get the values encoded in UTF-8
def dbms_type_cast(columns, values)
values.each do |row|
row.each_index do |idx|
row[idx] = row[idx].force_encoding('UTF-8') if row[idx].is_a?(String)
end
end
end
end
# Snowflake only has NUMBER data types. This provides a method for forcing known
# integer types like ID to actually be treated as Integer.
module IntegerCoercion
def set_integer_columns(*cols)
cols.each do |col|
columns_hash[col.to_s].instance_variable_set(:@cast_type, ActiveRecord::Type::Integer.new)
end
end
end
ActiveRecord::Base.extend(IntegerCoercion)
class SampleModel < ActiveRecord::Base
set_integer_columns :id
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment