Skip to content

Commit

Permalink
Add DDL to rel group
Browse files Browse the repository at this point in the history
  • Loading branch information
andyfengHKU committed Sep 28, 2023
1 parent 17723ab commit fe77b6b
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 101 deletions.
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::bindCreateTable(const parser::Statement&
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 @@ std::unique_ptr<BoundStatement> Binder::bindRenameTable(const Statement& stateme
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 validatePropertyNotExist(TableSchema* tableSchema, const std::string
}
}

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 @@ std::unique_ptr<BoundStatement> Binder::bindDropProperty(const Statement& statem
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 @@ std::unique_ptr<BoundStatement> Binder::bindRenameProperty(const Statement& stat
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

0 comments on commit fe77b6b

Please sign in to comment.