|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require "cases/helper_cockroachdb" |
| 4 | +require "models/post" |
| 5 | + |
| 6 | +module CockroachDB |
| 7 | + class TableHintsTest < ActiveRecord::TestCase |
| 8 | + fixtures :posts |
| 9 | + |
| 10 | + def test_add_hint |
| 11 | + force_index = ->(q) { q.force_index("index_posts_on_author_id") } |
| 12 | + index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") } |
| 13 | + |
| 14 | + assert_sql(/"posts"@\{FORCE_INDEX=index_posts_on_author_id\}/) do |
| 15 | + Post.then(&force_index).take |
| 16 | + end |
| 17 | + |
| 18 | + assert_sql(/"posts"@\{NO_FULL_SCAN\}/) do |
| 19 | + Post.then(&index_hint).take |
| 20 | + end |
| 21 | + |
| 22 | + [force_index, index_hint].permutation do |procs| |
| 23 | + assert_sql(/"posts"@\{NO_FULL_SCAN,FORCE_INDEX=index_posts_on_author_id\}/) do |
| 24 | + Post.then(&procs.reduce(:<<)).take |
| 25 | + end |
| 26 | + end |
| 27 | + end |
| 28 | + |
| 29 | + def test_choose_index_order |
| 30 | + idx = "index_posts_on_author_id" |
| 31 | + assert_sql(/"posts"@\{FORCE_INDEX=#{idx},ASC\}/) do |
| 32 | + Post.force_index(idx, direction: "ASC").take |
| 33 | + end |
| 34 | + assert_sql(/"posts"@\{FORCE_INDEX=#{idx},DESC\}/) do |
| 35 | + Post.force_index(idx, direction: "DESC").take |
| 36 | + end |
| 37 | + assert_sql(/"posts"@\{NO_FULL_SCAN,FORCE_INDEX=#{idx},DESC\}/) do |
| 38 | + Post.force_index(idx, direction: "DESC").index_hint("NO_FULL_SCAN").take |
| 39 | + end |
| 40 | + end |
| 41 | + |
| 42 | + def test_use_other_table |
| 43 | + force_index = ->(q) { q.force_index("index_subscribers_on_nick") } |
| 44 | + index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") } |
| 45 | + post_from = Post.select(:id).from("subscribers") |
| 46 | + |
| 47 | + assert_sql(/subscribers@\{FORCE_INDEX=index_subscribers_on_nick\}/) do |
| 48 | + post_from.then(&force_index).take |
| 49 | + end |
| 50 | + |
| 51 | + assert_sql(/subscribers@\{NO_FULL_SCAN\}/) do |
| 52 | + post_from.then(&index_hint).take |
| 53 | + end |
| 54 | + |
| 55 | + [force_index, index_hint].permutation do |procs| |
| 56 | + assert_sql(/subscribers@\{NO_FULL_SCAN,FORCE_INDEX=index_subscribers_on_nick\}/) do |
| 57 | + post_from.then(&procs.reduce(:<<)).take |
| 58 | + end |
| 59 | + end |
| 60 | + end |
| 61 | + |
| 62 | + def test_from_with_space |
| 63 | + ["foo\t", "foo "].each do |
| 64 | + assert_match(/FROM foo@\{H\}/, Post.from(_1).index_hint("H").to_sql) |
| 65 | + assert_match( |
| 66 | + /FROM foo@\{H,FORCE_INDEX=i\}/, |
| 67 | + Post.from(_1).index_hint("H").force_index("i").to_sql |
| 68 | + ) |
| 69 | + end |
| 70 | + end |
| 71 | + |
| 72 | + def test_reset_with_from |
| 73 | + force_index = ->(q) { q.force_index("type") } |
| 74 | + index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") } |
| 75 | + |
| 76 | + [force_index, index_hint].permutation do |
| 77 | + assert_match( |
| 78 | + /FROM age\z/, |
| 79 | + Post.then(&_1).then(&_2).from("age").to_sql |
| 80 | + ) |
| 81 | + end |
| 82 | + [force_index, index_hint].each do |
| 83 | + assert_match(/FROM age\z/, Post.then(&_1).from("age").to_sql) |
| 84 | + end |
| 85 | + |
| 86 | + end |
| 87 | + |
| 88 | + def test_ignore_from_multiple_tables |
| 89 | + tables = "ta, tb" |
| 90 | + from = ->(q) { q.from(tables) } |
| 91 | + force_index = ->(q) { q.force_index("type") } |
| 92 | + index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") } |
| 93 | + |
| 94 | + ( |
| 95 | + [from, force_index, index_hint].permutation + |
| 96 | + [from, force_index].permutation + |
| 97 | + [from, index_hint].permutation |
| 98 | + ).each do |procs| |
| 99 | + assert_match( |
| 100 | + /FROM #{tables}\z/, |
| 101 | + Post.then(&procs.reduce(:<<)).to_sql |
| 102 | + ) |
| 103 | + end |
| 104 | + end |
| 105 | + |
| 106 | + def test_ignore_from_subquery |
| 107 | + subquery = Post.where("created_at < ?", 1.year.ago) |
| 108 | + from = ->(q) { q.from(subquery) } |
| 109 | + force_index = ->(q) { q.force_index("safeword") } |
| 110 | + index_hint = ->(q) { q.index_hint("NO_FULL_SCAN") } |
| 111 | + |
| 112 | + ( |
| 113 | + [from, force_index, index_hint].permutation + |
| 114 | + [from, force_index].permutation + |
| 115 | + [from, index_hint].permutation |
| 116 | + ).each do |procs| |
| 117 | + refute_match( |
| 118 | + /safeword|NO_FULL_SCAN|@/, |
| 119 | + Post.then(&procs.reduce(:<<)).to_sql |
| 120 | + ) |
| 121 | + end |
| 122 | + end |
| 123 | + end |
| 124 | +end |
0 commit comments