FIX: compatibility with ActiveRecord param encoder

FIX: compatibility with ActiveRecord param encoder

MiniSql supports swapping in a param encoder. Builder had some params which were not compatible with ARs encoder since AR ignores stuff like :_test the underscore denotes an ignore.

This changes the prefix in builder from _m_ to mq_auto_

diff --git a/CHANGELOG b/CHANGELOG
index 1ea58c6..61b66bf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+2021-03-22 - 1.1.1
+
+- FIX: compatability with ActiveRecord param encoder
+
 2021-03-22 - 1.1.0
 
 - FEATURE: added new APIs to support prepared statements
diff --git a/lib/mini_sql/builder.rb b/lib/mini_sql/builder.rb
index 983f262..497b9de 100644
--- a/lib/mini_sql/builder.rb
+++ b/lib/mini_sql/builder.rb
@@ -17,9 +17,11 @@ class MiniSql::Builder
         @args.merge!(args[0])
       else # convert simple params to hash
         args.each do |v|
-          param = "_m_#{@count_variables += 1}"
+          # for compatability with AR param encoded we keep a non _
+          # prefix (must be [a-z])
+          param = "mq_auto_#{@count_variables += 1}"
           sql_part = sql_part.sub('?', ":#{param}")
-          @args[param] = v
+          @args[param.to_sym] = v
         end
       end
 
@@ -31,7 +33,7 @@ class MiniSql::Builder
 
   [:limit, :offset].each do |k|
     define_method k do |value|
-      @args["_m_#{k}"] = value
+      @args["mq_auto_#{k}".to_sym] = value
       @sections[k] = true
       self
     end
@@ -82,9 +84,9 @@ class MiniSql::Builder
       when :left_join
         joined = v.map { |item| (+"LEFT JOIN ") << item }.join("\n")
       when :limit
-        joined = (+"LIMIT :_m_limit")
+        joined = (+"LIMIT :mq_auto_limit")
       when :offset
-        joined = (+"OFFSET :_m_offset")
+        joined = (+"OFFSET :mq_auto_offset")
       when :order_by
         joined = (+"ORDER BY ") << v.join(" , ")
       when :group_by
diff --git a/lib/mini_sql/postgres/connection.rb b/lib/mini_sql/postgres/connection.rb
index 88d4766..9df9e40 100644
--- a/lib/mini_sql/postgres/connection.rb
+++ b/lib/mini_sql/postgres/connection.rb
@@ -3,7 +3,7 @@
 module MiniSql
   module Postgres
     class Connection < MiniSql::Connection
-      attr_reader :raw_connection, :type_map, :param_encoder
+      attr_reader :raw_connection, :param_encoder
 
       def self.default_deserializer_cache
         @deserializer_cache ||= DeserializerCache.new
diff --git a/lib/mini_sql/version.rb b/lib/mini_sql/version.rb
index d39bc93..897e33c 100644
--- a/lib/mini_sql/version.rb
+++ b/lib/mini_sql/version.rb
@@ -1,4 +1,4 @@
 # frozen_string_literal: true
 module MiniSql
-  VERSION = "1.1.0"
+  VERSION = "1.1.1"
 end
diff --git a/test/mini_sql/builder_tests.rb b/test/mini_sql/builder_tests.rb
index 486fe91..a083b65 100644
--- a/test/mini_sql/builder_tests.rb
+++ b/test/mini_sql/builder_tests.rb
@@ -1,6 +1,25 @@
 # frozen_string_literal: true
 
 module MiniSql::BuilderTests
+  class ValidatingParamEncoder
+    def initialize(old_encoder)
+      @old_encoder = old_encoder
+    end
+
+    def encode(sql, *params)
+      params[0].each do |(k, v)|
+        if !(Symbol === k)
+          raise "Attempting to use a String instead of Symbol as a key"
+        end
+
+        if !k.to_s.match?(/^[a-z]/i)
+          raise "Incompatible key used"
+        end
+      end
+      @old_encoder.encode(sql, *params)
+    end
+  end
+
   def test_where
     builder = @connection.build("select 1 as one /*where*/")
     builder.where("1 = :zero")
@@ -8,6 +27,33 @@ module MiniSql::BuilderTests
     assert_equal(0, l)
   end
 
+  def test_param_encoder_compat
+    ignore_warnings do
+      class << @connection
+        alias :old_param_encoder :param_encoder
+        def param_encoder
+          MiniSql::BuilderTests::ValidatingParamEncoder.new(old_param_encoder)
+        end
+      end
+    end
+
+    builder = @connection.build("select 1 as one /*where*/ /*offset*/ /*limit*/")
+    builder.where("1 = ?", 0)
+    builder.where("2 = :not_two", not_two: 1)
+    builder.offset(2)
+    builder.limit(2)
+
+    # all params replaced
+    refute_match(/:/, builder.to_sql)
+
+  ensure
+    ignore_warnings do
+      class << @connection
+        alias :param_encoder :old_param_encoder
+      end
+    end
+  end
+
   def test_append_params
     builder = @connection.build("select 1 as one /*where*/")
     builder.where("1 = :zero", zero: 0)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index dcda83d..16b7e0e 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -57,3 +57,11 @@ require "time"
 require_relative "mini_sql/connection_tests"
 require_relative "mini_sql/builder_tests"
 require_relative "mini_sql/prepared_connection_tests"
+
+# can be more tidy and strategic, but will do for small blocks of code
+def ignore_warnings
+  old_stderr = $stderr
+  $stderr = StringIO.new
+ensure
+  $stderr = old_stderr
+end

GitHub sha: e6ffa5dd

1 Like