From 86ce2b65ff18c96ff1239a65e1702676b5d56b49 Mon Sep 17 00:00:00 2001 From: Loic Nageleisen Date: Thu, 23 Nov 2017 16:33:01 +0100 Subject: [PATCH] Properly handle backslash escaping --- lib/rebel/sql.rb | 6 +++++- test/test_raw.rb | 30 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/rebel/sql.rb b/lib/rebel/sql.rb index 8a91797..b5216e8 100644 --- a/lib/rebel/sql.rb +++ b/lib/rebel/sql.rb @@ -292,7 +292,10 @@ module Rebel end def escape_str(str) - str.gsub(@string_quote, @escaped_string_quote) + str.dup.tap do |s| + s.gsub!('\\') { @escaped_string_backslash } if @escaped_string_backslash + s.gsub!(@string_quote) { @escaped_string_quote } + end end def value(v) @@ -390,6 +393,7 @@ module Rebel @identifier_quote = options[:identifier_quote] || '"' @string_quote = options[:string_quote] || "'" @escaped_string_quote = options[:escaped_string_quote] || "''" + @escaped_string_backslash = options[:escaped_string_backslash] @true_literal = options[:true_literal] || 'TRUE' @false_literal = options[:false_literal] || 'FALSE' diff --git a/test/test_raw.rb b/test/test_raw.rb index 458a29a..e3cee69 100644 --- a/test/test_raw.rb +++ b/test/test_raw.rb @@ -8,7 +8,7 @@ class TestRaw < Minitest::Test end def assert_mysql(expected, &actual) - assert_equal(expected.to_s, Rebel::SQL(identifier_quote: '`', string_quote: '"', escaped_string_quote: '""', &actual).to_s) + assert_equal(expected.to_s, Rebel::SQL(identifier_quote: '`', escaped_string_quote: "\\'", escaped_string_backslash: '\\', &actual).to_s) end def assert_sqlite(expected, &actual) @@ -137,21 +137,31 @@ class TestRaw < Minitest::Test def test_string assert_sql("'FOO'") { value('FOO') } - assert_mysql('"FOO"') { value('FOO') } + assert_mysql("'FOO'") { value('FOO') } assert_postgresql("'FOO'") { value('FOO') } assert_sqlite("'FOO'") { value('FOO') } end def test_escaped_string - assert_sql("'FOO''BAR'") { value("FOO'BAR") } - assert_mysql('"FOO\'BAR"') { value("FOO'BAR") } - assert_postgresql("'FOO''BAR'") { value("FOO'BAR") } - assert_sqlite("'FOO''BAR'") { value("FOO'BAR") } + assert_sql (%q('FOO''BAR')) { value(%q(FOO'BAR)) } + assert_postgresql (%q('FOO''BAR')) { value(%q(FOO'BAR)) } + assert_sqlite (%q('FOO''BAR')) { value(%q(FOO'BAR)) } + assert_mysql (%q('FOO\'BAR')) { value(%q(FOO'BAR)) } - assert_sql("'FOO\"BAR'") { value('FOO"BAR') } - assert_mysql('"FOO""BAR"') { value('FOO"BAR') } - assert_postgresql("'FOO\"BAR'") { value('FOO"BAR') } - assert_sqlite("'FOO\"BAR'") { value('FOO"BAR') } + assert_sql (%q('FOO"BAR')) { value(%q(FOO"BAR)) } + assert_postgresql (%q('FOO"BAR')) { value(%q(FOO"BAR)) } + assert_sqlite (%q('FOO"BAR')) { value(%q(FOO"BAR)) } + assert_mysql (%q('FOO"BAR')) { value(%q(FOO"BAR)) } + + assert_sql (%q('FOO\BAR')) { value(%q(FOO\BAR)) } + assert_postgresql (%q('FOO\BAR')) { value(%q(FOO\BAR)) } + assert_sqlite (%q('FOO\BAR')) { value(%q(FOO\BAR)) } + assert_mysql (%q('FOO\\BAR')) { value(%q(FOO\BAR)) } + + assert_sql (%q('FOO\\''BAR')) { value(%q(FOO\'BAR)) } + assert_postgresql (%q('FOO\\''BAR')) { value(%q(FOO\'BAR)) } + assert_sqlite (%q('FOO\\''BAR')) { value(%q(FOO\'BAR)) } + assert_mysql (%q('FOO\\\'BAR')) { value(%q(FOO\'BAR)) } end def test_boolean_literal