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

Enumerating error codes for error management #1350

Open
wants to merge 7 commits into
base: staging
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ parts:
title: Troubleshooting
- file: source/dev-guide/contribute/unit-test
title: Unit Testing UDFs in EvaDB
- file: source/dev-guide/contribute/error-codes
title: Error Codes in EvaDB

- file: source/dev-guide/debugging
title: Debugging EvaDB
Expand Down
41 changes: 41 additions & 0 deletions docs/source/dev-guide/contribute/error-codes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Using Error Codes in EvaDB
==========================

Introduction
------------

Proper error handling is an essential aspect of robust software development. In EvaDB, error codes provide a standardized way of reporting and logging errors. This guide explains how to use predefined error codes, and how they enhance debugging and error tracking.

Error Codes Overview
--------------------

EvaDB implements an `ErrorManager` class with predefined error codes for various error scenarios. Each error code is associated with a default error message, which can be extended with additional information when required. A list of all error codes can be found in `evadb/error_manager.py`.

Using Error Codes without Additional Message
--------------------------------------------

In cases where the default error message suffices, you can use the error code directly. This is common in scenarios where the error context is self-explanatory.

.. code-block:: python

from error_manager import ErrorManager

# Example of using an error code without an additional message
def some_function():
if not some_condition:
raise Exception(ErrorManager.get_error_message(ErrorManager.EXPECTED_SELECTION_STATEMENT))

Using Error Codes with Additional Message
-----------------------------------------

In scenarios requiring more detailed error information, you can provide an additional message along with the error code. This is useful for adding context or specifics about the error.

.. code-block:: python

from error_manager import ErrorManager

# Example of using an error code with an additional message
def some_function(param):
if not validate(param):
error_msg = ErrorManager.get_error_message(ErrorManager.UNSUPPORTED_TYPE, f"Invalid parameter: {param}")
raise Exception(error_msg)
176 changes: 176 additions & 0 deletions error-map.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
0000 - ERROR_GENERIC

=======================Expected-Type Errors=======================

0100 - EXPECTED_SELECTION_STATEMENT
- evadb/parser/utils.py
- 41
- 48
- 61
- 170
- 184
- evadb/interfaces/relational/utils.py
- 88
- evadb/parser/table_ref.py
- 253
0101 - EXPECTED_CREATE_TABLE_STATEMENT
- evadb/parser/utils.py
- 101
0102 - EXPECTED_SHOW_STATEMENT
- evadb/parser/utils.py
- 108
0103 - EXPECTED_INSERT_STATEMENT
- evadb/parser/utils.py
- 122
0104 - EXPECTED_EXPLAIN_STATEMENT
- evadb/parser/utils.py
- 115
0105 - EXPECTED_LOAD_STATEMENT
- evadb/parser/utils.py
- 129
0106 - EXPECTED_DROP_OBJECT_STATEMENT
- evadb/parser/utils.py
- 141
0107 - EXPECTED_RENAME_STATEMENT
- evadb/parser/utils.py
- 191
0108 - EXPECTED_CREATE_FUNCTION_STATEMENT
- evadb/parser/utils.py
- 88
0109_EXPECTED_COLUMNS_NUMBER_MISMATCH
- evadb/binder/binder_utils.py
- 246

0110 - QUERY_EXPECTS_ONE_CHILD
- evadb/executor/create_executor.py
- 67
- evadb/executor/create_function_executor.py
- 114
- 164
- 221
0111 - EXPECTED_API_TOKEN_SET
- evadb/functions/chatgpt.py
- 127
- evadb/functions/dalle.py
- 65
- evadb/functions/stable_diffusion.py
- 68
- evadb/third_party/vector_stores/pinecone.py
- 44
- 53
0112 - EXPECTED_PD_DF
- evadb/functions/abstract/tracker_abstract_function.py
- 90


=======================Index Errors=======================

1100 - CANNOT_CREATE_INDEX_ON_MULIPLE_COLUMN
- evadb/binder/create_index_statement_binder.py
- 37
- 67
1101 - CREATE_INDEX_ONLY_ON_EXISTING_TABLE
- - evadb/binder/create_index_statement_binder.py
- 40
1102 - CANNOT_CREATE_INDEX_ON_NONEXISTANT_COLUMN
- evadb/binder/create_index_statement_binder.py
- 76
1103 - INDEX_INPUT_TYPE_MISMATCH
- evadb/binder/create_index_statement_binder.py
- 85
- 100
1104 - INDEX_INPUT_DIM_MISMATCH
- evadb/binder/create_index_statement_binder.py
- 94
1105 - CREATE_INDEX_FIRST
- evadb/third_party/vector_stores/faiss.py
- 58
- 67
- 73

=======================Type Errors=======================

2100 - UNSUPPORTED_TYPE
- evadb/catalog/catalog_manager.py
- 551
- evadb/executor/delete_executor.py
- 73
- evadb/executor/show_info_executor.py
- 32
- evadb/expression/comparison_expression.py
- 49
- evadb/expression/tuple_value_expression.py
- 83
2101 - UNSUPPORTED_OPERATION
- evadb/executor/union_executor.py
- 35
- evadb/models/storage/batch.py
- 204
- 268
- evadb/optimizer/binder.py
- 61
- evadb/optimizer/group_expression.py
- 31
- evadb/executor/exchange_executor.py
- 74
2102 - UNSUPPORTED_CLAUSE
- evadb/interfaces/relational/utils.py
- 100
2103 - UNSUPPORTED_LIBRARY
- evadb/executor/create_function_executor.py
- 319
2104 - CONCURRENT_CALLS_NOT_SUPPORTED
- evadb/utils/stats.py
- 32




=======================Not Found/ Already Exists Errors=========================

3100 - TABLE_NOT_FOUND
- evadb/catalog/catalog_manager.py
- 589

3101 - TABLE_ALREADY_EXISTS
- evadb/catalog/catalog_manager.py
- 613

3102 - DIRECTORY_NOT_FOUND
- evadb/configuration/bootstrap_environment.py
- 60
- 61

3103 - DIRECTORY_ALREADY_EXISTS

3104 - FILE_NOT_FOUND
- evadb/functions/ndarray/open.py
- 48

3105 - FILE_ALREADY_EXISTS

3106 - KEY_NOT_FOUND
- evadb/executor/exchange_executor.py
- 35
- 38


=======================Failed-to Errors=======================
4100 - DROP_TABLE_FAILED
- evadb/executor/drop_object_executor.py
- 68
4101 - VECTOR_STORE_HANDLER_INITALIZATION_FAILED
- evadb/executor/drop_object_executor.py
- 125

4102 - RELATION_EXECUTE_FAILED
- evadb/interfaces/relational/relation.py
- 124
- 264

=======================Not implemented=======================
9999 - NOT_IMPLEMENTED
- evadb/executor/delete_executor.py
- 97
- evadb/executor/insert_executor.py
- 41
81 changes: 81 additions & 0 deletions evadb/error_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# coding=utf-8
# Copyright 2018-2023 EvaDB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from enum import Enum


class ErrorCode:
def __init__(self, code, message=""):
self.code = code
self.default_message = message

def __str__(self):
return f"[{self.code}] {self.default_message}"

class ErrorManager:
# Generic Error
ERROR_GENERIC = ErrorCode(0, "Error")

# Expected-Type Errors
EXPECTED_SELECTION_STATEMENT = ErrorCode(100, "Expected a select statement")
EXPECTED_CREATE_TABLE_STATEMENT = ErrorCode(101, "Expected a create table statement")
EXPECTED_SHOW_STATEMENT = ErrorCode(102, "Expected a show statement")
EXPECTED_INSERT_STATEMENT = ErrorCode(103, "Expected an insert statement")
EXPECTED_EXPLAIN_STATEMENT = ErrorCode(104, "Expected an explain statement")
EXPECTED_LOAD_STATEMENT = ErrorCode(105, "Expected a load statement")
EXPECTED_DROP_OBJECT_STATEMENT = ErrorCode(106, "Expected a drop object statement")
EXPECTED_RENAME_STATEMENT = ErrorCode(107, "Expected a rename statement")
EXPECTED_CREATE_FUNCTION_STATEMENT = ErrorCode(108, "Expected a create function statement")
EXPECTED_COLUMNS_NUMBER_MISMATCH = ErrorCode(109, "Unexpected number of columns")
QUERY_EXPECTS_ONE_CHILD = ErrorCode(110, "Query expects one child")
EXPECTED_API_TOKEN_SET = ErrorCode(111, "API token expected to be se.")
EXPECTED_PD_DF = ErrorCode(112, "Expected a Pandas DataFrame")

# Index Errors
CANNOT_CREATE_INDEX_ON_MULIPLE_COLUMN = ErrorCode(1100, "Index cannot be created on more than 1 column")
CREATE_INDEX_ONLY_ON_EXISTING_TABLE = ErrorCode(1101, "Index can only be created on an existing table")
CANNOT_CREATE_INDEX_ON_NONEXISTANT_COLUMN = ErrorCode(1102, "Index is created on non-existent column")
INDEX_INPUT_TYPE_MISMATCH = ErrorCode(1103, "Index input type is mismatched")
INDEX_INPUT_DIM_MISMATCH = ErrorCode(1104, "Index input dimensions are mismatched")
CREATE_INDEX_FIRST = ErrorCode(1105, "Create an index first")

# Type Errors
UNSUPPORTED_TYPE = ErrorCode(2100, "Type not supported")
UNSUPPORTED_OPERATION = ErrorCode(2101, "Operation not supported")
UNSUPPORTED_CLAUSE = ErrorCode(2102, "Clause not supported")
UNSUPPORTED_LIBRARY = ErrorCode(2103, "Library not supported")
CONCURRENT_CALLS_NOT_SUPPORTED = ErrorCode(2104, "Concurrent queries not supported")

# Not Found/Already Exists Errors
TABLE_NOT_FOUND = ErrorCode(3100, "Table not found")
TABLE_ALREADY_EXISTS = ErrorCode(3101, "Table already exists")
DIRECTORY_NOT_FOUND = ErrorCode(3102, "Directory not found")
DIRECTORY_ALREADY_EXISTS = ErrorCode(3103, "Directory already exists")
FILE_NOT_FOUND = ErrorCode(3104, "File not found")
FILE_ALREADY_EXISTS = ErrorCode(3105, "File already exists")
KEY_NOT_FOUND = ErrorCode(3106, "Key not found")

# Failed-to Errors
DROP_TABLE_FAILED = ErrorCode(4100, "DROP table failed")
VECTOR_STORE_HANDLER_INITALIZATION_FAILED = ErrorCode(4101, "Initialization of vector store failed")
RELATION_EXECUTE_FAILED = ErrorCode(4102, "Relation execute failed")

# Not implemented
NOT_IMPLEMENTED = ErrorCode(9999, "Functionality not implemented for current use-case.")

@staticmethod
def get_error_message(error_code, additional_message=None):
if additional_message:
return f"{error_code} Details: {additional_message}"
return str(error_code)
10 changes: 6 additions & 4 deletions evadb/executor/create_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pandas as pd

from evadb.database import EvaDBDatabase
from evadb.error_manager import ErrorManager
from evadb.executor.abstract_executor import AbstractExecutor
from evadb.executor.executor_utils import (
create_table_catalog_entry_for_native_table,
Expand Down Expand Up @@ -64,10 +65,11 @@ def exec(self, *args, **kwargs):

msg = f"The table {name} has been successfully created"
if self.children != []:
assert (
len(self.children) == 1
), "Create table from query expects 1 child, finds {}".format(
len(self.children)
assert len(self.children) == 1, ErrorManager.get_error_message(
ErrorManager.QUERY_EXPECTS_ONE_CHILD,
"Create table from query expects 1 child, finds {}".format(
len(self.children)
),
)
child = self.children[0]

Expand Down