instacart / makara

A Read-Write Proxy for Connections; Also provides an ActiveRecord adapter.
http://tech.taskrabbit.com/
MIT License
928 stars 170 forks source link

Choosing Primary instead of Replica when using 'with' (because of newlines) #376

Open jackcb123 opened 1 year ago

jackcb123 commented 1 year ago

Issue: Many of my complex sql statements were being performed by the primary instead of the replica. It turns out that the sql_replica_matchers regex is insufficient for queries that begin with CTE 'with' statements.

In lib/active_record/connection_adapters/makara_abstract_adapter.rb

SQL_REPLICA_MATCHERS = [/\A\s*(select|with.+\)\s*select)\s/i].map(&:freeze).freeze

should be changed to

SQL_REPLICA_MATCHERS = [/\A\s*(select|with[\s\S]*\)\s*select)\s/i].map(&:freeze).freeze

[\s\S] is the difference and accounts for new lines.

This is because '.' regex doesn't account for new lines (which will obviously be there in complex sql statements).

My workaround is this. Hope this helps! :)

class ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter < ::Makara::Proxy
  CUSTOM_SQL_REPLICA_MATCHERS = [/\A\s*(select|with[\s\S]*\)\s*select)\s/i].map(&:freeze).freeze

  def sql_slave_matchers
    CUSTOM_SQL_REPLICA_MATCHERS
  end

  def sql_replica_matchers
    CUSTOM_SQL_REPLICA_MATCHERS
  end
end