Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion query/ir/codegen/DBPassPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace {

using DBPassFactory = std::unique_ptr<mlir::Pass> (*)(const mlir::db::DBPassContext*);

constexpr size_t DB_PASS_COUNT = 52;
constexpr size_t DB_PASS_COUNT = 53;

// The optimisation pipeline every query runs through, in order. An EXPLAIN prefix
// reporting on a pass walks the same table one pass at a time, which is what keeps the
Expand Down Expand Up @@ -70,6 +70,7 @@ const std::array<DBPassFactory, DB_PASS_COUNT> dbPassPipeline = {
[](const mlir::db::DBPassContext* context) { return mlir::db::createCountFromMetadata(context); },
[](const mlir::db::DBPassContext*) { return mlir::db::createFuseUnwindRange(); },
[](const mlir::db::DBPassContext*) { return mlir::db::createSinkUnwindSource(); },
[](const mlir::db::DBPassContext* context) { return mlir::db::createStageFilterConjuncts(context); },
};

}
Expand Down
16 changes: 16 additions & 0 deletions query/ir/dialect/db/DBInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ def ColumnCarrierOpInterface : OpInterface<"ColumnCarrierOpInterface"> {
];
}

def RowCostOpInterface : OpInterface<"RowCostOpInterface"> {
let cppNamespace = "::mlir::db";

let description = [{
An op computing a row of its result at a cost other than a comparison of two scalar
columns, which is 1 on this scale and the cost of every op without the interface. A
random read of node or edge storage costs about 10.
}];

let methods = [
InterfaceMethod<
"The cost of computing one row of the op's result",
"double", "getRowCost", (ins)>
];
}

def EdgeTypesOutputOpInterface : OpInterface<"EdgeTypesOutputOpInterface"> {
let cppNamespace = "::mlir::db";

Expand Down
54 changes: 54 additions & 0 deletions query/ir/dialect/db/DBOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ namespace storage = mlir::storage;

namespace {

constexpr double STORAGE_READ_ROW_COST = 10.0;
constexpr double STRING_TEST_ROW_COST = 3.0;
constexpr double MEMBERSHIP_TEST_ROW_COST = 5.0;
constexpr double CONTAINER_BUILD_ROW_COST = 15.0;
constexpr double VECTOR_FUNCTION_ROW_COST = 40.0;

Type columnElement(Value column) {
return ::db::inferredColumnElement(column);
}
Expand Down Expand Up @@ -3401,3 +3407,51 @@ Speculation::Speculatability ModOp::getSpeculatability() {
Speculation::Speculatability PowOp::getSpeculatability() {
return speculatableOverNumbers(getOperation());
}

double GetNodeLabelSet::getRowCost() {
return STORAGE_READ_ROW_COST;
}

double GetEdgeTypes::getRowCost() {
return STORAGE_READ_ROW_COST;
}

double GetNodeProperties::getRowCost() {
return STORAGE_READ_ROW_COST;
}

double GetEdgeProperties::getRowCost() {
return STORAGE_READ_ROW_COST;
}

double StartsWithOp::getRowCost() {
return STRING_TEST_ROW_COST;
}

double EndsWithOp::getRowCost() {
return STRING_TEST_ROW_COST;
}

double ContainsOp::getRowCost() {
return STRING_TEST_ROW_COST;
}

double InOp::getRowCost() {
return MEMBERSHIP_TEST_ROW_COST;
}

double MakeList::getRowCost() {
return CONTAINER_BUILD_ROW_COST;
}

double MakeMap::getRowCost() {
return CONTAINER_BUILD_ROW_COST;
}

double CosineSimilarity::getRowCost() {
return VECTOR_FUNCTION_ROW_COST;
}

double EuclideanDistance::getRowCost() {
return VECTOR_FUNCTION_ROW_COST;
}
26 changes: 13 additions & 13 deletions query/ir/dialect/db/DBOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ def UnwindYield : TuringOp<"unwind_yield", [Pure, Terminator, HasParent<"UnwindC
/**
* MakeList
*/
def MakeList : TuringOp<"make_list", [Pure, ConstantThroughOperands]> {
def MakeList : TuringOp<"make_list", [Pure, ConstantThroughOperands, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Build one list per row out of the row's cell in each element column";

let description = [{
Expand Down Expand Up @@ -534,7 +534,7 @@ def MakeList : TuringOp<"make_list", [Pure, ConstantThroughOperands]> {
/**
* MakeMap
*/
def MakeMap : TuringOp<"make_map", [Pure, ConstantThroughOperands]> {
def MakeMap : TuringOp<"make_map", [Pure, ConstantThroughOperands, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Build one map per row out of the row's cell in each value column";

let description = [{
Expand Down Expand Up @@ -1975,7 +1975,7 @@ def PathElements : TuringOp<"path_elements", [NoMemoryEffect,
/**
* GetNodeProperties
*/
def GetNodeProperties : TuringOp<"get_node_properties", [Pure, ConstantThroughOperands]> {
def GetNodeProperties : TuringOp<"get_node_properties", [Pure, ConstantThroughOperands, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Read one named property of each node as a column of values";

let description = [{
Expand Down Expand Up @@ -2031,7 +2031,7 @@ def GetNodeProperties : TuringOp<"get_node_properties", [Pure, ConstantThroughOp
/**
* GetEdgeProperties
*/
def GetEdgeProperties : TuringOp<"get_edge_properties", [Pure, ConstantThroughOperands]> {
def GetEdgeProperties : TuringOp<"get_edge_properties", [Pure, ConstantThroughOperands, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Read one named property of each edge as a column of values";

let description = [{
Expand Down Expand Up @@ -2065,7 +2065,7 @@ def GetEdgeProperties : TuringOp<"get_edge_properties", [Pure, ConstantThroughOp
}];
}

def GetNodeLabelSet : TuringOp<"get_node_label_set", [Pure]> {
def GetNodeLabelSet : TuringOp<"get_node_label_set", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Read the label-set ID of each node as a column";

let description = [{
Expand All @@ -2083,7 +2083,7 @@ def GetNodeLabelSet : TuringOp<"get_node_label_set", [Pure]> {
}];
}

def GetEdgeTypes : TuringOp<"get_edge_types", [Pure]> {
def GetEdgeTypes : TuringOp<"get_edge_types", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Read the type ID of each edge as a column";

let description = [{
Expand Down Expand Up @@ -3269,7 +3269,7 @@ def PointWithinBBox : TuringOp<"point_within_bbox", [MayRaise, ConstantThroughOp
}];
}

class BinaryFunctionOp<string mnemonic> : TuringOp<mnemonic, [Pure, ConstantThroughOperands]> {
class BinaryFunctionOp<string mnemonic, list<Trait> traits = []> : TuringOp<mnemonic, !listconcat([Pure, ConstantThroughOperands], traits)> {
let summary = "Apply a binary function row-wise to two value columns";

let arguments = (ins Column:$lhs, Column:$rhs);
Expand All @@ -3280,8 +3280,8 @@ class BinaryFunctionOp<string mnemonic> : TuringOp<mnemonic, [Pure, ConstantThro
}];
}

def CosineSimilarity : BinaryFunctionOp<"cosine_similarity">;
def EuclideanDistance : BinaryFunctionOp<"euclidean_distance">;
def CosineSimilarity : BinaryFunctionOp<"cosine_similarity", [DeclareOpInterfaceMethods<RowCostOpInterface>]>;
def EuclideanDistance : BinaryFunctionOp<"euclidean_distance", [DeclareOpInterfaceMethods<RowCostOpInterface>]>;

def ConstantOp : TuringOp<"constant", [Pure, ConstantLike, DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
let summary = "Produces a constant value in a column";
Expand Down Expand Up @@ -3630,19 +3630,19 @@ def LteOp : PredicateOp<"lte", [Pure]> {
let summary = "Row-wise less-than-or-equal comparison of two value columns";
}

def StartsWithOp : PredicateOp<"starts_with", [Pure]> {
def StartsWithOp : PredicateOp<"starts_with", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Row-wise test of whether each string column value starts with the given prefix";
}

def EndsWithOp : PredicateOp<"ends_with", [Pure]> {
def EndsWithOp : PredicateOp<"ends_with", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Row-wise test of whether each string column value ends with the given suffix";
}

def ContainsOp : PredicateOp<"contains", [Pure]> {
def ContainsOp : PredicateOp<"contains", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Row-wise test of whether each string column value contains the given substring";
}

def InOp : PredicateOp<"in", [Pure]> {
def InOp : PredicateOp<"in", [Pure, DeclareOpInterfaceMethods<RowCostOpInterface>]> {
let summary = "Row-wise test of whether each value is an element of the given list";

let description = [{
Expand Down
Loading
Loading