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 HTTP API service of Create table and Drop table. #820

Closed
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
6 changes: 3 additions & 3 deletions python/test/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ def test_without_output_select_list(self):
@pytest.mark.parametrize("condition_list", ["c1 > 0.1 and c2 < 3.0",
"c1 > 0.1 and c2 < 1.0",
"c1 < 0.1 and c2 < 1.0",
pytest.param("c1 + 0.1 and c2 - 1.0",marks=pytest.mark.xfail),
pytest.param("c1 * 0.1 and c2 / 1.0",marks=pytest.mark.xfail),
pytest.param("c1 > 0.1 %@#$sf c2 < 1.0",marks=pytest.mark.xfail),
pytest.param("c1 + 0.1 and c2 - 1.0", marks=pytest.mark.xfail),
pytest.param("c1 * 0.1 and c2 / 1.0", marks=pytest.mark.xfail),
pytest.param("c1 > 0.1 %@#$sf c2 < 1.0", marks=pytest.mark.xfail),
"c1",
"c1 = 0",
"_row_id",
Expand Down
2 changes: 1 addition & 1 deletion python/test/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ def test_table_with_various_column_types(self):
assert res.error_code == ErrorCode.OK

# create/drop table with different invalid options
@pytest.mark.skip(reason="teardown error")
# @pytest.mark.skip(reason="teardown error")
@pytest.mark.parametrize("invalid_option_array", [
pytest.param([], marks=pytest.mark.xfail),
pytest.param((), marks=pytest.mark.xfail),
Expand Down
136 changes: 124 additions & 12 deletions src/network/http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
module;

#include "type/data_type.h"
#include "definition/column_def.h"
module http_server;

import infinity;
import third_party;
import defer_op;
import data_block;
import data_table;
import value;
import stl;
import infinity_exception;
import logger;
import query_result;
import query_options;
import column_vector;
import infinity_context;
import session;
import session_manager;
import query_context;
import parsed_expr;
import search_expr;
import column_def;


namespace {
Expand Down Expand Up @@ -70,12 +84,17 @@ class CreateDatabaseHandler final : public HttpRequestHandler {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

// get database name
String database_name = request->getPathVariable("database_name");

// get create option
String body_info = request->readBodyToString();

nlohmann::json body_info_json = nlohmann::json::parse(body_info);
String database_name = body_info_json["database_name"];
CreateDatabaseOptions options;
auto result = infinity->CreateDatabase(database_name, options);
String option = body_info_json["create_option"];
CreateDatabaseOptions create_option;

// create database
auto result = infinity->CreateDatabase(database_name, create_option);

HTTPStatus http_status;
nlohmann::json json_response;
Expand All @@ -98,11 +117,16 @@ class DropDatabaseHandler final : public HttpRequestHandler {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

// get database name
String database_name = request->getPathVariable("database_name");

// get drop option
String body_info = request->readBodyToString();
nlohmann::json body_info_json = nlohmann::json::parse(body_info);
String database_name = body_info_json["database_name"];
DropDatabaseOptions options;
auto result = infinity->DropDatabase(database_name,options);
String option = body_info_json["drop_option"];
DropDatabaseOptions drop_option;

auto result = infinity->DropDatabase(database_name,drop_option);

nlohmann::json json_response;
HTTPStatus http_status;
Expand All @@ -125,7 +149,7 @@ class RetrieveDatabaseHandler final : public HttpRequestHandler {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

auto db_name = request->getPathVariable("db_name");
auto db_name = request->getPathVariable("database_name");
auto result = infinity->GetDatabase(db_name);

nlohmann::json json_response;
Expand All @@ -143,6 +167,87 @@ class RetrieveDatabaseHandler final : public HttpRequestHandler {
}
};

class CreateTableHandler final : public HttpRequestHandler {
public:
SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

String database_name = request->getPathVariable("database_name");
String table_name = request->getPathVariable("table_name");

String body_info = request->readBodyToString();
nlohmann::json body_info_json = nlohmann::json::parse(body_info);

auto fields = body_info_json["fields"];
auto properties = body_info_json["properties"];

Vector<ColumnDef *> new_column_defs;
int id = 0;
nlohmann::json json_response;

for (auto &field : fields) {
for (auto& el : field.items()){
String column_name = el.key();
auto values = el.value();
SharedPtr<DataType> column_type = DataType::StringDeserialize(values["type"]);
// json_response["res"] = column_type->ToString();
HashSet<ConstraintType> constraints;
for (auto &constraint : values["constraints"]){
// json_response["res"] = ColumnDef::StringToConstraintType(constraint);
constraints.insert(ColumnDef::StringToConstraintType(constraint));
}
ColumnDef *col_def = new ColumnDef(id ++, column_type, column_name, constraints);
// json_response["res"] = col_def->ToString();
new_column_defs.emplace_back(col_def);
}
}
Vector<TableConstraint *> table_constraint;
CreateTableOptions create_table_opts;

auto result = infinity->CreateTable(database_name, table_name, new_column_defs, table_constraint, create_table_opts);

HTTPStatus http_status;
http_status = HTTPStatus::CODE_200;

if(result.IsOk()) {
json_response["error_code"] = 0;
http_status = HTTPStatus::CODE_200;
} else {
json_response["error_code"] = result.ErrorCode();
json_response["error_message"] = result.ErrorMsg();
http_status = HTTPStatus::CODE_500;
}
return ResponseFactory::createResponse(http_status, json_response.dump());
}
};

class DeleteTableHandler final : public HttpRequestHandler {
public:
SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final {
auto infinity = Infinity::RemoteConnect();
DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });

String database_name = request->getPathVariable("database_name");
String table_name = request->getPathVariable("table_name");
DropTableOptions drop_table_opts;
auto result = infinity->DropTable(database_name, table_name, drop_table_opts);

HTTPStatus http_status;
http_status = HTTPStatus::CODE_200;
nlohmann::json json_response;
if(result.IsOk()) {
json_response["error_code"] = 0;
http_status = HTTPStatus::CODE_200;
} else {
json_response["error_code"] = result.ErrorCode();
json_response["error_message"] = result.ErrorMsg();
http_status = HTTPStatus::CODE_500;
}
return ResponseFactory::createResponse(http_status, json_response.dump());
}
};

}

namespace infinity {
Expand All @@ -153,10 +258,17 @@ void HTTPServer::Start(u16 port) {

SharedPtr<HttpRouter> router = HttpRouter::createShared();
router->route("GET", "/hello", MakeShared<HttpHandler>());

// database
router->route("GET", "/databases", MakeShared<ListDatabaseHandler>());
router->route("POST", "/databases", MakeShared<CreateDatabaseHandler>());
router->route("DELETE", "/databases", MakeShared<DropDatabaseHandler>());
router->route("GET", "/databases/{db_name}", MakeShared<RetrieveDatabaseHandler>());
router->route("POST", "/databases/{database_name}", MakeShared<CreateDatabaseHandler>());
router->route("DELETE", "/databases/{database_name}", MakeShared<DropDatabaseHandler>());
router->route("GET", "/databases/{database_name}", MakeShared<RetrieveDatabaseHandler>());

// tables
router->route("POST", "/databases/{database_name}/tables/{table_name}", MakeShared<CreateTableHandler>());
router->route("DELETE", "/databases/{database_name}/tables/{table_name}", MakeShared<DeleteTableHandler>());


SharedPtr<HttpConnectionProvider> connection_provider = HttpConnectionProvider::createShared({"localhost", port, WebAddress::IP_4});
SharedPtr<HttpConnectionHandler> connection_handler = HttpConnectionHandler::createShared(router);
Expand Down
29 changes: 29 additions & 0 deletions src/parser/definition/column_def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,33 @@ std::string ColumnDef::ToString() const {
return ss.str();
}


ConstraintType ColumnDef::StringToConstraintType(std::string type) {
std::map<std::string, int> string_to_constraint_type = {
{"primarykey", 1},
{"unique", 2},
{"null", 3},
{"not null", 4},
{"invalid", 5},
};
if(string_to_constraint_type.find(type) != string_to_constraint_type.end()){
int num = string_to_constraint_type.find(type)->second;
switch (num) {
case 1:
return ConstraintType::kPrimaryKey;
case 2:
return ConstraintType::kUnique;
case 3:
return ConstraintType::kNull;
case 4:
return ConstraintType::kNotNull;
case 5:
return ConstraintType::kInvalid;
}
}
ParserError("Unexpected error.");
return ConstraintType::kInvalid;
}


} // namespace infinity
4 changes: 4 additions & 0 deletions src/parser/definition/column_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ enum class ConstraintType : char {

std::string ConstrainTypeToString(ConstraintType type);

ConstraintType StringToConstraintType(std::string string);

class TableElement {
public:
explicit TableElement(TableElementType type) : type_(type) {}
Expand Down Expand Up @@ -78,6 +80,8 @@ class ColumnDef : public TableElement {

ColumnDef(LogicalType logical_type, const std::shared_ptr<TypeInfo> &type_info_ptr);

static ConstraintType StringToConstraintType(std::string type);

inline ~ColumnDef() override = default;

std::string ToString() const;
Expand Down
37 changes: 37 additions & 0 deletions src/parser/type/data_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ std::string DataType::ToString() const {
return LogicalType2Str(type_);
}

LogicalType DataType::ToLogicalType() const {
return Str2LogicalType(str_type_);
}

bool DataType::operator==(const DataType &other) const {
if (this == &other)
return true;
Expand Down Expand Up @@ -308,6 +312,39 @@ std::shared_ptr<DataType> DataType::Deserialize(const nlohmann::json &data_type_
return data_type;
}


std::shared_ptr<DataType> DataType::StringDeserialize(const std::string &data_type_string) {
const LogicalType logical_type = Str2LogicalType(data_type_string);
std::shared_ptr<TypeInfo> type_info{nullptr};
// if (data_type_json.contains("type_info")) {
// const nlohmann::json &type_info_json = data_type_json["type_info"];
// switch (logical_type) {
// case LogicalType::kArray: {
// ParserError("Array isn't implemented here.");
// type_info = nullptr;
// break;
// }
// // case LogicalType::kBitmap: {
// // type_info = BitmapInfo::Make(type_info_json["length_limit"]);
// // break;
// // }
// case LogicalType::kDecimal: {
// type_info = DecimalInfo::Make(type_info_json["precision"], type_info_json["scale"]);
// break;
// }
// case LogicalType::kEmbedding: {
// type_info = EmbeddingInfo::Make(type_info_json["embedding_type"], type_info_json["dimension"]);
// break;
// }
// default:
// // There's no type_info for other types
// break;
// }
// }
std::shared_ptr<DataType> data_type = std::make_shared<DataType>(logical_type, type_info);
return data_type;
}

template <>
std::string DataType::TypeToString<BooleanT>() {
return "Boolean";
Expand Down
4 changes: 4 additions & 0 deletions src/parser/type/data_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class DataType {
bool operator!=(const DataType &other) const;

[[nodiscard]] std::string ToString() const;
[[nodiscard]] LogicalType ToLogicalType() const;

[[nodiscard]] size_t Size() const;

Expand Down Expand Up @@ -160,6 +161,8 @@ class DataType {

static std::shared_ptr<DataType> Deserialize(const nlohmann::json &data_type_json);

static std::shared_ptr<DataType> StringDeserialize(const std::string &data_type_string);

// Estimated serialized size in bytes, ensured be no less than Write requires, allowed be larger.
[[nodiscard]] int32_t GetSizeInBytes() const;

Expand All @@ -172,6 +175,7 @@ class DataType {

private:
LogicalType type_{LogicalType::kInvalid};
std::string str_type_ {"invalid"};
bool plain_type_{false};
std::shared_ptr<TypeInfo> type_info_{nullptr};
// Static method
Expand Down
Loading