File: sql_log_normalizer_spec.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (86 lines) | stat: -rw-r--r-- 3,506 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
require_relative "spec_helper"

describe "sql_log_normalizer extension" do
  def db(opts={})
    return @db if @db
    @sql = String.new
    def @sql.info(sql)
      replace(sql.sub(/\A\(.*?\) /, ''))
    end
    if opts[:logger] == false
      loggers = []
    else
      loggers = @sql
    end
    @db = Sequel.mock(:loggers=>loggers)
    case opts[:type]
    when :backslash
      @db.extend_datasets do
        private
        def literal_string_append(sql, v)
          sql << "'" << v.gsub(/(\\|')/){"\\#{$1}"} << "'"
        end
      end
    when :n_standard
      @db.extend_datasets do
        private
        def literal_string_append(sql, v)
          sql << "N'" << v.gsub("'", "''") << "'"
        end
      end
    when :bad
      @db.extend_datasets do
        private
        def literal_string_append(sql, v)
          sql << "X'" << v.gsub("'", "''") << "'"
        end
      end
    end
    @db.extension(:sql_log_normalizer)
    @db
  end

  it "should normalize literal strings and numbers for standard escaping" do
    db[:ts].first(:a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM ts WHERE ((a = 1) AND (b = 2.3) AND (c = 'd') AND (d = 'e\\f\\''g''')) LIMIT 1"
    @sql.must_equal "SELECT * FROM ts WHERE ((a = ?) AND (b = ?) AND (c = ?) AND (d = ?)) LIMIT ?"
  end

  it "should normalize literal strings and numbers for backslash escaping" do
    db(:type=>:backslash)[:ts].first(:a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM ts WHERE ((a = 1) AND (b = 2.3) AND (c = 'd') AND (d = 'e\\\\f\\\\\\'g\\'')) LIMIT 1"
    @sql.must_equal "SELECT * FROM ts WHERE ((a = ?) AND (b = ?) AND (c = ?) AND (d = ?)) LIMIT ?"
  end

  it "should normalize literal strings and numbers for N' escaping" do
    db(:type=>:n_standard)[:ts].first(:a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM ts WHERE ((a = 1) AND (b = 2.3) AND (c = N'd') AND (d = N'e\\f\\''g''')) LIMIT 1"
    @sql.must_equal "SELECT * FROM ts WHERE ((a = ?) AND (b = ?) AND (c = ?) AND (d = ?)) LIMIT ?"
  end

  it "should normalize literal strings and numbers for N' escaping when using non N' string" do
    db(:type=>:n_standard)[:ts].first(:a=>1, :b=>2.3, :c=>Sequel.lit("'d'"), :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM ts WHERE ((a = 1) AND (b = 2.3) AND (c = 'd') AND (d = N'e\\f\\''g''')) LIMIT 1"
    @sql.must_equal "SELECT * FROM ts WHERE ((a = ?) AND (b = ?) AND (c = ?) AND (d = ?)) LIMIT ?"
  end

  it "should raise an error if you attempt to load it into a database that doesn't literalize strings in an expected way" do
    proc{db(:type=>:bad)}.must_raise Sequel::Error
  end

  it "should not affect cases where no logger is used" do
    db(:logger=>false)[:ts].first(:a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM ts WHERE ((a = 1) AND (b = 2.3) AND (c = 'd') AND (d = 'e\\f\\''g''')) LIMIT 1"
  end

  it "should handle case where identifier contains apostrophe (will not remove all strings in this case)" do
    db[:"'ts"].first(:a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'")
    db.sqls.last.must_equal "SELECT * FROM 'ts WHERE ((a = 1) AND (b = 2.3) AND (c = 'd') AND (d = 'e\\f\\''g''')) LIMIT 1"
    @sql.must_equal "SELECT * FROM ?d?e\\f\\?g''')) LIMIT ?"
  end

  it "should not include bound variables when logging" do
    db.log_connection_yield("X", nil, :a=>1, :b=>2.3, :c=>'d', :d=>"e\\f\\'g'"){}
    @sql.must_equal "X"
  end
end