• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2019 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "src/trace_processor/sqlite/db_sqlite_table.h"
19 
20 #include "test/gtest_and_gmock.h"
21 
22 namespace perfetto {
23 namespace trace_processor {
24 namespace {
25 
CreateSchema()26 Table::Schema CreateSchema() {
27   Table::Schema schema;
28   schema.columns.push_back({"id", SqlValue::Type::kLong, true /* is_id */,
29                             true /* is_sorted */, false /* is_hidden */,
30                             false /* is_set_id */});
31   schema.columns.push_back({"type", SqlValue::Type::kLong, false /* is_id */,
32                             false /* is_sorted */, false /* is_hidden */,
33                             false /* is_set_id */});
34   schema.columns.push_back({"test1", SqlValue::Type::kLong, false /* is_id */,
35                             true /* is_sorted */, false /* is_hidden */,
36                             false /* is_set_id */});
37   schema.columns.push_back({"test2", SqlValue::Type::kLong, false /* is_id */,
38                             false /* is_sorted */, false /* is_hidden */,
39                             false /* is_set_id */});
40   schema.columns.push_back({"test3", SqlValue::Type::kLong, false /* is_id */,
41                             false /* is_sorted */, false /* is_hidden */,
42                             false /* is_set_id */});
43   return schema;
44 }
45 
TEST(DbSqliteTable,IdEqCheaperThanOtherEq)46 TEST(DbSqliteTable, IdEqCheaperThanOtherEq) {
47   auto schema = CreateSchema();
48   constexpr uint32_t kRowCount = 1234;
49 
50   QueryConstraints id_eq;
51   id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
52 
53   auto id_cost = DbSqliteTable::EstimateCost(schema, kRowCount, id_eq);
54 
55   QueryConstraints a_eq;
56   a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
57 
58   auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_eq);
59 
60   ASSERT_LT(id_cost.cost, a_cost.cost);
61   ASSERT_LT(id_cost.rows, a_cost.rows);
62 }
63 
TEST(DbSqliteTable,IdEqCheaperThatOtherConstraint)64 TEST(DbSqliteTable, IdEqCheaperThatOtherConstraint) {
65   auto schema = CreateSchema();
66   constexpr uint32_t kRowCount = 1234;
67 
68   QueryConstraints id_eq;
69   id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
70 
71   auto id_cost = DbSqliteTable::EstimateCost(schema, kRowCount, id_eq);
72 
73   QueryConstraints a_eq;
74   a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
75 
76   auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_eq);
77 
78   ASSERT_LT(id_cost.cost, a_cost.cost);
79   ASSERT_LT(id_cost.rows, a_cost.rows);
80 }
81 
TEST(DbSqliteTable,SingleEqCheaperThanMultipleConstraint)82 TEST(DbSqliteTable, SingleEqCheaperThanMultipleConstraint) {
83   auto schema = CreateSchema();
84   constexpr uint32_t kRowCount = 1234;
85 
86   QueryConstraints single_eq;
87   single_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
88 
89   auto single_cost = DbSqliteTable::EstimateCost(schema, kRowCount, single_eq);
90 
91   QueryConstraints multi_eq;
92   multi_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
93   multi_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
94 
95   auto multi_cost = DbSqliteTable::EstimateCost(schema, kRowCount, multi_eq);
96 
97   // The cost of the single filter should be cheaper (because of our special
98   // handling of single equality). But the number of rows should be greater.
99   ASSERT_LT(single_cost.cost, multi_cost.cost);
100   ASSERT_GT(single_cost.rows, multi_cost.rows);
101 }
102 
TEST(DbSqliteTable,MultiSortedEqCheaperThanMultiUnsortedEq)103 TEST(DbSqliteTable, MultiSortedEqCheaperThanMultiUnsortedEq) {
104   auto schema = CreateSchema();
105   constexpr uint32_t kRowCount = 1234;
106 
107   QueryConstraints sorted_eq;
108   sorted_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
109   sorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
110 
111   auto sorted_cost = DbSqliteTable::EstimateCost(schema, kRowCount, sorted_eq);
112 
113   QueryConstraints unsorted_eq;
114   unsorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
115   unsorted_eq.AddConstraint(4u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
116 
117   auto unsorted_cost =
118       DbSqliteTable::EstimateCost(schema, kRowCount, unsorted_eq);
119 
120   // The number of rows should be the same but the cost of the sorted
121   // query should be less.
122   ASSERT_LT(sorted_cost.cost, unsorted_cost.cost);
123   ASSERT_EQ(sorted_cost.rows, unsorted_cost.rows);
124 }
125 
TEST(DbSqliteTable,EmptyTableCosting)126 TEST(DbSqliteTable, EmptyTableCosting) {
127   auto schema = CreateSchema();
128 
129   QueryConstraints id_eq;
130   id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
131 
132   auto id_cost = DbSqliteTable::EstimateCost(schema, 0, id_eq);
133 
134   QueryConstraints a_eq;
135   a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
136 
137   auto a_cost = DbSqliteTable::EstimateCost(schema, 0, a_eq);
138 
139   ASSERT_DOUBLE_EQ(id_cost.cost, a_cost.cost);
140   ASSERT_EQ(id_cost.rows, a_cost.rows);
141 }
142 
TEST(DbSqliteTable,OrderByOnSortedCheaper)143 TEST(DbSqliteTable, OrderByOnSortedCheaper) {
144   auto schema = CreateSchema();
145   constexpr uint32_t kRowCount = 1234;
146 
147   QueryConstraints a_qc;
148   a_qc.AddOrderBy(1u, false);
149 
150   auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_qc);
151 
152   // On an ordered column, the constraint for sorting would get pruned so
153   // we would end up with an empty constraint set.
154   QueryConstraints sorted_qc;
155   auto sorted_cost = DbSqliteTable::EstimateCost(schema, kRowCount, sorted_qc);
156 
157   ASSERT_LT(sorted_cost.cost, a_cost.cost);
158   ASSERT_EQ(sorted_cost.rows, a_cost.rows);
159 }
160 
161 }  // namespace
162 }  // namespace trace_processor
163 }  // namespace perfetto
164