From bfc09d682b8ce1a02c982446a4937b7444147fe8 Mon Sep 17 00:00:00 2001 From: sufleR Date: Fri, 19 Dec 2025 15:02:44 +0100 Subject: [PATCH 1/2] Fix whitespace normalization to preserve SQL quoted strings in ERB templates The previous implementation of prepare_query used a simple regex to normalize whitespace, which incorrectly modified content inside SQL quoted strings when preparing queries for logs. This caused issues with multiline ERB templates where string literals could be corrupted. Changes: - Refactored prepare_query to render ERB first, then normalize whitespace - Added regex pattern to match quoted strings and preserve their content - Only whitespace outside of quotes is normalized to single spaces - Simplified test database configuration to use consistent postgres setup - Added test coverage for multiline ERB templates with quoted strings This fix ensures that SQL string literals remain intact while still providing clean, single-line output for logging purposes. --- lib/sql_query.rb | 12 ++++++++++-- spec/spec_helper.rb | 24 +++++++----------------- spec/sql_queries/multiline_erb.sql.erb | 9 +++++++++ spec/sql_query_spec.rb | 16 ++++++++++++++++ 4 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 spec/sql_queries/multiline_erb.sql.erb diff --git a/lib/sql_query.rb b/lib/sql_query.rb index 23b7b04..19082dc 100644 --- a/lib/sql_query.rb +++ b/lib/sql_query.rb @@ -78,8 +78,16 @@ def initialize def prepare_query(for_logs) query_template = File.read(file_path) - query_template = query_template.gsub(/(\n|\s)+/, ' ') if for_logs - ERB.new(query_template).result(binding) + rendered_sql = ERB.new(query_template).result(binding) + + return rendered_sql unless for_logs + + # Normalize whitespace while preserving SQL quoted strings + # Matches: 'single-quoted' OR "double-quoted" OR (whitespace) + # Only captures whitespace when NOT inside quotes + rendered_sql.gsub(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|(\s+)/) do |match| + $1 ? ' ' : match # Replace whitespace with space, preserve quoted strings + end end def split_to_path_and_name(file) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 67a4845..0349788 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -33,23 +33,13 @@ def BigDecimal.new(...) mocks.verify_partial_doubles = true end - connection_config = if ENV['CI'] - { - adapter: 'postgresql', - host: 'localhost', - username: 'postgres', - password: 'postgres', - database: 'sqlquery_test' - } - else - { - adapter: 'postgresql', - host: 'localhost', - username: 'sqlquery', - password: 'sqlquery', - database: 'sqlquery' - } - end + connection_config = { + adapter: 'postgresql', + host: 'localhost', + username: 'postgres', + password: 'postgres', + database: 'sqlquery_test' + } ActiveRecord::Base.establish_connection(connection_config) diff --git a/spec/sql_queries/multiline_erb.sql.erb b/spec/sql_queries/multiline_erb.sql.erb new file mode 100644 index 0000000..8ba41f7 --- /dev/null +++ b/spec/sql_queries/multiline_erb.sql.erb @@ -0,0 +1,9 @@ +<% + field1 = @field1 || 'default1' + field2 = @field2 || 'default2' +%> +SELECT + <%= quote field1 %> as field1, + <%= quote field2 %> as field2 +FROM players +WHERE email = <%= quote @email %> diff --git a/spec/sql_query_spec.rb b/spec/sql_query_spec.rb index 390153b..11cbb70 100644 --- a/spec/sql_query_spec.rb +++ b/spec/sql_query_spec.rb @@ -211,6 +211,22 @@ class Model < ActiveRecord::Base .to eq("SELECT * FROM players WHERE email = ' e@mail.dev ' ") end end + + context 'when template has multiline ERB blocks' do + let(:file_name) { :multiline_erb } + let(:options) { { email: 'test@dev.com', field1: 'val1', field2: 'val2' } } + let(:query) { described_class.new(file_name, options) } + + it 'processes multiline ERB correctly without syntax errors' do + expect { query.prepared_for_logs }.not_to raise_error + end + + it 'includes rendered values in prepared_for_logs output' do + result = query.prepared_for_logs + expect(result).to include("'val1' as field1") + expect(result).to include("'val2' as field2") + end + end end describe '.config' do From 36cd2d7905f2bb672afdbaf41d1930c37f0475ba Mon Sep 17 00:00:00 2001 From: sufleR Date: Fri, 19 Dec 2025 15:07:38 +0100 Subject: [PATCH 2/2] Fix RuboCop style violations in prepare_query method - Replace Perl-style backreference $1 with ::Regexp.last_match(1) - Remove extra spacing before inline comment --- lib/sql_query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sql_query.rb b/lib/sql_query.rb index 19082dc..3795851 100644 --- a/lib/sql_query.rb +++ b/lib/sql_query.rb @@ -86,7 +86,7 @@ def prepare_query(for_logs) # Matches: 'single-quoted' OR "double-quoted" OR (whitespace) # Only captures whitespace when NOT inside quotes rendered_sql.gsub(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|(\s+)/) do |match| - $1 ? ' ' : match # Replace whitespace with space, preserve quoted strings + ::Regexp.last_match(1) ? ' ' : match # Replace whitespace with space, preserve quoted strings end end