Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DDL to rel group #2103

Merged
merged 1 commit into from
Sep 28, 2023
Merged
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
11 changes: 10 additions & 1 deletion src/binder/bind/bind_copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,19 @@ std::unique_ptr<BoundStatement> Binder::bindCopyFromClause(const Statement& stat
auto& copyStatement = (CopyFrom&)statement;
auto catalogContent = catalog.getReadOnlyVersion();
auto tableName = copyStatement.getTableName();
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
// Bind to table schema.
auto tableID = catalogContent->getTableID(tableName);
auto tableSchema = catalogContent->getTableSchema(tableID);
switch (tableSchema->tableType) {
case TableType::REL_GROUP:
case TableType::RDF: {
throw BinderException(StringUtils::string_format("Cannot copy into {} table with type {}.",
tableName, TableTypeUtils::toString(tableSchema->tableType)));
}
default:
break;
}
auto csvReaderConfig = bindParsingOptions(copyStatement.getParsingOptionsRef());
auto filePaths = bindFilePaths(copyStatement.getFilePaths());
auto fileType = bindFileType(filePaths);
Expand Down
55 changes: 48 additions & 7 deletions src/binder/bind/bind_ddl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "binder/ddl/bound_create_table.h"
#include "binder/ddl/bound_drop_table.h"
#include "catalog/node_table_schema.h"
#include "catalog/rel_table_group_schema.h"
#include "catalog/rel_table_schema.h"
#include "common/exception/binder.h"
#include "common/string_utils.h"
Expand Down Expand Up @@ -219,11 +220,35 @@
std::unique_ptr<BoundStatement> Binder::bindDropTable(const Statement& statement) {
auto& dropTable = reinterpret_cast<const Drop&>(statement);
auto tableName = dropTable.getTableName();
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
auto catalogContent = catalog.getReadOnlyVersion();
auto tableID = catalogContent->getTableID(tableName);
if (catalogContent->containsNodeTable(tableName)) {
validateNodeTableHasNoEdge(catalog, tableID);
auto tableSchema = catalogContent->getTableSchema(tableID);
switch (tableSchema->tableType) {
case TableType::NODE: {
for (auto& schema : catalogContent->getRelTableSchemas()) {
auto relTableSchema = reinterpret_cast<RelTableSchema*>(schema);
if (relTableSchema->isSrcOrDstTable(tableID)) {
throw BinderException(StringUtils::string_format(

Check warning on line 232 in src/binder/bind/bind_ddl.cpp

View check run for this annotation

Codecov / codecov/patch

src/binder/bind/bind_ddl.cpp#L232

Added line #L232 was not covered by tests
"Cannot delete node table {} referenced by rel table {}.",
tableSchema->tableName, relTableSchema->tableName));

Check warning on line 234 in src/binder/bind/bind_ddl.cpp

View check run for this annotation

Codecov / codecov/patch

src/binder/bind/bind_ddl.cpp#L234

Added line #L234 was not covered by tests
}
}
} break;
case TableType::REL: {
for (auto& schema : catalogContent->getRelTableGroupSchemas()) {
auto relTableGroupSchema = reinterpret_cast<RelTableGroupSchema*>(schema);
for (auto& relTableID : relTableGroupSchema->getRelTableIDs()) {
if (relTableID == tableSchema->getTableID()) {
throw BinderException(StringUtils::string_format(
"Cannot delete rel table {} referenced by rel group {}.",
tableSchema->tableName, relTableGroupSchema->tableName));
}
}
}
}
default:
break;
}
return make_unique<BoundDropTable>(tableID, tableName);
}
Expand Down Expand Up @@ -255,7 +280,7 @@
auto tableName = info->tableName;
auto newName = extraInfo->newName;
auto catalogContent = catalog.getReadOnlyVersion();
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
if (catalogContent->containsTable(newName)) {
throw BinderException("Table: " + newName + " already exists.");
}
Expand All @@ -280,17 +305,31 @@
}
}

static void validatePropertyDDLOnTable(TableSchema* tableSchema, const std::string& ddlOperation) {
switch (tableSchema->tableType) {
case TableType::REL_GROUP:
case TableType::RDF: {
throw BinderException(
StringUtils::string_format("Cannot {} property on table {} with type {}.", ddlOperation,
tableSchema->tableName, TableTypeUtils::toString(tableSchema->tableType)));
}
default:
return;
}
}

std::unique_ptr<BoundStatement> Binder::bindAddProperty(const Statement& statement) {
auto& alter = reinterpret_cast<const Alter&>(statement);
auto info = alter.getInfo();
auto extraInfo = reinterpret_cast<ExtraAddPropertyInfo*>(info->extraInfo.get());
auto tableName = info->tableName;
auto dataType = bindDataType(extraInfo->dataType);
auto propertyName = extraInfo->propertyName;
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
auto catalogContent = catalog.getReadOnlyVersion();
auto tableID = catalogContent->getTableID(tableName);
auto tableSchema = catalogContent->getTableSchema(tableID);
validatePropertyDDLOnTable(tableSchema, "add");
validatePropertyNotExist(tableSchema, propertyName);
if (dataType->getLogicalTypeID() == LogicalTypeID::SERIAL) {
throw BinderException("Serial property in node table must be the primary key.");
Expand All @@ -310,10 +349,11 @@
auto extraInfo = reinterpret_cast<ExtraDropPropertyInfo*>(info->extraInfo.get());
auto tableName = info->tableName;
auto propertyName = extraInfo->propertyName;
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
auto catalogContent = catalog.getReadOnlyVersion();
auto tableID = catalogContent->getTableID(tableName);
auto tableSchema = catalogContent->getTableSchema(tableID);
validatePropertyDDLOnTable(tableSchema, "drop");
validatePropertyExist(tableSchema, propertyName);
auto propertyID = tableSchema->getPropertyID(propertyName);
if (tableSchema->getTableType() == TableType::NODE &&
Expand All @@ -333,10 +373,11 @@
auto tableName = info->tableName;
auto propertyName = extraInfo->propertyName;
auto newName = extraInfo->newName;
validateNodeRelTableExist(tableName);
validateTableExist(tableName);
auto catalogContent = catalog.getReadOnlyVersion();
auto tableID = catalogContent->getTableID(tableName);
auto tableSchema = catalogContent->getTableSchema(tableID);
validatePropertyDDLOnTable(tableSchema, "rename");
validatePropertyExist(tableSchema, propertyName);
auto propertyID = tableSchema->getPropertyID(propertyName);
validatePropertyNotExist(tableSchema, newName);
Expand Down
18 changes: 0 additions & 18 deletions src/binder/binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,24 +172,6 @@ void Binder::validateTableExist(const std::string& tableName) {
}
}

void Binder::validateNodeRelTableExist(const std::string& tableName) {
if (!catalog.getReadOnlyVersion()->containsNodeTable(tableName) &&
!catalog.getReadOnlyVersion()->containsRelTable(tableName)) {
throw BinderException("Table " + tableName + " does not exist.");
}
}

void Binder::validateNodeTableHasNoEdge(const Catalog& _catalog, table_id_t tableID) {
for (auto& tableSchema : _catalog.getReadOnlyVersion()->getRelTableSchemas()) {
auto relTableSchema = reinterpret_cast<RelTableSchema*>(tableSchema);
if (relTableSchema->isSrcOrDstTable(tableID)) {
throw BinderException(StringUtils::string_format(
"Cannot delete a node table with edges. It is on the edges of rel: {}.",
relTableSchema->tableName));
}
}
}

std::string Binder::getUniqueExpressionName(const std::string& name) {
return "_" + std::to_string(lastExpressionId++) + "_" + name;
}
Expand Down
21 changes: 16 additions & 5 deletions src/catalog/catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,34 @@ common::table_id_t Catalog::addRelTableGroupSchema(const binder::BoundCreateTabl
auto tableID = catalogContentForWriteTrx->addRelTableGroupSchema(info);
auto relTableGroupSchema =
(RelTableGroupSchema*)catalogContentForWriteTrx->getTableSchema(tableID);
// TODO(Ziyi): remove this when we can log variable size record. See also wal_record.h
for (auto relTableID : relTableGroupSchema->getRelTableIDs()) {
wal->logRelTableRecord(relTableID);
}
wal->logRelTableGroupRecord(tableID, relTableGroupSchema->getRelTableIDs());
return tableID;
}

common::table_id_t Catalog::addRdfGraphSchema(const binder::BoundCreateTableInfo& info) {
table_id_t Catalog::addRdfGraphSchema(const binder::BoundCreateTableInfo& info) {
initCatalogContentForWriteTrxIfNecessary();
return catalogContentForWriteTrx->addRdfGraphSchema(info);
}

void Catalog::dropTableSchema(table_id_t tableID) {
initCatalogContentForWriteTrxIfNecessary();
catalogContentForWriteTrx->dropTableSchema(tableID);
wal->logDropTableRecord(tableID);
auto tableSchema = catalogContentForWriteTrx->getTableSchema(tableID);
switch (tableSchema->tableType) {
case TableType::REL_GROUP: {
auto relTableGroupSchema = reinterpret_cast<RelTableGroupSchema*>(tableSchema);
auto relTableIDs = relTableGroupSchema->getRelTableIDs();
catalogContentForWriteTrx->dropTableSchema(tableID);
for (auto relTableID : relTableIDs) {
wal->logDropTableRecord(relTableID);
}
} break;
default: {
catalogContentForWriteTrx->dropTableSchema(tableID);
wal->logDropTableRecord(tableID);
}
}
}

void Catalog::renameTable(table_id_t tableID, const std::string& newName) {
Expand Down
14 changes: 12 additions & 2 deletions src/catalog/catalog_content.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,18 @@ std::vector<TableSchema*> CatalogContent::getTableSchemas(
}

void CatalogContent::dropTableSchema(table_id_t tableID) {
auto tableName = getTableName(tableID);
tableNameToIDMap.erase(tableName);
auto tableSchema = getTableSchema(tableID);
switch (tableSchema->tableType) {
case common::TableType::REL_GROUP: {
auto relTableGroupSchema = reinterpret_cast<RelTableGroupSchema*>(tableSchema);
for (auto& relTableID : relTableGroupSchema->getRelTableIDs()) {
dropTableSchema(relTableID);
}
} break;
default:
break;
}
tableNameToIDMap.erase(tableSchema->tableName);
tableSchemas.erase(tableID);
}

Expand Down
1 change: 1 addition & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_library(kuzu_common
type_utils.cpp
utils.cpp
string_utils.cpp
table_type.cpp
ser_deser.cpp)

target_link_libraries(kuzu_common Glob)
Expand Down
31 changes: 31 additions & 0 deletions src/common/table_type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "common/table_type.h"

#include "common/exception/not_implemented.h"

namespace kuzu {
namespace common {

std::string TableTypeUtils::toString(TableType tableType) {
switch (tableType) {
case TableType::UNKNOWN: {
return "UNKNOWN";

Check warning on line 11 in src/common/table_type.cpp

View check run for this annotation

Codecov / codecov/patch

src/common/table_type.cpp#L11

Added line #L11 was not covered by tests
}
case TableType::NODE: {
return "NODE";
}
case TableType::REL: {
return "REL";
}
case TableType::RDF: {
return "RDF";

Check warning on line 20 in src/common/table_type.cpp

View check run for this annotation

Codecov / codecov/patch

src/common/table_type.cpp#L20

Added line #L20 was not covered by tests
}
case TableType::REL_GROUP: {
return "REL_GROUP";
}
default: // LCOV_EXCL_START
throw NotImplementedException("TableTypeUtils::toString"); // LCOV_EXCL_STOP

Check warning on line 26 in src/common/table_type.cpp

View check run for this annotation

Codecov / codecov/patch

src/common/table_type.cpp#L26

Added line #L26 was not covered by tests
}
}

} // namespace common
} // namespace kuzu
17 changes: 1 addition & 16 deletions src/function/table_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,7 @@ void ShowTablesFunction::tableFunc(std::pair<offset_t, offset_t> morsel,
for (auto i = 0u; i < numTablesToOutput; i++) {
auto tableSchema = tables[morsel.first + i];
outputVectors[0]->setValue(i, tableSchema->tableName);

std::string typeString;
switch (tableSchema->tableType) {
case TableType::NODE: {
typeString = "NODE";
} break;
case TableType::REL: {
typeString = "REL";
} break;
case TableType::RDF: {
typeString = "RDF";
} break;
default: {
throw common::NotImplementedException{"ShowTablesFunction::tableFunc"};
}
};
std::string typeString = TableTypeUtils::toString(tableSchema->tableType);
outputVectors[1]->setValue(i, typeString);
outputVectors[2]->setValue(i, tableSchema->comment);
}
Expand Down
5 changes: 0 additions & 5 deletions src/include/binder/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,6 @@ class Binder {

void validateTableType(common::table_id_t tableID, common::TableType expectedTableType);
void validateTableExist(const std::string& tableName);
// TODO(Xiyang): remove this validation once we refactor DDL.
void validateNodeRelTableExist(const std::string& tableName);

static void validateNodeTableHasNoEdge(
const catalog::Catalog& _catalog, common::table_id_t tableID);

/*** helpers ***/
std::string getUniqueExpressionName(const std::string& name);
Expand Down
3 changes: 3 additions & 0 deletions src/include/catalog/catalog_content.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class CatalogContent {
inline std::vector<TableSchema*> getRelTableSchemas() const {
return getTableSchemas(common::TableType::REL);
}
inline std::vector<TableSchema*> getRelTableGroupSchemas() const {
return getTableSchemas(common::TableType::REL_GROUP);
}

std::vector<TableSchema*> getTableSchemas() const;
std::vector<TableSchema*> getTableSchemas(
Expand Down
5 changes: 5 additions & 0 deletions src/include/common/table_type.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <cstdint>
#include <string>

namespace kuzu {
namespace common {
Expand All @@ -13,5 +14,9 @@ enum class TableType : uint8_t {
REL_GROUP = 4,
};

struct TableTypeUtils {
static std::string toString(TableType tableType);
};

} // namespace common
} // namespace kuzu
2 changes: 0 additions & 2 deletions src/include/storage/wal/wal.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ class WAL : public BaseWALAndWALIterator {

void logNodeTableRecord(common::table_id_t tableID);
void logRelTableRecord(common::table_id_t tableID);
void logRelTableGroupRecord(
common::table_id_t tableID, std::vector<common::table_id_t> relTableIDs);
void logRdfGraphRecord(common::table_id_t rdfGraphID, common::table_id_t nodeTableID,
common::table_id_t relTableID);

Expand Down
17 changes: 0 additions & 17 deletions src/include/storage/wal/wal_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,6 @@ struct RelTableRecord {
inline bool operator==(const RelTableRecord& rhs) const { return tableID == rhs.tableID; }
};

struct RelTableGroupRecord {
common::table_id_t tableID;
// TODO(Ziyi): add this back when we can serialize variable size record.
// std::vector<RelTableRecord> relTableRecords;

RelTableGroupRecord() = default;
RelTableGroupRecord(common::table_id_t tableID) : tableID{tableID} {}

bool operator==(const RelTableGroupRecord& other) const;
};

struct RdfGraphRecord {
common::table_id_t tableID;
NodeTableRecord nodeTableRecord;
Expand Down Expand Up @@ -456,7 +445,6 @@ struct WALRecord {
CommitRecord commitRecord;
NodeTableRecord nodeTableRecord;
RelTableRecord relTableRecord;
RelTableGroupRecord relTableGroupRecord;
RdfGraphRecord rdfGraphRecord;
DiskOverflowFileNextBytePosRecord diskOverflowFileNextBytePosRecord;
CopyNodeRecord copyNodeRecord;
Expand Down Expand Up @@ -491,9 +479,6 @@ struct WALRecord {
case WALRecordType::REL_TABLE_RECORD: {
return relTableRecord == rhs.relTableRecord;
}
case WALRecordType::REL_TABLE_GROUP_RECORD: {
return relTableGroupRecord == rhs.relTableGroupRecord;
}
case WALRecordType::RDF_GRAPH_RECORD: {
return rdfGraphRecord == rhs.rdfGraphRecord;
}
Expand Down Expand Up @@ -531,8 +516,6 @@ struct WALRecord {
static WALRecord newCatalogRecord();
static WALRecord newNodeTableRecord(common::table_id_t tableID);
static WALRecord newRelTableRecord(common::table_id_t tableID);
static WALRecord newRelTableGroupRecord(
common::table_id_t tableID, std::vector<common::table_id_t> relTableIDs);
static WALRecord newRdfGraphRecord(common::table_id_t rdfGraphID,
common::table_id_t nodeTableID, common::table_id_t relTableID);
static WALRecord newOverflowFileNextBytePosRecord(
Expand Down
1 change: 0 additions & 1 deletion src/include/storage/wal_replayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class WALReplayer {
void replayNodeTableRecord(const WALRecord& walRecord);
// TODO(Guodong/Ziyi) : fix this
void replayRelTableRecord(const WALRecord& walRecord, bool isRdf = false);
void replayRelTableGroupRecord(const WALRecord& walRecord);
void replayRdfGraphRecord(const WALRecord& walRecord);
void replayOverflowFileNextBytePosRecord(const WALRecord& walRecord);
void replayCopyNodeRecord(const WALRecord& walRecord);
Expand Down
Loading