Skip to content

Commit

Permalink
Merge pull request #1877 from kuzudb/catalog-rework
Browse files Browse the repository at this point in the history
Catalog rework
  • Loading branch information
acquamarin committed Aug 1, 2023
2 parents df7a367 + a1db82b commit 416d392
Show file tree
Hide file tree
Showing 76 changed files with 961 additions and 754 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.11)

project(Kuzu VERSION 0.0.6.2 LANGUAGES CXX)
project(Kuzu VERSION 0.0.6.3 LANGUAGES CXX)

find_package(Threads REQUIRED)

Expand Down
37 changes: 18 additions & 19 deletions src/binder/bind/bind_ddl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ std::unique_ptr<BoundStatement> Binder::bindCreateNodeTableClause(
auto primaryKeyIdx = bindPrimaryKey(
createNodeTableClause.getPKColName(), createNodeTableClause.getPropertyNameDataTypes());
for (auto i = 0u; i < boundProperties.size(); ++i) {
if (boundProperties[i].dataType.getLogicalTypeID() == LogicalTypeID::SERIAL &&
if (boundProperties[i]->getDataType()->getLogicalTypeID() == LogicalTypeID::SERIAL &&
primaryKeyIdx != i) {
throw BinderException("Serial property in node table must be the primary key.");
}
Expand All @@ -50,7 +50,7 @@ std::unique_ptr<BoundStatement> Binder::bindCreateRelTableClause(
}
auto boundProperties = bindProperties(createRelClause.getPropertyNameDataTypes());
for (auto& boundProperty : boundProperties) {
if (boundProperty.dataType.getLogicalTypeID() == LogicalTypeID::SERIAL) {
if (boundProperty->getDataType()->getLogicalTypeID() == LogicalTypeID::SERIAL) {
throw BinderException("Serial property is not supported in rel table.");
}
}
Expand Down Expand Up @@ -94,27 +94,25 @@ std::unique_ptr<BoundStatement> Binder::bindAddPropertyClause(const parser::Stat
if (catalogContent->getTableSchema(tableID)->containProperty(addProperty.getPropertyName())) {
throw BinderException("Property: " + addProperty.getPropertyName() + " already exists.");
}
if (dataType.getLogicalTypeID() == LogicalTypeID::SERIAL) {
if (dataType->getLogicalTypeID() == LogicalTypeID::SERIAL) {
throw BinderException("Serial property in node table must be the primary key.");
}
auto defaultVal = ExpressionBinder::implicitCastIfNecessary(
expressionBinder.bindExpression(*addProperty.getDefaultValue()), dataType);
expressionBinder.bindExpression(*addProperty.getDefaultValue()), *dataType);
return make_unique<BoundAddProperty>(
tableID, addProperty.getPropertyName(), dataType, defaultVal, tableName);
tableID, addProperty.getPropertyName(), std::move(dataType), defaultVal, tableName);
}

std::unique_ptr<BoundStatement> Binder::bindDropPropertyClause(const parser::Statement& statement) {
auto& dropProperty = (DropProperty&)statement;
auto tableName = dropProperty.getTableName();
validateTableExist(catalog, tableName);
auto catalogContent = catalog.getReadOnlyVersion();
auto isNodeTable = catalogContent->containNodeTable(tableName);
auto tableID = catalogContent->getTableID(tableName);
auto propertyID =
bindPropertyName(catalogContent->getTableSchema(tableID), dropProperty.getPropertyName());
if (isNodeTable &&
((NodeTableSchema*)catalogContent->getTableSchema(tableID))->primaryKeyPropertyID ==
propertyID) {
auto tableSchema = catalogContent->getTableSchema(tableID);
auto propertyID = bindPropertyName(tableSchema, dropProperty.getPropertyName());
if (tableSchema->getTableType() == catalog::TableType::NODE &&
reinterpret_cast<NodeTableSchema*>(tableSchema)->getPrimaryKeyPropertyID() == propertyID) {
throw BinderException("Cannot drop primary key of a node table.");
}
return make_unique<BoundDropProperty>(tableID, propertyID, tableName);
Expand All @@ -137,10 +135,11 @@ std::unique_ptr<BoundStatement> Binder::bindRenamePropertyClause(
tableID, tableName, propertyID, renameProperty.getNewName());
}

std::vector<Property> Binder::bindProperties(
std::vector<std::unique_ptr<Property>> Binder::bindProperties(
std::vector<std::pair<std::string, std::string>> propertyNameDataTypes) {
std::vector<Property> boundPropertyNameDataTypes;
std::vector<std::unique_ptr<Property>> boundPropertyNameDataTypes;
std::unordered_set<std::string> boundPropertyNames;
boundPropertyNameDataTypes.reserve(propertyNameDataTypes.size());
for (auto& propertyNameDataType : propertyNameDataTypes) {
if (boundPropertyNames.contains(propertyNameDataType.first)) {
throw BinderException(StringUtils::string_format(
Expand All @@ -151,8 +150,8 @@ std::vector<Property> Binder::bindProperties(
StringUtils::string_format("PropertyName: {} is an internal reserved propertyName.",
propertyNameDataType.first));
}
auto dataType = bindDataType(propertyNameDataType.second);
boundPropertyNameDataTypes.emplace_back(propertyNameDataType.first, dataType);
boundPropertyNameDataTypes.push_back(std::make_unique<Property>(
propertyNameDataType.first, bindDataType(propertyNameDataType.second)));
boundPropertyNames.emplace(propertyNameDataType.first);
}
return boundPropertyNameDataTypes;
Expand Down Expand Up @@ -187,15 +186,15 @@ uint32_t Binder::bindPrimaryKey(const std::string& pkColName,

property_id_t Binder::bindPropertyName(TableSchema* tableSchema, const std::string& propertyName) {
for (auto& property : tableSchema->properties) {
if (property.name == propertyName) {
return property.propertyID;
if (property->getName() == propertyName) {
return property->getPropertyID();
}
}
throw BinderException(
tableSchema->tableName + " table doesn't have property: " + propertyName + ".");
}

LogicalType Binder::bindDataType(const std::string& dataType) {
std::unique_ptr<common::LogicalType> Binder::bindDataType(const std::string& dataType) {
auto boundType = LogicalTypeUtils::dataTypeFromString(dataType);
if (boundType.getLogicalTypeID() == common::LogicalTypeID::FIXED_LIST) {
auto validNumericTypes = common::LogicalTypeUtils::getNumericalLogicalTypeIDs();
Expand All @@ -222,7 +221,7 @@ LogicalType Binder::bindDataType(const std::string& dataType) {
storage::StorageUtils::getDataTypeSize(boundType)));
}
}
return boundType;
return std::make_unique<common::LogicalType>(boundType);
}

} // namespace binder
Expand Down
48 changes: 25 additions & 23 deletions src/binder/bind/bind_graph_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,53 +123,55 @@ static std::vector<table_id_t> pruneRelTableIDs(const Catalog& catalog_,
std::vector<table_id_t> result;
for (auto& relTableID : relTableIDs) {
auto relTableSchema = catalog_.getReadOnlyVersion()->getRelTableSchema(relTableID);
if (!srcNodeTableIDs.contains(relTableSchema->srcTableID) ||
!dstNodeTableIDs.contains(relTableSchema->dstTableID)) {
if (!srcNodeTableIDs.contains(relTableSchema->getSrcTableID()) ||
!dstNodeTableIDs.contains(relTableSchema->getDstTableID())) {
continue;
}
result.push_back(relTableID);
}
return result;
}

static std::vector<std::pair<std::string, std::vector<Property>>> getPropertyNameAndSchemasPairs(
static std::vector<std::pair<std::string, std::vector<Property*>>> getPropertyNameAndSchemasPairs(
const std::vector<std::string>& propertyNames,
std::unordered_map<std::string, std::vector<Property>> propertyNamesToSchemas) {
std::vector<std::pair<std::string, std::vector<Property>>> propertyNameAndSchemasPairs;
std::unordered_map<std::string, std::vector<Property*>> propertyNamesToSchemas) {
std::vector<std::pair<std::string, std::vector<Property*>>> propertyNameAndSchemasPairs;
for (auto& propertyName : propertyNames) {
auto propertySchemas = propertyNamesToSchemas.at(propertyName);
propertyNameAndSchemasPairs.emplace_back(propertyName, std::move(propertySchemas));
}
return propertyNameAndSchemasPairs;
}

static std::vector<std::pair<std::string, std::vector<Property>>>
static std::vector<std::pair<std::string, std::vector<Property*>>>
getRelPropertyNameAndPropertiesPairs(const std::vector<RelTableSchema*>& relTableSchemas) {
std::vector<std::string> propertyNames; // preserve order as specified in catalog.
std::unordered_map<std::string, std::vector<Property>> propertyNamesToSchemas;
std::unordered_map<std::string, std::vector<Property*>> propertyNamesToSchemas;
for (auto& relTableSchema : relTableSchemas) {
for (auto& property : relTableSchema->properties) {
if (!propertyNamesToSchemas.contains(property.name)) {
propertyNames.push_back(property.name);
propertyNamesToSchemas.insert({property.name, std::vector<Property>{}});
auto propertyName = property->getName();
if (!propertyNamesToSchemas.contains(propertyName)) {
propertyNames.push_back(propertyName);
propertyNamesToSchemas.emplace(propertyName, std::vector<Property*>{});
}
propertyNamesToSchemas.at(property.name).push_back(property);
propertyNamesToSchemas.at(propertyName).push_back(property.get());
}
}
return getPropertyNameAndSchemasPairs(propertyNames, propertyNamesToSchemas);
}

static std::vector<std::pair<std::string, std::vector<Property>>>
static std::vector<std::pair<std::string, std::vector<Property*>>>
getNodePropertyNameAndPropertiesPairs(const std::vector<NodeTableSchema*>& nodeTableSchemas) {
std::vector<std::string> propertyNames; // preserve order as specified in catalog.
std::unordered_map<std::string, std::vector<Property>> propertyNamesToSchemas;
std::unordered_map<std::string, std::vector<Property*>> propertyNamesToSchemas;
for (auto& nodeTableSchema : nodeTableSchemas) {
for (auto& property : nodeTableSchema->properties) {
if (!propertyNamesToSchemas.contains(property.name)) {
propertyNames.push_back(property.name);
propertyNamesToSchemas.insert({property.name, std::vector<Property>{}});
auto propertyName = property->getName();
if (!propertyNamesToSchemas.contains(propertyName)) {
propertyNames.push_back(propertyName);
propertyNamesToSchemas.emplace(propertyName, std::vector<Property*>{});
}
propertyNamesToSchemas.at(property.name).push_back(property);
propertyNamesToSchemas.at(propertyName).push_back(property.get());
}
}
return getPropertyNameAndSchemasPairs(propertyNames, propertyNamesToSchemas);
Expand Down Expand Up @@ -278,8 +280,8 @@ std::shared_ptr<RelExpression> Binder::createRecursiveQueryRel(const parser::Rel
std::unordered_set<common::table_id_t> recursiveNodeTableIDs;
for (auto relTableID : tableIDs) {
auto relTableSchema = catalog.getReadOnlyVersion()->getRelTableSchema(relTableID);
recursiveNodeTableIDs.insert(relTableSchema->srcTableID);
recursiveNodeTableIDs.insert(relTableSchema->dstTableID);
recursiveNodeTableIDs.insert(relTableSchema->getSrcTableID());
recursiveNodeTableIDs.insert(relTableSchema->getDstTableID());
}
auto recursiveRelPatternInfo = relPattern.getRecursiveInfo();
auto tmpNode = createQueryNode(
Expand Down Expand Up @@ -423,8 +425,8 @@ void Binder::bindQueryNodeProperties(NodeExpression& node) {
getNodePropertyNameAndPropertiesPairs(tableSchemas)) {
bool isPrimaryKey = false;
if (!node.isMultiLabeled()) {
isPrimaryKey =
tableSchemas[0]->getPrimaryKey().propertyID == propertySchemas[0].propertyID;
isPrimaryKey = tableSchemas[0]->getPrimaryKey()->getPropertyID() ==
propertySchemas[0]->getPropertyID();
}
auto propertyExpression =
expressionBinder.createPropertyExpression(node, propertySchemas, isPrimaryKey);
Expand All @@ -434,7 +436,7 @@ void Binder::bindQueryNodeProperties(NodeExpression& node) {

std::vector<common::table_id_t> Binder::bindNodeTableIDs(
const std::vector<std::string>& tableNames) {
if (!catalog.getReadOnlyVersion()->hasNodeTable()) {
if (catalog.getReadOnlyVersion()->getNodeTableIDs().empty()) {
throw common::BinderException("No node table exists in database.");
}
std::unordered_set<table_id_t> tableIDs;
Expand All @@ -454,7 +456,7 @@ std::vector<common::table_id_t> Binder::bindNodeTableIDs(

std::vector<common::table_id_t> Binder::bindRelTableIDs(
const std::vector<std::string>& tableNames) {
if (!catalog.getReadOnlyVersion()->hasRelTable()) {
if (catalog.getReadOnlyVersion()->getRelTableIDs().empty()) {
throw common::BinderException("No rel table exists in database.");
}
std::unordered_set<table_id_t> tableIDs;
Expand Down
35 changes: 18 additions & 17 deletions src/binder/bind/bind_updating_clause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,12 @@ std::unique_ptr<BoundCreateInfo> Binder::bindCreateNodeInfo(
auto primaryKey = nodeTableSchema->getPrimaryKey();
std::shared_ptr<Expression> primaryKeyExpression;
std::vector<expression_pair> setItems;
for (auto& property : catalog.getReadOnlyVersion()->getNodeProperties(nodeTableID)) {
if (collection.hasKeyVal(node, property.name)) {
setItems.emplace_back(collection.getKeyVal(node, property.name));
for (auto& property : catalog.getReadOnlyVersion()->getProperties(nodeTableID)) {
if (collection.hasKeyVal(node, property->getName())) {
setItems.emplace_back(collection.getKeyVal(node, property->getName()));
} else {
auto propertyExpression =
expressionBinder.bindNodePropertyExpression(*node, property.name);
expressionBinder.bindNodePropertyExpression(*node, property->getName());
auto nullExpression = expressionBinder.createNullLiteralExpression();
nullExpression = ExpressionBinder::implicitCastIfNecessary(
nullExpression, propertyExpression->dataType);
Expand All @@ -134,14 +134,14 @@ std::unique_ptr<BoundCreateInfo> Binder::bindCreateNodeInfo(
}
for (auto& [key, val] : collection.getKeyVals(node)) {
auto propertyExpression = static_pointer_cast<PropertyExpression>(key);
if (propertyExpression->getPropertyID(nodeTableID) == primaryKey.propertyID) {
if (propertyExpression->getPropertyID(nodeTableID) == primaryKey->getPropertyID()) {
primaryKeyExpression = val;
}
}
if (nodeTableSchema->getPrimaryKey().dataType.getLogicalTypeID() != LogicalTypeID::SERIAL &&
if (primaryKey->getDataType()->getLogicalTypeID() != LogicalTypeID::SERIAL &&
primaryKeyExpression == nullptr) {
throw BinderException("Create node " + node->toString() + " expects primary key " +
primaryKey.name + " as input.");
primaryKey->getName() + " as input.");
}
auto extraInfo = std::make_unique<ExtraCreateNodeInfo>(std::move(primaryKeyExpression));
return std::make_unique<BoundCreateInfo>(
Expand All @@ -160,12 +160,12 @@ std::unique_ptr<BoundCreateInfo> Binder::bindCreateRelInfo(
// CreateRel requires all properties in schema as input. So we rewrite set property to
// null if user does not specify a property in the query.
std::vector<expression_pair> setItems;
for (auto& property : catalogContent->getRelProperties(relTableID)) {
if (collection.hasKeyVal(rel, property.name)) {
setItems.push_back(collection.getKeyVal(rel, property.name));
for (auto& property : catalogContent->getProperties(relTableID)) {
if (collection.hasKeyVal(rel, property->getName())) {
setItems.push_back(collection.getKeyVal(rel, property->getName()));
} else {
auto propertyExpression =
expressionBinder.bindRelPropertyExpression(*rel, property.name);
expressionBinder.bindRelPropertyExpression(*rel, property->getName());
auto nullExpression = expressionBinder.createNullLiteralExpression();
nullExpression = ExpressionBinder::implicitCastIfNecessary(
nullExpression, propertyExpression->dataType);
Expand Down Expand Up @@ -262,20 +262,21 @@ std::unique_ptr<BoundDeleteInfo> Binder::bindDeleteNodeInfo(std::shared_ptr<Node
auto anchorPrimaryKey = tableSchemas[0]->getPrimaryKey();
for (auto i = 1; i < tableSchemas.size(); ++i) {
auto primaryKey = tableSchemas[i]->getPrimaryKey();
if (primaryKey.name != anchorPrimaryKey.name) {
if (primaryKey->getName() != anchorPrimaryKey->getName()) {
throw common::BinderException(common::StringUtils::string_format(
"Cannot delete node {} with different primary key name. Expect {} but get {}.",
node->toString(), anchorPrimaryKey.name, primaryKey.name));
node->toString(), anchorPrimaryKey->getName(), primaryKey->getName()));
}
if (primaryKey.dataType != anchorPrimaryKey.dataType) {
if (*primaryKey->getDataType() != *anchorPrimaryKey->getDataType()) {
throw common::BinderException(common::StringUtils::string_format(
"Cannot delete node {} with different primary key data type. Expect {} but get {}.",
node->toString(), LogicalTypeUtils::dataTypeToString(anchorPrimaryKey.dataType),
LogicalTypeUtils::dataTypeToString(primaryKey.dataType)));
node->toString(),
LogicalTypeUtils::dataTypeToString(*anchorPrimaryKey->getDataType()),
LogicalTypeUtils::dataTypeToString(*primaryKey->getDataType())));
}
}
auto primaryKeyExpression =
expressionBinder.bindNodePropertyExpression(*node, anchorPrimaryKey.name);
expressionBinder.bindNodePropertyExpression(*node, anchorPrimaryKey->getName());
auto extraInfo = std::make_unique<ExtraDeleteNodeInfo>(primaryKeyExpression);
return std::make_unique<BoundDeleteInfo>(UpdateTableType::NODE, node, std::move(extraInfo));
}
Expand Down
Loading

0 comments on commit 416d392

Please sign in to comment.