From 027a398287ae7f9533415bfbece6718159dd3690 Mon Sep 17 00:00:00 2001 From: automvc Date: Sun, 16 Mar 2025 18:30:50 +0800 Subject: [PATCH] support condition build in SQL --- src/bee/api.py | 90 +++++- src/bee/condition.py | 424 ++++++++++++++++++++++++++ src/bee/config.py | 5 +- src/bee/exception.py | 4 +- src/bee/factory.py | 31 +- src/bee/honeyfactory.py | 104 +++++++ src/bee/name/naming_handler.py | 2 +- src/bee/obj2sql.py | 209 +++++++++++-- src/bee/osql/enum.py | 66 +++- src/bee/osql/honeyfactory.py | 20 -- src/bee/sqllib.py | 16 +- tests/exam/BatchInsertTest.py | 18 +- tests/exam15/ByIdTest.py | 3 +- tests/exam16/SuidTest1.py | 39 +++ tests/exam16/SuidTest2.py | 53 ++++ tests/exam16/conditionTest.py | 68 +++++ tests/exam16/conditionTest2.py | 40 +++ tests/exam16/conditionTest3_paging.py | 66 ++++ tests/exam16/conditionTest4_delete.py | 53 ++++ tests/exam16/conditionTest5_update.py | 42 +++ 20 files changed, 1281 insertions(+), 72 deletions(-) create mode 100644 src/bee/condition.py create mode 100644 src/bee/honeyfactory.py delete mode 100644 src/bee/osql/honeyfactory.py create mode 100644 tests/exam16/SuidTest1.py create mode 100644 tests/exam16/SuidTest2.py create mode 100644 tests/exam16/conditionTest.py create mode 100644 tests/exam16/conditionTest2.py create mode 100644 tests/exam16/conditionTest3_paging.py create mode 100644 tests/exam16/conditionTest4_delete.py create mode 100644 tests/exam16/conditionTest5_update.py diff --git a/src/bee/api.py b/src/bee/api.py index 0ed8a8d..3a57554 100644 --- a/src/bee/api.py +++ b/src/bee/api.py @@ -1,11 +1,12 @@ from bee import SqlUtil +from bee.base import AbstractCommOperate from bee.exception import BeeException, ParamBeeException from bee.obj2sql import ObjToSQL from bee.osql.enum import FunctionType, SuidType from bee.osql.logger import Logger from bee.sqllib import BeeSql -from bee.base import AbstractCommOperate +from bee.condition import Condition class Suid(AbstractCommOperate): @@ -24,7 +25,7 @@ class Suid(AbstractCommOperate): sql, params = self.objToSQL.toSelectSQL(entity) Logger.logsql("select SQL:", sql) super().log_params(params) - list_r= self.beeSql.select(sql, self.to_class_t(entity), params) # 返回值用到泛型 + list_r = self.beeSql.select(sql, self.to_class_t(entity), params) return list_r except Exception as e: raise BeeException(e) @@ -75,6 +76,39 @@ class Suid(AbstractCommOperate): raise BeeException(e) finally: super().doBeforeReturnSimple() + + # since 1.6.0 + def select2(self, entity, condition: Condition=None): + if entity is None: + return None + + try: + super().doBeforePasreEntity(entity, SuidType.SELECT) + sql, params = self.objToSQL.toSelectSQL2(entity, condition) + Logger.logsql("select SQL:", sql) + super().log_params(params) + list_r = self.beeSql.select(sql, self.to_class_t(entity), params) + return list_r + except Exception as e: + raise BeeException(e) + finally: + super().doBeforeReturn(list_r) + + # since 1.6.0 + def delete2(self, entity, condition: Condition=None): + if entity is None: + return None + + try: + super().doBeforePasreEntity(entity, SuidType.DELETE) + sql, params = self.objToSQL.toDeleteSQL2(entity, condition) + Logger.logsql("delete SQL:", sql) + super().log_params(params) + return self.beeSql.modify(sql, params) + except Exception as e: + raise BeeException(e) + finally: + super().doBeforeReturnSimple() def to_class_t(self, entity): return type(entity) # 返回实体的类型 @@ -115,7 +149,7 @@ class SuidRich(Suid): sql, params = self.objToSQL.toSelectSQLWithPaging(entity, start, size) Logger.logsql("select_paging SQL:", sql) super().log_params(params) - list_r= self.beeSql.select(sql, self.to_class_t(entity), params) + list_r = self.beeSql.select(sql, self.to_class_t(entity), params) return list_r except Exception as e: raise BeeException(e) @@ -129,7 +163,7 @@ class SuidRich(Suid): return 0 try: - super().doBeforePasreListEntity(entity_list) + super().doBeforePasreListEntity(entity_list, SuidType.INSERT) sql, list_params = self.objToSQL.toInsertBatchSQL(entity_list) Logger.logsql("insert batch SQL:", sql) super().log_params(list_params) @@ -137,7 +171,7 @@ class SuidRich(Suid): except Exception as e: raise BeeException(e) finally: - super().doBeforeReturn() + super().doBeforeReturnSimple() def select_first(self, entity): # listT = self.select_paging(entity, 0, 2) @@ -213,6 +247,44 @@ class SuidRich(Suid): r = self.count(entity) return r > 0 + # /** + # * Update record according to whereFields. + # * @param entity table's entity(do not allow null). + # *
Fields that are not specified as whereFields, as part of the set(only non empty and non null fields + # *
are processed by default). + # * @param condition Condition as filter the record. + # * @param whereFields As a field list of where part in SQL, multiple fields can separated by commas in one + # *
whereField parameter or use variable parameter (the fields in the list will be used as where filter) + # *
But if id's value is null can not as filter. + # *
Notice:the method op of condition also maybe converted to the where expression. + # * @return the numbers of update record(s) successfully,if fails, return integer less than 0. + # * @since 1.6.0 + # */ + def updateBy(self, entity, condition: Condition=None, *whereFields): + if entity is None: + return None + + print(len(whereFields)) + print(type(whereFields)) + if whereFields is None or len(whereFields) == 0 or (len(whereFields) == 1 and (not whereFields[0] or whereFields[0].isspace())): + raise ParamBeeException("whereFields at least include one field.") + + try: + super().doBeforePasreEntity(entity, SuidType.UPDATE) + sql, params = self.objToSQL.toUpdateBySQL2(entity, condition, whereFields) + Logger.logsql("updateBy SQL:", sql) + super().log_params(params) + return self.beeSql.modify(sql, params) + except Exception as e: + raise BeeException(e) + finally: + super().doBeforeReturnSimple() + + # since 1.6.0 + # * @param entity table's entity(do not allow null). + # *
If the field of entity is not null or empty, it will be translate to field=value in where part.Other can define with condition. + # def update3(self, entity, condition: Condition=None, *updateFields): + def create_table(self, entityClass, is_drop_exist_table=None): if is_drop_exist_table: sql0 = self.objToSQL.toDropTableSQL(entityClass) @@ -254,6 +326,7 @@ class PreparedSql(AbstractCommOperate): """ eg: """ + def select(self, sql, return_type_class, params=None, start=None, size=None): if sql is None: return None @@ -264,17 +337,16 @@ class PreparedSql(AbstractCommOperate): Logger.logsql("select SQL(PreparedSql):", sql) super().log_params(params) - return self.beeSql.select(sql, return_type_class, params) # 返回值用到泛型 + return self.beeSql.select(sql, return_type_class, params) except Exception as e: raise BeeException(e) - - """ eg: preparedSql=PreparedSql() entity_list =preparedSql.select_dict("SELECT * FROM orders WHERE name=#{name} and id=#{id} and name=#{name}", Orders, params_dict ={"name":"bee1","id":4}) """ + def select_dict(self, sql, return_type_class, params_dict=None, start=None, size=None): if params_dict: sql, params_dict = SqlUtil.transform_sql(sql, params_dict) @@ -286,6 +358,7 @@ class PreparedSql(AbstractCommOperate): params = ('bee130', 'test-update', 1) updateNum = preparedSql.modify(sql, params) """ + # def modify(self, sql: str, params=None) -> int: def modify(self, sql, params=None): try: @@ -307,7 +380,6 @@ class PreparedSql(AbstractCommOperate): sql, params_dict = SqlUtil.transform_sql(sql, params_dict) return self.modify(sql, params_dict) - def __init__(self): super().__init__() self._beeSql = None diff --git a/src/bee/condition.py b/src/bee/condition.py new file mode 100644 index 0000000..3f4b8f8 --- /dev/null +++ b/src/bee/condition.py @@ -0,0 +1,424 @@ +from abc import ABC, abstractmethod +from typing import List, Any + +from bee.context import HoneyContext +from bee.exception import ParamBeeException, BeeErrorGrammarException +from bee.name.naming_handler import NamingHandler +from bee.osql.enum import FunctionType, Op, OrderType, SuidType +from bee.osql.logger import Logger +from bee.osql.sqlkeyword import K + +#since 1.6.0 +class Expression: + + def __init__(self, field_name: str=None, Op: Op=None, op_type=None, value: Any=None, + op_num: int=None, value2: Any=None, value3: Any=None, value4: Any=None): + self.field_name = field_name + self.op_type = op_type if op_type else Op.get_name() if Op else None + self.op = Op + self.value = value + self.op_num = op_num # if op_num is not None else 2 # Default for binary operations + self.value2 = value2 + self.value3 = value3 + self.value4 = value4 + + def __str__(self): + if self.op_num == 2: # Binary operation + return f"{self.field_name} {self.op} {self.value}" + else: + return str(self.__dict__) + + +class PreparedValue: + + def __init__(self, typeStr: str, value: Any): + self.typeStr = typeStr + self.value = value + + def __repr__(self): + return str(self.__dict__) + + +class ConditionStruct: + + def __init__(self, where: str, pv: List[PreparedValue], values: List, suidType:SuidType, selectFields:str, start:int, size:int, has_for_update:bool): + self.where = where + self.pv = pv + self.values = values + self.selectFields = selectFields + self.start = start + self.size = size + self.suidType = suidType + self.has_for_update = has_for_update + + def __repr__(self): + return str(self.__dict__) + + +class Condition(ABC): + + @abstractmethod + def op(self, field: str, Op: Op, value: Any) -> 'Condition': + pass + + @abstractmethod + def opWithField(self, field: str, op: Op, field2: str) -> 'Condition': + pass + + @abstractmethod + def and_(self) -> 'Condition': + pass + + @abstractmethod + def or_(self) -> 'Condition': + pass + + @abstractmethod + def not_(self) -> 'Condition': + pass + + @abstractmethod + def l_parentheses(self) -> 'Condition': + pass + + @abstractmethod + def r_parentheses(self) -> 'Condition': + pass + + @abstractmethod + def between(self, field: str, low: Any, high: Any) -> 'Condition': + pass + + @abstractmethod + def groupBy(self, field:str) -> 'Condition': + pass + + @abstractmethod + def having(self, functionType:FunctionType, field: str, op: Op, value: Any) -> 'Condition': + pass + + @abstractmethod + def orderBy(self, field:str) -> 'Condition': + pass + + @abstractmethod + def orderBy2(self, field:str) -> 'Condition': + pass + + @abstractmethod + def orderBy3(self, field:str) -> 'Condition': + pass + + @abstractmethod + def selectField(self, *field:str) -> 'Condition': + pass + + @abstractmethod + def forUpdate(self) -> 'Condition': + pass + + @abstractmethod + def start(self, start:int) -> 'Condition': + pass + + @abstractmethod + def size(self, size:int) -> 'Condition': + pass + + @abstractmethod + def suidType(self, suidType:SuidType) -> 'Condition': + pass + + @abstractmethod + def getSuidType(self) -> 'Condition': + pass + + +class ConditionImpl(Condition): + + def __init__(self): + self.expressions = [] # List of Expression objects + self.where_fields = set() # Fields used in WHERE clause + self.__isStartOrderBy = True # 实例变量 + self.__isStartGroupBy = True + self.__isStartHaving = True + self.__suidType = SuidType.SELECT + + def __check_field(self, field): + pass # TODO + + def op(self, field: str, Op: Op, value: Any) -> 'ConditionImpl': + self.__check_field(field) + exp = Expression(field_name=field, Op=Op, value=value, op_num=2) + self.expressions.append(exp) + self.where_fields.add(field) + return self + + def and_(self) -> 'ConditionImpl': + exp = Expression(op_type=K.and_(), op_num=1) + self.expressions.append(exp) + return self + + def or_(self) -> 'ConditionImpl': + exp = Expression(op_type=K.or_(), op_num=1) + self.expressions.append(exp) + return self + + def not_(self) -> 'ConditionImpl': + exp = Expression(op=Op.eq, op_type=K.not_(), op_num=1) + self.expressions.append(exp) + return self + + def l_parentheses(self) -> 'ConditionImpl': + exp = Expression(value="(", op_num=-2) + self.expressions.append(exp) + return self + + def r_parentheses(self) -> 'ConditionImpl': + exp = Expression(value=")", op_num=-1) + self.expressions.append(exp) + return self + + def between(self, field: str, low: Any, high: Any) -> 'ConditionImpl': + self.__check_field(field) + exp = Expression(field_name=field, op_type=K.between(), value=low, value2=high, op_num=3) + self.expressions.append(exp) + self.where_fields.add(field) + return self + + def opWithField(self, field: str, op: Op, field2: str) -> 'ConditionImpl': + self.__check_field(field) + self.__check_field(field2) + expr = Expression(field_name=field, Op=op, value=field2, op_num=-3) + self.expressions.append(expr) + self.where_fields.add(field) + return self + + # 'forUpdate', 'groupBy', 'orderBy', 'selectField', 'size', 'start' + + def groupBy(self, field:str) -> 'Condition': + self.__check_field(field) + exp = Expression(field_name=field, op_type=K.group_by(), op_num=-4) + + if self.__isStartGroupBy: + self.__isStartGroupBy = False + exp.value = K.group_by() + else: + exp.value = self.COMMA + self.expressions.append(exp) + return self + + # having(FunctionType.MIN, "field", Op.ge, 60)-->having min(field)>=60 + def having(self, functionType:FunctionType, field: str, op: Op, value: Any) -> 'Condition': + self.__check_field(field) + exp = Expression(field_name=field, Op=op, value=value, op_num=5) + exp.value2 = functionType + + if self.__isStartHaving: + if self.__isStartGroupBy: + Logger.warn("The 'having' must be after 'group by'!") + self.__isStartHaving = False + exp.op_type = K.having() + else: + exp.op_type = K.and_() + + self.expressions.append(exp) + self.where_fields.add(field) + return self + + __COMMA = "," + + def orderBy(self, field:str) -> 'Condition': + self.__check_field(field) + exp = Expression(field_name=field, op_type=K.order_by(), op_num=12) + self.expressions.append(exp) + if self.__isStartOrderBy: + self.__isStartOrderBy = False + exp.value = K.order_by() + else: + exp.value = self.__COMMA + return self + + def orderBy2(self, field:str, orderType:OrderType) -> 'Condition': + self.__check_field(field) + exp = Expression(field_name=field, op_type=K.order_by(), op_num=13) + exp.value2 = orderType.get_name() + self.expressions.append(exp) + if self.__isStartOrderBy: + self.__isStartOrderBy = False + exp.value = K.order_by() + else: + exp.value = self.__COMMA + return self + + def orderBy3(self, functionType:FunctionType, field:str, orderType:OrderType) -> 'Condition': + self.__check_field(field) + exp = Expression(field_name=field, op_type=K.order_by(), op_num=14) + exp.value2 = orderType.get_name() + exp.value3 = functionType.get_name() + self.expressions.append(exp) + if self.__isStartOrderBy: + self.__isStartOrderBy = False + exp.value = K.order_by() + else: + exp.value = self.__COMMA + return self + + def selectField(self, *fields:str) -> 'Condition': + self.__check_field(fields) + exp = Expression(value=fields, op_num=20) + self.expressions.append(exp) + return self + + def start(self, start:int) -> 'Condition': + if start is None or start < 0: # if not 0: is True + raise ParamBeeException("Parameter 'start' need >=0 .") + exp = Expression(value=start, op_num=21) + self.expressions.append(exp) + return self + + def size(self, size:int) -> 'Condition': + if not size or size <= 0: + raise ParamBeeException("Parameter 'size' need >0 .") + + exp = Expression(value=size, op_num=22) + self.expressions.append(exp) + return self + + def suidType(self, suidType:SuidType) -> 'Condition': + self.__suidType = suidType + return self + + #get + def getSuidType(self) -> 'Condition': + return self.__suidType + + def forUpdate(self) -> 'Condition': + exp = Expression(op_type=K.for_update(), op_num=30) + self.expressions.append(exp) + return self + + # parse + def parseCondition(self) -> ConditionStruct: + return ParseCondition.parse(self.expressions, self) + + +class ParseCondition: + + @staticmethod + def __getPlaceholder() -> str: + return HoneyContext.get_placeholder() + + @staticmethod + def parse(expressions, condition:Condition) -> ConditionStruct: + where_clauses = [] + prepared_values = [] + values = [] + + is_need_and = False + suidType = condition.getSuidType() + + def adjust_and() -> bool: + nonlocal is_need_and + if is_need_and: + where_clauses.append(" " + K.and_() + " ") + is_need_and = False + # return False + return is_need_and + + ph = ParseCondition.__getPlaceholder() + + __has_for_update = False + __selectFields = None + __start = None + __size = None + for exp in expressions: + # exp.field_name ->column_name + column_name = NamingHandler.toColumnName(exp.field_name) + if exp.op_num == 2: # Binary operation + is_need_and = adjust_and() + if exp.value is None: + where_clause = f"{column_name} {K.isnull()}" + else: + where_clause = f"{column_name} {exp.op} {ph}" + prepared_values.append(PreparedValue(type(exp.value), exp.value)) + values.append(exp.value) + where_clauses.append(where_clause) + is_need_and = True + elif exp.op_num == 3: # BETWEEN + is_need_and = adjust_and() + where_clause = f"{column_name} {exp.op_type} {ph} {K.and_()} {ph}" + where_clauses.append(where_clause) + prepared_values.append(PreparedValue(type(exp.value), exp.value)) + prepared_values.append(PreparedValue(type(exp.value), exp.value2)) + values.append(exp.value) + values.append(exp.value2) + is_need_and = True + elif exp.op_num == -3: # eg:field1=field2 + is_need_and = adjust_and() + where_clause = f"{column_name} {exp.op} {exp.value}" + where_clauses.append(where_clause) + is_need_and = True + elif exp.op_num == -4: # group by + if suidType != SuidType.SELECT: + raise BeeErrorGrammarException(suidType.get_name() + " do not support 'group by' !") + + where_clause = f" {exp.value} {column_name}" + where_clauses.append(where_clause) + + elif exp.op_num == 5: # having + if suidType != SuidType.SELECT: + raise BeeErrorGrammarException(suidType.get_name() + " do not support 'having' !") + + where_clause = f" {exp.op_type} {exp.value2.get_name()}({column_name}) {exp.op} {ph}" + where_clauses.append(where_clause) + prepared_values.append(PreparedValue(type(exp.value), exp.value)) + values.append(exp.value) + + elif exp.op_num == 12 or exp.op_num == 13 or exp.op_num == 14: # order by + if suidType != SuidType.SELECT: + raise BeeErrorGrammarException(suidType.get_name() + " do not support 'order by' !") + + where_clauses.append(" " + exp.value + " ") # order by或者, + if 14 == exp.op_num: # order by max(total) + where_clauses.append(exp.value3) + where_clauses.append("(") + where_clauses.append(column_name) + where_clauses.append(")") + else: + where_clauses.append(column_name) + + if 13 == exp.op_num or 14 == exp.op_num: # 指定 desc,asc + where_clauses.append(" "); + where_clauses.append(exp.value2) + + elif exp.op_num == 1: # Logical operator (AND, OR, NOT) + if exp.op_type == K.not_(): + is_need_and = adjust_and() + where_clauses.append(f" {exp.op_type} ") + is_need_and = False + elif exp.op_num == -2: # Left parenthesis + is_need_and = adjust_and() + where_clauses.append("(") + elif exp.op_num == -1: # Right parenthesis + where_clauses.append(")") + is_need_and = True + + elif exp.op_num == 20: + __selectFields = exp.value + + elif exp.op_num == 21: + __start = exp.value + elif exp.op_num == 22: + __size = exp.value + + elif exp.op_num == 30: # for update TODO + __has_for_update = True + else: + Logger.warn(f"Unknown operation number: {exp.op_num}") + + # Join all where clauses into a single string + where_clause_str = "".join(where_clauses) + + return ConditionStruct(where_clause_str, prepared_values, values, suidType, __selectFields, __start, __size, __has_for_update) + diff --git a/src/bee/config.py b/src/bee/config.py index 1753128..e76f455 100644 --- a/src/bee/config.py +++ b/src/bee/config.py @@ -78,6 +78,9 @@ class HoneyConfig: try: config_file = cls.__adjust_config_file(cls, config_file) + if not os.path.isfile(config_file): + Logger.info("Not found the file bee.properties!") + return with open(config_file, 'r') as file: cls._loaded = True # 设置为已加载 Logger.info("Loading config file: " + config_file) @@ -140,7 +143,7 @@ class HoneyConfig: if path_separator not in t_database: root_dir = PreConfig.config_path newPath = root_dir + path_separator + t_database - Logger.warn("adjust the SQLite db file path to: " + newPath) + Logger.info("adjust the SQLite db file path to: " + newPath) if not os.path.isfile(newPath): raise ConfigBeeException(f"File not found in current path or adjust path: {newPath}") cls.__db_config_data['database'] = newPath diff --git a/src/bee/exception.py b/src/bee/exception.py index d28ffef..b5a6cdc 100644 --- a/src/bee/exception.py +++ b/src/bee/exception.py @@ -46,6 +46,8 @@ class ConfigBeeException(BeeException): ... class SqlBeeException(BeeException): ... +class ParamBeeException(BeeException): ... + class BeeErrorNameException(BeeException): ... -class ParamBeeException(BeeException): ... +class BeeErrorGrammarException(BeeException): ... diff --git a/src/bee/factory.py b/src/bee/factory.py index 1ce33fd..f2cc18e 100644 --- a/src/bee/factory.py +++ b/src/bee/factory.py @@ -1,10 +1,13 @@ -from bee.osql.honeyfactory import HoneyFactory +# from bee.honeyfactory import HoneyFactory +from bee.name.naming import * + class BeeFactory: __connection = None __instance = None + __honeyFactory=None def __new__(cls): if cls.__instance is None: @@ -17,11 +20,31 @@ class BeeFactory: def get_connection(self): return BeeFactory.__connection + + __nameTranslate = None + + def getInitNameTranslate(self) -> NameTranslate: + + if self.__nameTranslate is None: + # int translateType=HoneyConfig.getHoneyConfig().naming_translateType; + translateType = 1 # TODO from config + if translateType == 1: __nameTranslate = UnderScoreAndCamelName() + elif translateType == 2: __nameTranslate = UpperUnderScoreAndCamelName() + elif translateType == 3: __nameTranslate = OriginalName() + elif translateType == 4: __nameTranslate = DbUpperAndJavaLower() + else:__nameTranslate = UnderScoreAndCamelName() + + return __nameTranslate; + # def __getattribute__(self, item): # print(f"Accessing attribute: {item}") # return super().__getattribute__(item) + # def getHoneyFactory(self): + # if self.__honeyFactory is None: + # __honeyFactory = HoneyFactory() + # return __honeyFactory + + + - def getHoneyFactory(self): - return HoneyFactory() - \ No newline at end of file diff --git a/src/bee/honeyfactory.py b/src/bee/honeyfactory.py new file mode 100644 index 0000000..b3e993e --- /dev/null +++ b/src/bee/honeyfactory.py @@ -0,0 +1,104 @@ +from bee.api import Suid, SuidRich, PreparedSql +from bee.obj2sql import ObjToSQL +from bee.sqllib import BeeSql +from bee.condition import ConditionImpl +class HoneyFactory: + + __instance = None + + def __new__(cls): + if cls.__instance is None: + cls.__instance = super().__new__(cls) + return cls.__instance + + def __init__(self): + self.suid = None + self.suidRich = None + self.beeSql = None + self.objToSQL = None + self.objToSQLRich = None + self.preparedSql = None + self.callableSql = None + self.condition = None + + def getSuid(self): + if self.suid is None: + return Suid() + return self.suid + + def setSuid(self, suid): + self.suid = suid + + def getSuidRich(self): + if self.suidRich is None: + return SuidRich() + return self.suidRich + + def setSuidRich(self, suidRich): + self.suidRich = suidRich + + def getBeeSql(self): + if self.beeSql is None: + return BeeSql() + return self.beeSql + + def setBeeSql(self, beeSql): + self.beeSql = beeSql + + def getObjToSQL(self): + if self.objToSQL is None: + return ObjToSQL() + return self.objToSQL + + def setObjToSQL(self, objToSQL): + self.objToSQL = objToSQL + + # def getObjToSQLRich(self): + # if self.objToSQLRich is None: + # return ObjectToSQLRich() + # return self.objToSQLRich + # + # def setObjToSQLRich(self, objToSQLRich): + # self.objToSQLRich = objToSQLRich + + def getPreparedSql(self): + if self.preparedSql is None: + return PreparedSql() + return self.preparedSql + + def setPreparedSql(self, preparedSql): + self.preparedSql = preparedSql + + # def getCallableSql(self): + # if self.callableSql is None: + # return CallableSqlLib() + # return self.callableSql + # + # def setCallableSql(self, callableSql): + # self.callableSql = callableSql + + def getCondition(self): + if self.condition is None: + return ConditionImpl() + return self.condition + + def setCondition(self, condition): + if condition is not None: + self.condition = condition.clone() + else: + self.condition = condition + + +class BF: + + @staticmethod + def suid(): + return HoneyFactory().getSuid() + + @staticmethod + def suidRich(): + return HoneyFactory().getSuidRich() + + @staticmethod + def condition(): + return HoneyFactory().getCondition() diff --git a/src/bee/name/naming_handler.py b/src/bee/name/naming_handler.py index 4601f21..db73cec 100644 --- a/src/bee/name/naming_handler.py +++ b/src/bee/name/naming_handler.py @@ -8,7 +8,7 @@ class NamingHandler: def getNameTranslate() -> NameTranslate: # TODO 下一步,要支持使用实时命名规则 factory = BeeFactory() - return factory.getHoneyFactory().getInitNameTranslate() + return factory.getInitNameTranslate() @staticmethod def toTableName(entityName) -> str: diff --git a/src/bee/obj2sql.py b/src/bee/obj2sql.py index 89cd5e9..78d0081 100644 --- a/src/bee/obj2sql.py +++ b/src/bee/obj2sql.py @@ -1,14 +1,16 @@ +from bee import SqlUtil from bee.config import HoneyConfig from bee.context import HoneyContext -from bee.exception import SqlBeeException +from bee.exception import SqlBeeException, ParamBeeException from bee.name import NameCheckUtil +from bee.name.naming_handler import NamingHandler from bee.osql.const import DatabaseConst, SysConst +from bee.osql.enum import SuidType from bee.osql.logger import Logger from bee.osql.sqlkeyword import K -from bee.paging import Paging from bee.util import HoneyUtil -from bee.name.naming_handler import NamingHandler +from bee.condition import Condition class ObjToSQL: @@ -19,11 +21,16 @@ class ObjToSQL: table_name = HoneyUtil.get_table_name(entity) return self.__build_select_sql(table_name, classField, fieldAndValue) + def toSelectSQL2(self, entity, condition: Condition): + fieldAndValue, classField = self.__getKeyValue_classField(entity) + + table_name = HoneyUtil.get_table_name(entity) + return self.__build_select_sql2(table_name, classField, fieldAndValue, condition) + def toSelectSQLWithPaging(self, entity, start, size): sql, params = self.toSelectSQL(entity) - paging = Paging() - sql = paging.to_page_sql(sql, start, size) + sql = SqlUtil.add_paging(sql, start, size) return sql, params def toUpdateSQL(self, entity): @@ -44,7 +51,27 @@ class ObjToSQL: table_name = HoneyUtil.get_table_name(entity) return self.__build_update_sql(table_name, fieldAndValue, conditions) + def toUpdateBySQL2(self, entity, condition, whereFields): + + # fieldAndValue = self.__getKeyValue(entity) + fieldAndValue, classField = self.__getKeyValue_classField(entity) + # print(type(whereFields)) + # print(type(classField)) + # whereFields=list(whereFields) + ext=list(set(whereFields) - set(classField)) + # print(whereFields) + # print(classField) + + # ext=whereFields-classField + # print(ext) + + if ext: + raise ParamBeeException("some fields in whereFields not in bean: ", ext) + + table_name = HoneyUtil.get_table_name(entity) + return self.__build_update_by_sql2(table_name, fieldAndValue, condition, whereFields) + def toInsertSQL(self, entity): table_name = HoneyUtil.get_table_name(entity) fieldAndValue = self.__getKeyValue(entity) @@ -56,6 +83,11 @@ class ObjToSQL: fieldAndValue = self.__getKeyValue(entity) return self.__build_delete_sql(table_name, fieldAndValue) + def toDeleteSQL2(self, entity, condition): + table_name = HoneyUtil.get_table_name(entity) + fieldAndValue = self.__getKeyValue(entity) + return self.__build_delete_sql2(table_name, fieldAndValue, condition) + def toInsertBatchSQL(self, entity_list): table_name = HoneyUtil.get_table_name(entity_list[0]) # fieldAndValue = self.__getKeyValue(entity_list[0]) @@ -164,17 +196,18 @@ class ObjToSQL: def __getPlaceholder(self): return HoneyContext.get_placeholder() - - def __build_update_sql(self, table_name, set_dict, conditions): + #updateById + def __build_update_sql(self, table_name, set_dict, entityFilter): + # entityFilter just pk if not set_dict: raise SqlBeeException("Update SQL's set part is empty!") - # if not conditions: #还没有用到 + # if not entityFilter: #还没有用到 # Logger.warn("Update SQL's where part is empty, would update all records!") set_dict2 = self.__toColumns_with_dict(set_dict) - conditions2 = self.__toColumns_with_dict(conditions) + conditions2 = self.__toColumns_with_dict(entityFilter) ph=self.__getPlaceholder() if self.__getPlaceholderType() == 3: @@ -223,20 +256,20 @@ class ObjToSQL: def __toColumns_with_dict(self, kv): return {NamingHandler.toColumnName(k):v for k, v in kv.items()} - def __build_where_condition(self, conditions): - conditions2 = self.__toColumns_with_dict(conditions) + def __build_where_condition(self, entityFilter): + entityFilter2 = self.__toColumns_with_dict(entityFilter) ph = self.__getPlaceholder() if self.__getPlaceholderType() == 3: - condition_str = f" {K.and_()} ".join(f"{key} = {ph}{key}" for key in conditions2.keys()) + condition_str = f" {K.and_()} ".join(f"{key} = {ph}{key}" for key in entityFilter2.keys()) else: - condition_str = f" {K.and_()} ".join(f"{key} = {ph}" for key in conditions2.keys()) + condition_str = f" {K.and_()} ".join(f"{key} = {ph}" for key in entityFilter2.keys()) return condition_str def __toColumns(self, classField): return [NamingHandler.toColumnName(field) for field in classField] - def __build_select_sql(self, table_name, classField, conditions=None): + def __build_select_sql(self, table_name, classField, entityFilter=None): if not classField: raise SqlBeeException("column list is empty!") @@ -247,29 +280,153 @@ class ObjToSQL: #where part params = [] - if conditions: - condition_str=self.__build_where_condition(conditions) + if entityFilter: + condition_str=self.__build_where_condition(entityFilter) sql += f" {K.where()} {condition_str}" - params = list(conditions.values()) + params = list(entityFilter.values()) return sql, params - def __build_select_by_id_sql(self, table_name, classField, where_condition_str): - if not classField: + def __build_select_sql2(self, table_name, classField, entityFilter=None, condition=None): + + if condition: + conditionStruct=condition.parseCondition() + selectFields=conditionStruct.selectFields + + if not selectFields and not classField: raise SqlBeeException("column list is empty!") - columns = self.__toColumns(classField) + if selectFields: + columns=self.__toColumns(selectFields) # TODO + else: + columns=self.__toColumns(classField) + sql = f"{K.select()} {', '.join(columns)} {K.from_()} {table_name}" - return sql + where_condition_str - - def __build_delete_sql(self, table_name, conditions): + + #where part + params = [] + if entityFilter: + condition_str=self.__build_where_condition(entityFilter) + sql += f" {K.where()} {condition_str}" + params = list(entityFilter.values()) + + if conditionStruct: + # condition_where=conditionStruct.where + # if condition_where: + # values=conditionStruct.values + # if entityFilter: + # sql += " "+ K.and_() + # else: + # sql +=" "+ K.where() + # sql +=" "+condition_where + # params = params + values + sql,params=self.__appendWhere(sql, params, entityFilter, conditionStruct) + start = conditionStruct.start + size = conditionStruct.size + if start or size: + sql = SqlUtil.add_paging(sql, start, size) + if conditionStruct.has_for_update: + sql += " " + K.for_update() + + return sql, params + + def __appendWhere(self,sql,params,entityFilter,conditionStruct): + if conditionStruct: + condition_where=conditionStruct.where + if condition_where: + values=conditionStruct.values + if entityFilter: + sql += " "+ K.and_() + else: + sql +=" "+ K.where() + sql +=" "+condition_where + params = params + values + return sql,params + + def __build_delete_sql2(self, table_name, entityFilter, condition=None): sql = f"{K.delete()} {K.from_()} {table_name}" params = [] - if conditions: - condition_str=self.__build_where_condition(conditions) + if entityFilter: + condition_str=self.__build_where_condition(entityFilter) sql += f" {K.where()} {condition_str}" - params = list(conditions.values()) + params = list(entityFilter.values()) + + if condition: + condition.suidType(SuidType.DELETE) + conditionStruct=condition.parseCondition() + sql,params=self.__appendWhere(sql, params, entityFilter, conditionStruct) + return sql, params + def __build_update_by_sql2(self, table_name, entityFilter, condition, whereFields): + + where_dict = {} + set_dict = {} + for key, value in entityFilter.items(): + if key in whereFields: + where_dict[key] = value + else: + set_dict[key] = value + + if not set_dict: + raise SqlBeeException("Update SQL's set part is empty!") + + no_value_filter = set(whereFields) - set(where_dict) + # print(no_value_filter) + + if condition: + condition.suidType(SuidType.UPDATE) + conditionStruct=condition.parseCondition() + where=conditionStruct.where + if not where_dict and not where: + Logger.warn("Update SQL's where part is empty, would update all records!") + + set_dict2 = self.__toColumns_with_dict(set_dict) + conditions2 = self.__toColumns_with_dict(where_dict) + + ph=self.__getPlaceholder() + if self.__getPlaceholderType() == 3: + updateSet = ', '.join(f"{key} = {ph}{key}" for key in set_dict2.keys()) + condition_str = f" {K.and_()} ".join(f"{key} = {ph}{key}" for key in conditions2.keys()) + else: + updateSet = ', '.join(f"{key} = {ph}" for key in set_dict2.keys()) + condition_str = f" {K.and_()} ".join(f"{key} = {ph}" for key in conditions2.keys()) + + if no_value_filter: + no_value_filter2 = self.__toColumns(no_value_filter) + if condition_str: + condition_str+=" " +{K.and_()} + condition_str += f" {K.and_()} ".join(f"{key} {K.isnull()}" for key in no_value_filter2) + + # sql = f"UPDATE {table_name} SET {updateSet} WHERE {condition_str}" + if condition_str: + sql = f"{K.update()} {table_name} {K.set()} {updateSet} {K.where()} {condition_str}" + else: + sql = f"{K.update()} {table_name} {K.set()} {updateSet}" + params = list(set_dict2.values()) + list(conditions2.values()) + + if where: + sql,params=self.__appendWhere(sql, params, whereFields, conditionStruct) + + return sql, params + + + def __build_select_by_id_sql(self, table_name, classField, where_condition_str): + if not classField: + raise SqlBeeException("column list is empty!") + + columns = self.__toColumns(classField) + sql = f"{K.select()} {', '.join(columns)} {K.from_()} {table_name}" + return sql + where_condition_str + + def __build_delete_sql(self, table_name, entityFilter): + # sql = f"{K.delete()} {K.from_()} {table_name}" + # params = [] + # if entityFilter: + # condition_str=self.__build_where_condition(entityFilter) + # sql += f" {K.where()} {condition_str}" + # params = list(entityFilter.values()) + # return sql, params + return self.__build_delete_sql2(table_name, entityFilter, None) def __build_delete_by_id_sql(self, table_name, where_condition_str): sql = f"{K.delete()} {K.from_()} {table_name}" diff --git a/src/bee/osql/enum.py b/src/bee/osql/enum.py index fa21211..753e906 100644 --- a/src/bee/osql/enum.py +++ b/src/bee/osql/enum.py @@ -1,6 +1,20 @@ from enum import Enum +from bee.config import PreConfig + +# class EnumCaseMeta(EnumMeta): +# def __getattribute__(self, name): +# value = super().__getattribute__(name) +# if isinstance(value, self._enum_type_): +# enum_member = value +# if PreConfig.sql_key_word_case == "upper": +# return enum_member._name_ +# else: +# return enum_member._name_.lower() +# return value + +# class FunctionType(Enum, metaclass=EnumCaseMeta): class FunctionType(Enum): MAX = "max" MIN = "min" @@ -8,8 +22,13 @@ class FunctionType(Enum): AVG = "avg" COUNT = "count" + # def get_name(self): + # return self.value def get_name(self): - return self.value + if PreConfig.sql_key_word_case == "upper": + return self.value.upper() + else: + return self.value.lower() class SuidType(Enum): @@ -27,7 +46,46 @@ class SuidType(Enum): # def getType(self): # 为了更贴近 Java 的 getter 方法命名 # return self.type - @property # 或者使用 property 装饰器 - def type_value(self): - return self.type + # @property # 或者使用 property 装饰器 + def get_name(self): + return self.value + + +class OrderType(Enum): + ASC = "asc" + DESC = "desc" + + # def get_name(self): + # return self.value + def get_name(self): + if PreConfig.sql_key_word_case == "upper": + return self.value.upper() + else: + return self.value.lower() + + def __str__(self): + return self.get_name() + +class Op(Enum): + eq = "=" + gt = ">" + lt = "<" + ne = "!=" + ge = ">=" + le = "<=" + like = " like " + like_left = " like " + like_right = " like " + like_left_right = " like " + # not_like = " not like " + in_ = " in" + not_in = " not in" + # is_null = "IS NULL" + # is_not_null = "IS NOT NULL" + + def get_name(self): + return self.value + + def __str__(self): + return self.get_name() diff --git a/src/bee/osql/honeyfactory.py b/src/bee/osql/honeyfactory.py deleted file mode 100644 index b267f99..0000000 --- a/src/bee/osql/honeyfactory.py +++ /dev/null @@ -1,20 +0,0 @@ -from bee.name.naming import NameTranslate, UnderScoreAndCamelName, \ - UpperUnderScoreAndCamelName, OriginalName, DbUpperAndJavaLower - - -class HoneyFactory: - - __nameTranslate = None - - def getInitNameTranslate(self) -> NameTranslate: - - if self.__nameTranslate is None: - # int translateType=HoneyConfig.getHoneyConfig().naming_translateType; - translateType = 1 # TODO from config - if translateType == 1: __nameTranslate = UnderScoreAndCamelName() - elif translateType == 2: __nameTranslate = UpperUnderScoreAndCamelName() - elif translateType == 3: __nameTranslate = OriginalName() - elif translateType == 4: __nameTranslate = DbUpperAndJavaLower() - else:__nameTranslate = UnderScoreAndCamelName() - - return __nameTranslate; diff --git a/src/bee/sqllib.py b/src/bee/sqllib.py index 8df096d..5bda526 100644 --- a/src/bee/sqllib.py +++ b/src/bee/sqllib.py @@ -25,7 +25,7 @@ class BeeSql: # 将行数据映射到新创建的实体对象 target_obj = HoneyUtil.transform_result(row, column_names, entityClass) rs_list.append(target_obj) - + Logger.info(" | <-- select rows: " + str(len(rs_list))) except Exception as e: raise SqlBeeException(e) finally: @@ -37,11 +37,14 @@ class BeeSql: # def modify(self, sql: str, params=None) -> int: def modify(self, sql, params=None): conn = self.__getConn() + a = 0 try: cursor = conn.cursor() cursor.execute(sql, params or []) conn.commit() - return cursor.rowcount # 返回受影响的行数 + a = cursor.rowcount # 返回受影响的行数 + Logger.info(" | <-- Affected rows: " + str(a)) + return a except Exception as e: Logger.error(f"Error in modify: {e}") conn.rollback() @@ -51,11 +54,14 @@ class BeeSql: def batch(self, sql, params=None): conn = self.__getConn() + a = 0 try: cursor = conn.cursor() cursor.executemany(sql, params or []) conn.commit() - return cursor.rowcount # 返回受影响的行数 + a = cursor.rowcount # 返回受影响的行数 + Logger.info(" | <-- Affected rows: " + str(a)) + return a except Exception as e: Logger.error(f"Error in batch: {e}") conn.rollback() @@ -71,7 +77,9 @@ class BeeSql: try: cursor = conn.cursor() cursor.execute(sql, params or []) - result = cursor.fetchone() # 返回一个元组,例如 (1,) + result = cursor.fetchone() # 返回一个元组,例如 (1,) + if result[0]: + Logger.info(" | <-- select rows: 1" ) return result[0] except Exception as e: diff --git a/tests/exam/BatchInsertTest.py b/tests/exam/BatchInsertTest.py index 669f628..b2f3eea 100644 --- a/tests/exam/BatchInsertTest.py +++ b/tests/exam/BatchInsertTest.py @@ -26,15 +26,31 @@ if __name__ == '__main__': student0=Student2() student0.name = "bee" + student0.age=20 + student0.remark= "bee" student1=Student2() student1.name = "bee1" student1.addr="" - student1.age=40 + student1.age=22 + student1.remark= "bee1" + + student2=Student2() + student2.name = "黄二" + student2.addr="" + student2.age=21 + + student3=Student2() + student3.name = "张三" + student3.addr="" + student3.age=21 + entity_list=[] entity_list.append(student0) entity_list.append(student1) + entity_list.append(student2) + entity_list.append(student3) suidRich = SuidRich() insertNum = suidRich.insert_batch(entity_list) diff --git a/tests/exam15/ByIdTest.py b/tests/exam15/ByIdTest.py index 2bb2bc9..0542220 100644 --- a/tests/exam15/ByIdTest.py +++ b/tests/exam15/ByIdTest.py @@ -15,7 +15,8 @@ if __name__ == '__main__': suidRich = SuidRich() # one = suidRich.select_by_id(orders) # 1.5.4 # one = suidRich.select_by_id(Orders,"1") #1.6.0 - one = suidRich.select_by_id(Orders,'bee') #1.6.0 + one = suidRich.select_by_id(Orders,1) + # one = suidRich.select_by_id(Orders,'bee') #1.6.0 print(one) # one = suidRich.select(orders) diff --git a/tests/exam16/SuidTest1.py b/tests/exam16/SuidTest1.py new file mode 100644 index 0000000..5bad056 --- /dev/null +++ b/tests/exam16/SuidTest1.py @@ -0,0 +1,39 @@ +# from org.teasoft.exam.entity.Orders import Orders +# from bee.api import Suid + +from bee.osql.enum import Op + +import MyConfig +from bee.honeyfactory import BF +from entity.Orders import Orders + + +# from bee.config import PreConfig +# from org.teasoft.exam.entity.Test import Test +if __name__ == '__main__': + print("start") + + MyConfig.init() + + # orders=Orders(id=1, name="bee") + orders=Orders() + # orders = Test() + # orders.id=1 + orders.name = "bee" + + suid = BF.suid() + orderList = suid.select(orders) #test + for one in orderList: + print(one) + + condition = BF.condition() + condition.op("name", Op.ne, "bee1").op("remark", Op.ne, "new2") + orderList = suid.select2(orders,condition) + for one in orderList: + print(one) + + + + + + print("finished") diff --git a/tests/exam16/SuidTest2.py b/tests/exam16/SuidTest2.py new file mode 100644 index 0000000..5336562 --- /dev/null +++ b/tests/exam16/SuidTest2.py @@ -0,0 +1,53 @@ +# from org.teasoft.exam.entity.Orders import Orders +# from bee.api import Suid +from bee.osql.enum import Op + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +# from bee.config import PreConfig +# from org.teasoft.exam.entity.Test import Test +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + # stu.name='张三' + + suid = BF.suid() + # orderList = suid.select(stu) #test + # for one in orderList: + # print(one) + + condition = BF.condition() + condition.op("name", Op.ne, "bee1").between("age", 20, 28) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + condition = BF.condition() + condition.op("name", Op.ne, "bee1").or_() + condition.l_parentheses().between("age", 20, 28).r_parentheses() + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + condition = BF.condition() + condition.opWithField("name", Op.eq, "remark") + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + # condition = BF.condition() + # condition.groupBy("name") + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + + + print("finished") diff --git a/tests/exam16/conditionTest.py b/tests/exam16/conditionTest.py new file mode 100644 index 0000000..3c8778f --- /dev/null +++ b/tests/exam16/conditionTest.py @@ -0,0 +1,68 @@ +# from org.teasoft.exam.entity.Orders import Orders +# from bee.api import Suid + +# from bee.config import PreConfig +from bee.osql.enum import Op, OrderType, FunctionType + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +# from bee.config import PreConfig +# from org.teasoft.exam.entity.Test import Test +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + # stu.name='张三' + + suid = BF.suid() + + # condition = BF.condition() + # condition.op("name", Op.ne, "bee1").between("age", 20, 28) + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + # + # + # condition = BF.condition() + # condition.op("name", Op.ne, "bee1").or_() + # condition.l_parentheses().between("age", 20, 28).r_parentheses() + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + # + # + # condition = BF.condition() + # condition.opWithField("name", Op.eq, "remark") + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + + # PreConfig.sql_key_word_case="upper" + + condition = BF.condition() + condition.selectField("name,age") + condition.op("name", Op.ne, "bee1") + condition.groupBy("name") + # having(FunctionType.MIN, "field", Op.ge, 60)-->having min(field)>=60 + condition.having(FunctionType.MIN, "age", Op.ge, 25) + condition.having(FunctionType.MAX, "age", Op.lt, 30) + condition.orderBy("name") + condition.orderBy2("age",OrderType.DESC) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + # condition = BF.condition() + # condition.groupBy("name") + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + + + print("finished") diff --git a/tests/exam16/conditionTest2.py b/tests/exam16/conditionTest2.py new file mode 100644 index 0000000..e2cfdf4 --- /dev/null +++ b/tests/exam16/conditionTest2.py @@ -0,0 +1,40 @@ +# from org.teasoft.exam.entity.Orders import Orders +# from bee.api import Suid + +# from bee.config import PreConfig +from bee.osql.enum import Op + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +# from bee.config import PreConfig +# from org.teasoft.exam.entity.Test import Test +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + # stu.name='张三' + + suid = BF.suid() + + + # empty condition + condition = BF.condition() + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + # field is null + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + print("finished") diff --git a/tests/exam16/conditionTest3_paging.py b/tests/exam16/conditionTest3_paging.py new file mode 100644 index 0000000..ba357d1 --- /dev/null +++ b/tests/exam16/conditionTest3_paging.py @@ -0,0 +1,66 @@ +from bee.osql.enum import Op + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + # stu.name='张三' + + suid = BF.suid() + + + # # empty condition + # condition = BF.condition() + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + + # field is null + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + condition.start(10).size(10) + # condition.start(5) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + # condition.start(0).size(10) + condition.start(5) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + # condition.start(0).size(10) + # condition.start(5) + condition.size(10) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + # condition.start("") + condition.size(10) + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + + print("finished") diff --git a/tests/exam16/conditionTest4_delete.py b/tests/exam16/conditionTest4_delete.py new file mode 100644 index 0000000..d1e6ab2 --- /dev/null +++ b/tests/exam16/conditionTest4_delete.py @@ -0,0 +1,53 @@ +from bee.osql.enum import Op, FunctionType + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + + suid = BF.suid() + + + # empty condition + # condition = BF.condition() + # orderList = suid.select2(stu,condition) + # for one in orderList: + # print(one) + + # field is null + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + delNum = suid.delete2(stu,condition) + print(delNum) + + + + condition = BF.condition() + condition.op("name", Op.eq, "黄二") + + orderList = suid.select2(stu,condition) + for one in orderList: + print(one) + + ##check do not support + # condition.groupBy("name") + # condition.having(FunctionType.MAX, "age", Op.lt, 30) + # condition.orderBy("name") + delNum = suid.delete2(stu,condition) + print(delNum) + + + print("finished") diff --git a/tests/exam16/conditionTest5_update.py b/tests/exam16/conditionTest5_update.py new file mode 100644 index 0000000..527c0a0 --- /dev/null +++ b/tests/exam16/conditionTest5_update.py @@ -0,0 +1,42 @@ +from bee.osql.enum import Op + +import MyConfig +from bee.honeyfactory import BF +from entity.Student2 import Student2 + + +if __name__ == '__main__': + print("start") + + MyConfig.init() + + stu=Student2() + + suidRich = BF.suidRich() + + + # field is null + condition = BF.condition() + # condition.op("remark", Op.eq, None) + condition.op("addr", Op.eq, None) + + orderList = suidRich.select2(stu,condition) + for one in orderList: + print(one) + + stu.addr="use new addr" + stu.remark="bee" + # updateNum = suidRich.updateBy(stu,condition,"remark") + # updateNum = suidRich.updateBy(stu,condition,"id") + updateNum = suidRich.updateBy(stu,condition,"name") + # updateNum = suidRich.updateBy(stu,condition) # check + # updateNum = suidRich.updateBy(stu,condition,"")# check + # updateNum = suidRich.updateBy(stu,condition," ")# check + print(updateNum) + # updateBy SQL: update student2 set addr = ?, remark = ? where name is null and addr is null + + orderList = suidRich.select(stu) + for one in orderList: + print(one) + + print("finished") -- Gitee