from dataclasses import dataclass
from bluebase.core import (
Value,
Comp,
AstTable,
AstAttr,
AstCond,
AstAssign,
AstSelect,
AstInsert,
AstDelete,
AstUpdate,
dump,
optional,
assignment,
)
from bluebase.rm import RmRecordData
from bluebase.ix import IxEntry
from bluebase.sm import (
SmTableNotFound,
SmManager,
)
from .error import (
QlEmptySelectClauseError,
QlEmptyFromClauseError,
QlAmbiguousTableError,
QlAmbiguousAttrError,
QlDuplicateAsteriskError,
QlDuplicateTableError,
QlDuplicateCondError,
QlDuplicateAssignError,
QlTableNotFound,
QlAttrNotFoundError,
QlInvalidCondTypeError,
QlInvalidValueCountError,
QlInvalidValueTypeError,
QlInvalidAssignTypeError,
)
from .type import (
QlSchema,
QlContext,
QlAttr,
QlCond,
QlAttrCond,
QlValueCond,
QlAssign,
QlAttrAssign,
QlValueAssign,
)
from .op import (
QlOp,
QlLeafOp,
QlFileScanOp,
QlIndexScanOp,
QlCartesianOp,
QlLoopJoinOp,
QlHashJoinOp,
QlIndexJoinOp,
QlFilterOp,
QlProjectOp,
)
__all__ = (
'QlOptim',
'QlManager',
)
[docs]
@dataclass(slots=True)
class QlOptim:
"""
Attributes:
push_file:
push_index:
loop_join:
hash_join:
index_join:
first_leaf:
"""
push_file: bool = False
push_index: bool = False
loop_join: bool = False
hash_join: bool = False
index_join: bool = False
first_leaf: bool = False
def verbose(self) -> str: # pragma: no cover
options = [
f"push_file: {self.push_file}",
f"push_index: {self.push_index}",
f"loop_join: {self.loop_join}",
f"hash_join: {self.hash_join}",
f"index_join: {self.index_join}",
f"first_leaf: {self.first_leaf}",
]
return "QlOptim\n" + '\n'.join(f' {option}' for option in options)
[docs]
class QlManager:
"""
A manager for the `QL <bluebase.ql>` component.
Attributes:
sm:
optim:
"""
sm: SmManager
optim: QlOptim
def __repr__(self) -> str: # pragma: no cover
return f"QlManager({dump(sm=self.sm)})"
def __init__(self, sm: SmManager) -> None:
self.sm = sm
self.optim = QlOptim()
[docs]
@optional
def _get_context(self, tables_: list[AstTable]) -> QlContext:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _identify_attr(self, context: QlContext, name: str) -> str:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_attr(self, context: QlContext, attr_: AstAttr) -> QlAttr:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_cond(self, context: QlContext, cond_: AstCond) -> QlCond:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _validate_select_clause(self, attrs_: list[AstAttr]) -> None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _validate_from_clause(self, tables_: list[AstTable]) -> None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_attrs(self,
context: QlContext,
attrs_: list[AstAttr],
) -> list[QlAttr]:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_conds(self,
context: QlContext,
conds_: list[AstCond],
) -> dict[str, QlCond]:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_assign(self,
context: QlContext,
assign_: AstAssign,
) -> QlAssign:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _resolve_assigns(self,
context: QlContext,
assigns_: list[AstAssign],
) -> dict[str, QlAssign]:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _pushdown_conds(self,
context: QlContext,
conds: dict[str, QlCond],
) -> dict[str, tuple[QlValueCond, bool]]:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _determine_join(self,
op: QlOp,
ref: str,
cond: QlCond,
) -> QlAttr | None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _find_index_join(self,
context: QlContext,
op: QlOp,
leafs: dict[str, QlLeafOp],
conds: dict[str, QlCond],
) -> tuple[str, QlAttrCond] | None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _find_hash_join(self,
op: QlOp,
leafs: dict[str, QlLeafOp],
conds: dict[str, QlCond],
) -> tuple[str, QlAttrCond] | None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _find_loop_join(self,
op: QlOp,
leafs: dict[str, QlLeafOp],
conds: dict[str, QlCond],
) -> tuple[str, QlAttrCond] | None:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _choose_first_leaf(self,
context: QlContext,
leafs: dict[str, QlLeafOp],
conds: dict[str, QlCond],
pushdown: dict[str, tuple[QlValueCond, bool]],
) -> QlLeafOp:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@optional
def _align_attr(self,
leaf: QlLeafOp,
cond: QlAttrCond,
) -> tuple[QlAttr, QlAttr]:
"""
Hint:
이런 함수가 있으면 편하다!
"""
raise NotImplementedError
[docs]
@assignment
def select(self, ast: AstSelect) -> QlOp:
"""
Raises:
QlEmptySelectClauseError:
QlDuplicateAsteriskError:
QlEmptyFromClauseError:
QlDuplicateTableError:
QlTableNotFound:
QlAmbiguousTableError:
QlAttrNotFoundError:
QlAmbiguousAttrError:
QlInvalidCondTypeError:
QlDuplicateCondError:
"""
raise NotImplementedError
[docs]
@assignment
def insert(self, ast: AstInsert) -> None:
"""
Raises:
QlTableNotFound:
QlInvalidValueCountError:
QlInvalidValueTypeError:
"""
raise NotImplementedError
[docs]
@assignment
def delete(self, ast: AstDelete, explain: bool = False) -> QlOp | None:
"""
scan 중에 delete를 허용하는 방법은 index scan cursor 관리가 굉장히 어렵습니다.
여기서는 일단 scan 결과를 모두 취득한 후, 한번에 delete를 진행합니다.
이른바 materialization 기법이며, 구현은 간단해지지만 메모리가 조금 낭비됩니다.
Raises:
QlTableNotFound:
QlAttrNotFoundError:
QlInvalidCondTypeError:
QlDuplicateCondError:
"""
raise NotImplementedError
[docs]
@assignment
def update(self, ast: AstUpdate, explain: bool = False) -> QlOp | None:
"""
scan 중에 update를 허용하는 방법은 index scan cursor 관리가 굉장히 어렵습니다.
여기서는 일단 scan 결과를 모두 취득한 후, 한번에 update를 진행합니다.
이른바 materialization 기법이며, 구현은 간단해지지만 메모리가 조금 낭비됩니다.
Raises:
QlTableNotFound:
QlAttrNotFoundError:
QlInvalidAssignTypeError:
QlDuplicateAssignError:
QlInvalidCondTypeError:
QlDuplicateCondError:
"""
raise NotImplementedError