blob: 891ba35b4a0cbccf10a5d7abd1d7d8261b256aa6 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace {
Table::Schema CreateSchema() {
Table::Schema schema;
schema.columns.push_back({"id", SqlValue::Type::kLong, true /* is_id */,
true /* is_sorted */, false /* is_hidden */,
false /* is_set_id */});
schema.columns.push_back({"type", SqlValue::Type::kLong, false /* is_id */,
false /* is_sorted */, false /* is_hidden */,
false /* is_set_id */});
schema.columns.push_back({"test1", SqlValue::Type::kLong, false /* is_id */,
true /* is_sorted */, false /* is_hidden */,
false /* is_set_id */});
schema.columns.push_back({"test2", SqlValue::Type::kLong, false /* is_id */,
false /* is_sorted */, false /* is_hidden */,
false /* is_set_id */});
schema.columns.push_back({"test3", SqlValue::Type::kLong, false /* is_id */,
false /* is_sorted */, false /* is_hidden */,
false /* is_set_id */});
return schema;
}
TEST(DbSqliteTable, IdEqCheaperThanOtherEq) {
auto schema = CreateSchema();
constexpr uint32_t kRowCount = 1234;
QueryConstraints id_eq;
id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto id_cost = DbSqliteTable::EstimateCost(schema, kRowCount, id_eq);
QueryConstraints a_eq;
a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_eq);
ASSERT_LT(id_cost.cost, a_cost.cost);
ASSERT_LT(id_cost.rows, a_cost.rows);
}
TEST(DbSqliteTable, IdEqCheaperThatOtherConstraint) {
auto schema = CreateSchema();
constexpr uint32_t kRowCount = 1234;
QueryConstraints id_eq;
id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto id_cost = DbSqliteTable::EstimateCost(schema, kRowCount, id_eq);
QueryConstraints a_eq;
a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_eq);
ASSERT_LT(id_cost.cost, a_cost.cost);
ASSERT_LT(id_cost.rows, a_cost.rows);
}
TEST(DbSqliteTable, SingleEqCheaperThanMultipleConstraint) {
auto schema = CreateSchema();
constexpr uint32_t kRowCount = 1234;
QueryConstraints single_eq;
single_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto single_cost = DbSqliteTable::EstimateCost(schema, kRowCount, single_eq);
QueryConstraints multi_eq;
multi_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
multi_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 1u);
auto multi_cost = DbSqliteTable::EstimateCost(schema, kRowCount, multi_eq);
// The cost of the single filter should be cheaper (because of our special
// handling of single equality). But the number of rows should be greater.
ASSERT_LT(single_cost.cost, multi_cost.cost);
ASSERT_GT(single_cost.rows, multi_cost.rows);
}
TEST(DbSqliteTable, MultiSortedEqCheaperThanMultiUnsortedEq) {
auto schema = CreateSchema();
constexpr uint32_t kRowCount = 1234;
QueryConstraints sorted_eq;
sorted_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
sorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto sorted_cost = DbSqliteTable::EstimateCost(schema, kRowCount, sorted_eq);
QueryConstraints unsorted_eq;
unsorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
unsorted_eq.AddConstraint(4u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto unsorted_cost =
DbSqliteTable::EstimateCost(schema, kRowCount, unsorted_eq);
// The number of rows should be the same but the cost of the sorted
// query should be less.
ASSERT_LT(sorted_cost.cost, unsorted_cost.cost);
ASSERT_EQ(sorted_cost.rows, unsorted_cost.rows);
}
TEST(DbSqliteTable, EmptyTableCosting) {
auto schema = CreateSchema();
QueryConstraints id_eq;
id_eq.AddConstraint(0u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
auto id_cost = DbSqliteTable::EstimateCost(schema, 0, id_eq);
QueryConstraints a_eq;
a_eq.AddConstraint(1u, SQLITE_INDEX_CONSTRAINT_LT, 1u);
auto a_cost = DbSqliteTable::EstimateCost(schema, 0, a_eq);
ASSERT_DOUBLE_EQ(id_cost.cost, a_cost.cost);
ASSERT_EQ(id_cost.rows, a_cost.rows);
}
TEST(DbSqliteTable, OrderByOnSortedCheaper) {
auto schema = CreateSchema();
constexpr uint32_t kRowCount = 1234;
QueryConstraints a_qc;
a_qc.AddOrderBy(1u, false);
auto a_cost = DbSqliteTable::EstimateCost(schema, kRowCount, a_qc);
// On an ordered column, the constraint for sorting would get pruned so
// we would end up with an empty constraint set.
QueryConstraints sorted_qc;
auto sorted_cost = DbSqliteTable::EstimateCost(schema, kRowCount, sorted_qc);
ASSERT_LT(sorted_cost.cost, a_cost.cost);
ASSERT_EQ(sorted_cost.rows, a_cost.rows);
}
} // namespace
} // namespace trace_processor
} // namespace perfetto