diff --git a/bee/__init__.py b/bee/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..20a71278b9c8d0b46aac4eaf06758c883f551c69
--- /dev/null
+++ b/bee/__init__.py
@@ -0,0 +1,17 @@
+"""
+Corresponding Java type ORM tool,
+JAVA ORM Bee:
+
+ maven:
+
+ org.teasoft
+ bee-all
+ 2.4.2
+
+
+ Gradle(Short):
+ implementation 'org.teasoft:bee-all:2.4.2'
+
+ note:the version can change to newest.
+
+"""
diff --git a/bee/api.py b/bee/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..b20e5df7c501c5d736a51d65cb0328cfd925cb1c
--- /dev/null
+++ b/bee/api.py
@@ -0,0 +1,102 @@
+from bee.obj2sql import ObjToSQL
+from bee.osql.logger import Logger
+from bee.sqllib import BeeSql
+
+
+class Suid:
+
+ def __init__(self):
+ self._beeSql = None
+ self._objToSQL = None
+
+ def select(self, entity):
+ if entity is None:
+ return None
+
+ try:
+ sql,params = self.objToSQL.toSelectSQL(entity)
+ # Logger.log_sql("select SQL: ", sql)
+ Logger.logsql("sql: ", sql)
+ Logger.logsql("params: ",params)
+ return self.beeSql.select(sql, self.to_class_t(entity),params) # 返回值用到泛型
+ finally:
+ pass # 在 Python 中可以省略 finally, 如果没有清理操作
+
+
+ def select_paging(self, entity, start, size):
+ if entity is None:
+ return None
+
+ try:
+ sql, params = self.objToSQL.toSelectSQLWithPaging(entity,start, size)
+ # Logger.log_sql("select SQL: ", sql)
+ Logger.logsql("sql: ", sql)
+ Logger.logsql("params: ",params)
+ return self.beeSql.select(sql, self.to_class_t(entity), params) # 返回值用到泛型
+ finally:
+ pass
+
+ def update(self, entity):
+ if entity is None:
+ return None
+
+ try:
+ sql, params = self.objToSQL.toUpdateSQL(entity)
+ Logger.logsql("sql: ", sql)
+ Logger.logsql("params: ",params)
+ return self.beeSql.modify(sql, params)
+ finally:
+ pass
+
+ def insert(self, entity):
+ if entity is None:
+ return None
+
+ try:
+ sql, params = self.objToSQL.toInsertSQL(entity)
+ Logger.logsql("sql: ", sql)
+ Logger.logsql("params: ",params)
+ return self.beeSql.modify(sql, params)
+ finally:
+ pass
+
+ def delete(self, entity):
+ if entity is None:
+ return None
+
+ try:
+ sql, params = self.objToSQL.toDeleteSQL(entity)
+ Logger.logsql("sql: ", sql)
+ Logger.logsql("params: ",params)
+ return self.beeSql.modify(sql, params)
+ finally:
+ pass
+
+ def to_class_t(self, entity):
+ return type(entity) #返回实体的类型
+
+ # def __init__(self, beeSql=None, objToSQL=None):
+ # self._beeSql = beeSql
+ # self._objToSQL = objToSQL
+
+ @property
+ def beeSql(self):
+ if self._beeSql is None:
+ # self._beeSql = BeeFactory.get_honey_factory().get_beeSql()
+ self._beeSql =BeeSql()
+ return self._beeSql
+
+ @beeSql.setter
+ def beeSql(self, beeSql):
+ self._beeSql = beeSql
+
+ @property
+ def objToSQL(self):
+ if self._objToSQL is None:
+ self._objToSQL= ObjToSQL()
+ return self._objToSQL
+
+ @objToSQL.setter
+ def objToSQL(self, objToSQL):
+ self._objToSQL = objToSQL
+
diff --git a/bee/config.py b/bee/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab811c6b5f22447d2d5385249e303676eb756e24
--- /dev/null
+++ b/bee/config.py
@@ -0,0 +1,131 @@
+import json
+
+from bee.key import Key
+from bee.osql.logger import Logger
+
+
+class HoneyConfig:
+
+ dbName =None
+ host =None
+ user =None
+ password=None
+ database=None
+ port =None
+
+ _loaded = False # 标记是否已加载配置
+
+ __db_config_data=None
+
+ __instance = None
+
+ def __new__(cls):
+ if cls.__instance is None:
+ Logger.debug("HoneyConfig.__new__")
+ cls.__instance = super().__new__(cls)
+ cls.__loadConfigInProperties(cls)
+ cls.__loadConfigInJson(cls)
+ if cls.port is not None:
+ cls.port=int(cls.port)
+
+ if cls.__db_config_data is None:
+ Logger.info("Default loading and init configuration file failed!")
+ return cls.__instance
+
+
+ @staticmethod
+ def __loadConfigInProperties(cls):
+ if cls._loaded:
+ return
+ config_file = Key.configPropertiesFileName # 文件路径
+
+ try:
+ with open(config_file, 'r') as file:
+ cls._loaded = True # 设置为已加载
+ print("Loading config file: "+config_file)
+ for line in file:
+ line = line.strip()
+ # 跳过空行和注释
+ if not line or line.startswith('#'):
+ continue
+ # 拆分键值对
+ try:
+ key, value = line.split('=',1)
+ key = key.strip()
+ value = value.strip()
+ except ValueError as err:
+ print(err,line)
+ continue
+
+ # 检查键是否以 'bee.db.' 开头
+ if key.startswith('bee.db.'):
+ # 获取属性名称
+ attr_name = key[len('bee.db.'):]
+ # 将值赋给对应的属性
+ if hasattr(cls, attr_name):
+ setattr(cls, attr_name, value)
+
+
+ cls.__db_config_data = cls.__instance.get_db_config_dict()
+ except OSError as err:
+ print(err)
+
+
+ @staticmethod
+ def __loadConfigInJson(cls):
+ if not cls._loaded: #只加载一次
+ # config_file_path = os.path.join(os.path.dirname(__file__), 'config.json')
+ config_file=Key.configJsonFileName
+ print("Loading config file: "+config_file)
+ try:
+ with open(config_file, 'r') as config_file:
+ cls._loaded = True # 设置为已加载
+ cls.__db_config_data = json.load(config_file)
+
+ cls.dbName=cls.__db_config_data.get("dbName")
+
+ except OSError as err:
+ print(err)
+
+
+ def get_db_config_dict(self):
+ """将DB相关的类属性打包成字典并返回"""
+ cls=type(self)
+ if cls.__db_config_data is not None:
+ return cls.__db_config_data
+
+ cls.__db_config_data={}
+
+ if HoneyConfig.dbName is not None:
+ cls.__db_config_data['dbName'] = HoneyConfig.dbName
+ if HoneyConfig.host is not None:
+ cls.__db_config_data['host'] = HoneyConfig.host
+ if HoneyConfig.user is not None:
+ cls.__db_config_data['user'] = HoneyConfig.user
+ if HoneyConfig.password is not None:
+ cls.__db_config_data['password'] = HoneyConfig.password
+ if HoneyConfig.database is not None:
+ cls.__db_config_data['database'] = HoneyConfig.database
+ if HoneyConfig.port is not None:
+ cls.__db_config_data['port'] = int(HoneyConfig.port)
+
+ return cls.__db_config_data
+
+ def set_db_config_dict(self,config):
+ cls=type(self)
+ cls.__db_config_data=config
+
+ if config is not None:
+ Logger.info("Reset db_config_data")
+ if config.get("dbName") is not None:
+ if cls.__db_config_data is None:
+ cls.__db_config_data={}
+ cls.__db_config_data["dbName"] = config.get("dbName")
+
+ def get_dbName(self):
+ return HoneyConfig.dbName.lower()
+
+ def set_dbName(self, dbName):
+ print("---------------:"+dbName)
+ HoneyConfig.dbName = dbName
+
diff --git a/bee/conn_builder.py b/bee/conn_builder.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c3b5a2efc2df4d06ef06d6a6c8cc80f3ba4497d
--- /dev/null
+++ b/bee/conn_builder.py
@@ -0,0 +1,88 @@
+# import sqlite3
+# import pymysql
+import importlib
+
+from bee.key import Key
+from bee.osql.const import DatabaseConst
+from bee.osql.logger import Logger
+
+class ConnectionBuilder:
+
+ @staticmethod
+ def build_connect(config):
+ dbName = None
+ if Key.dbName in config:
+ tempConfig = config.copy()
+ dbName = tempConfig.pop(Key.dbName, None)
+ else:
+ tempConfig = config
+
+ # Map database names to their respective module names and connection functions
+ db_modules = {
+ DatabaseConst.MYSQL.lower(): 'pymysql',
+ DatabaseConst.SQLite.lower(): 'sqlite3',
+ DatabaseConst.ORACLE.lower(): 'cx_Oracle',
+ DatabaseConst.PostgreSQL.lower(): 'psycopg2',
+ }
+
+ # Check if the dbName is supported
+ # if dbName not in db_modules:
+
+ if dbName is None:
+ # raise ValueError("Need set the dbName in Config!")
+ Logger.info("Need set the dbName in Config!")
+ return None
+
+ dbName = dbName.lower()
+
+ if Key.dbModuleName in config: #优先使用dbModuleName,让用户可以有选择覆盖默认配置的机会
+ dbModuleName = tempConfig.pop(Key.dbModuleName, None)
+ elif dbName not in db_modules:
+ # raise ValueError(f"Database type '{dbName}' is not supported, need config dbModuleName.")
+ print(f"Database type '{dbName}' is not supported, need config dbModuleName.")
+ return None
+ else:
+ dbModuleName = db_modules[dbName]
+
+
+ db_module = importlib.import_module(dbModuleName)
+ Logger.info(f"Use {dbModuleName}!")
+
+ # Now create the connection using the imported module
+ if dbName == DatabaseConst.MYSQL.lower():
+ return db_module.connect(**tempConfig)
+ elif dbName == DatabaseConst.SQLite.lower():
+ return db_module.connect(**tempConfig)
+
+
+
+
+# ### 2. 使用 `psycopg2`(PostgreSQL)
+#
+# ```python
+# import psycopg2
+#
+# def fetch_user_data_postgresql(username, age):
+# connection = psycopg2.connect(
+# host='localhost',
+# user='your_username',
+# password='your_password',
+# database='your_database'
+# )
+
+
+
+
+# import cx_Oracle
+#
+# def fetch_user_data_oracle(username, age):
+# connection = cx_Oracle.connect('username/password@localhost/orcl')
+
+# Or
+# import cx_Oracle
+#
+# # 创建数据库连接
+# def create_connection():
+# dsn = cx_Oracle.makedsn("hostname", 1521, service_name="your_service_name")
+# connection = cx_Oracle.connect(user="your_username", password="your_password", dsn=dsn)
+# return connection
diff --git a/bee/context.py b/bee/context.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ef0f810c56f8954b2bd896eb18773244c7e77e9
--- /dev/null
+++ b/bee/context.py
@@ -0,0 +1,55 @@
+# import sqlite3
+# import pymysql
+from bee.config import HoneyConfig
+from bee.conn_builder import ConnectionBuilder
+from bee.factory import BeeFactory
+from bee.key import Key
+from bee.osql.const import DatabaseConst
+
+
+class HoneyContext:
+
+ dbName=None
+
+ @staticmethod
+ def get_connection():
+
+ factory = BeeFactory()
+ conn = factory.get_connection()
+ if conn is not None:
+ # conn.ping(reconnect=True) #重新获取,要重连。 只是mysql?
+ return conn
+
+ honeyConfig = HoneyConfig()
+ config = honeyConfig.get_db_config_dict()
+
+ HoneyContext.__setDbName(config)
+ conn = ConnectionBuilder.build_connect(config)
+ factory.set_connection(conn)
+ return conn
+
+ @staticmethod
+ def __setDbName(config):
+ if Key.dbName in config:
+ dbName = config.get(Key.dbName, None)
+ if dbName is not None:
+ HoneyContext.dbName = dbName
+
+ @staticmethod
+ def get_placeholder():
+
+ honeyConfig=HoneyConfig()
+ dbName=honeyConfig.get_dbName().lower()
+
+ if dbName is None:
+ return None
+ elif dbName == DatabaseConst.MYSQL.lower() or dbName == DatabaseConst.PostgreSQL.lower():
+ return "%s"
+ elif dbName == DatabaseConst.SQLite.lower():
+ return "?"
+ elif dbName == DatabaseConst.ORACLE.lower():
+ # query = "SELECT * FROM users WHERE username = :username AND age = :age"
+ return ":"
+
+
+ #还要有set的方法,或在配置文件中设置 TODO
diff --git a/bee/factory.py b/bee/factory.py
new file mode 100644
index 0000000000000000000000000000000000000000..0cfa69f62428715fac4eb49ad7d9f2dd64e91f4c
--- /dev/null
+++ b/bee/factory.py
@@ -0,0 +1,20 @@
+class BeeFactory:
+
+ __connection = None
+
+ __instance = None
+
+ def __new__(cls):
+ if cls.__instance is None:
+ cls.__instance = super().__new__(cls)
+ return cls.__instance
+
+ def set_connection(self, connection):
+ BeeFactory.__connection = connection
+
+ def get_connection(self):
+ return BeeFactory.__connection
+
+ # def __getattribute__(self, item):
+ # print(f"Accessing attribute: {item}")
+ # return super().__getattribute__(item)
\ No newline at end of file
diff --git a/bee/key.py b/bee/key.py
new file mode 100644
index 0000000000000000000000000000000000000000..035a5759ee99acb594adf820d824fd1bed106acf
--- /dev/null
+++ b/bee/key.py
@@ -0,0 +1,13 @@
+
+
+class Key:
+ tablename = "__tablename__"
+ pk = "__pk__"
+ primary_key = "__primary_key__"
+ id="id"
+
+ dbModuleName="dbModuleName"
+ dbName="dbName"
+
+ configPropertiesFileName="bee.properties"
+ configJsonFileName="bee.json"
\ No newline at end of file
diff --git a/bee/name/NameUtil.py b/bee/name/NameUtil.py
new file mode 100644
index 0000000000000000000000000000000000000000..04bff41460dd6b923364949e8f4d4b31f6b942a4
--- /dev/null
+++ b/bee/name/NameUtil.py
@@ -0,0 +1,22 @@
+# NameUtil
+
+
+def getClassName(obj):
+ pass
+
+
+def toUnderscoreNaming(name):
+ pass
+
+
+def toCamelNaming(name):
+ pass
+
+
+def firstLetterToUpperCase(name):
+ pass
+
+
+def firstLetterToLowerCase(name):
+ pass
+
diff --git a/bee/name/UnderScoreAndCamelName.py b/bee/name/UnderScoreAndCamelName.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ab9f726c200e46b967515f192610b37831ec9dc
--- /dev/null
+++ b/bee/name/UnderScoreAndCamelName.py
@@ -0,0 +1,23 @@
+from bee.name import NameUtil
+
+
+def toTableName(entityName):
+ return NameUtil.toUnderscoreNaming(NameUtil.firstLetterToLowerCase(entityName))
+
+
+def toColumnName(fieldName):
+ return NameUtil.toUnderscoreNaming(fieldName)
+
+
+# def toEntityName(tableName):
+# if (HoneyConfig.getHoneyConfig().naming_toLowerCaseBefore):
+# # need lowercase first if the name has upper case
+# tableName = tableName.toLowerCase()
+# return NameUtil.firstLetterToUpperCase(NameUtil.toCamelNaming(tableName))
+#
+#
+# def toFieldName(columnName):
+# if (HoneyConfig.getHoneyConfig().naming_toLowerCaseBefore) :
+# # need lowercase first if the name has upper case
+# columnName = columnName.toLowerCase(); # if not , BEE_NAME -> BEENAME -> ??
+# return NameUtil.toCamelNaming(columnName)
diff --git a/bee/name/__init__.py b/bee/name/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bee/obj2sql.py b/bee/obj2sql.py
new file mode 100644
index 0000000000000000000000000000000000000000..3fca8b91f92f1b5f1e7f93c975be5322de233557
--- /dev/null
+++ b/bee/obj2sql.py
@@ -0,0 +1,224 @@
+from bee.config import HoneyConfig
+from bee.context import HoneyContext
+from bee.key import Key
+from bee.osql.const import DatabaseConst
+from bee.paging import Paging
+from bee.util import HoneyUtil
+
+
+class ObjToSQL:
+
+ # def toSelectSQL(self, entity):
+ # cls=type(entity)
+ # classField = HoneyUtil.get_class_field(cls) # list
+ # fieldAndValue = HoneyUtil.get_obj_field_value(entity) # dict
+ #
+ # classFieldAndValue = HoneyUtil.get_class_field_value(cls)
+ #
+ # table_name=HoneyUtil.get_table_name(entity)
+ # if not fieldAndValue:
+ # return f"SELECT {', '.join(classField)} FROM {table_name}", None
+ #
+ # # objKey = fieldAndValue.keys()
+ # # 获取去掉前缀的键
+ # # objKey = [key.lstrip('_') for key in fieldAndValue.keys()]
+ # fieldAndValue = {key.lstrip('_'): value for key, value in fieldAndValue.items()}
+ # objKey = fieldAndValue.keys()
+ # set1 = set(classField)
+ # set2 = set(objKey) # list转set 顺序会乱了
+ # setExt = set2 - set1
+ #
+ # # 默认删除动态加的属性
+ # for k in setExt:
+ # fieldAndValue.pop(k, None)
+ #
+ # #若对象的属性的值是None,则使用类级别的
+ # for name, value in fieldAndValue.items():
+ # if value is None:
+ # fieldAndValue[name]=classFieldAndValue[name]
+ #
+ # print(fieldAndValue)
+ #
+ # # 提取条件的键值对
+ # condition_list = []
+ # value_list=[]
+ # ph=self.__getPlaceholder()
+ # for key, value in fieldAndValue.items():
+ # if value is not None:
+ # condition_list.append(f"{key} = {ph}")
+ # value_list.append(value)
+ #
+ # where_clause = " AND ".join(condition_list)
+ # if where_clause is not None and where_clause != '' :
+ # sql = f"SELECT {', '.join(classField)} FROM {table_name} WHERE {where_clause}"
+ # else:
+ # sql = f"SELECT {', '.join(classField)} FROM {table_name}"
+ #
+ # return sql, value_list #如何将值放入上下文 TODO
+
+
+
+
+ def toSelectSQLWithPaging(self, entity, start, size):
+ sql, params = self.toSelectSQL(entity)
+
+ paging = Paging()
+ sql = paging.to_page_sql(sql, start, size)
+ return sql, params
+
+ def toSelectSQL(self, entity):
+ fieldAndValue, classField = self.__getKeyValue_classField(entity)
+
+ table_name = HoneyUtil.get_table_name(entity)
+ return self.__build_select_sql(table_name, classField, fieldAndValue);
+
+ def toUpdateSQL(self, entity):
+ fieldAndValue = self.__getKeyValue(entity)
+ pk = HoneyUtil.get_pk(entity)
+ if pk is None:
+ if not Key.id in fieldAndValue:
+ # if not "id" in fieldAndValue:
+ print("update by id,bean has id field or need set the pk field name with __pk__") # TODO throw exception
+ else:
+ idvalue = fieldAndValue.get(Key.id, None)
+ if idvalue is None:
+ print("the id value can not be None")
+ else:
+ pk = Key.id
+
+ conditions = {pk:fieldAndValue.pop(pk)}
+
+ table_name = HoneyUtil.get_table_name(entity)
+ return self.__build_update_sql(table_name, fieldAndValue, conditions)
+
+
+ def toInsertSQL(self, entity):
+ table_name = HoneyUtil.get_table_name(entity)
+ fieldAndValue = self.__getKeyValue(entity)
+ return self.__build_insert_sql(table_name, fieldAndValue)
+
+
+ def toDeleteSQL(self, entity):
+ table_name = HoneyUtil.get_table_name(entity)
+ fieldAndValue = self.__getKeyValue(entity)
+ return self.__build_delete_sql(table_name, fieldAndValue)
+
+ def __getKeyValue(self, entity):
+ fieldAndValue, _ = self.__getKeyValue_classField(entity)
+ return fieldAndValue
+
+ #__ or _只是用于范围保护,转成sql时,将这两种前缀统一去掉
+ def __getKeyValue_classField(self, entity):
+
+ cls=type(entity)
+ classField = HoneyUtil.get_class_field(cls) # list
+ fieldAndValue = HoneyUtil.get_obj_field_value(entity) # dict
+ # print(fieldAndValue)
+
+ classFieldAndValue = HoneyUtil.get_class_field_value(cls)
+ # print("aaaaa------------")
+ # print(classFieldAndValue)
+
+ # 获取去掉前缀的键 TODO __ ??
+ # fieldAndValue = {key.lstrip('_'): value for key, value in fieldAndValue.items()}
+
+ fieldAndValue = HoneyUtil.remove_prefix(fieldAndValue)
+
+
+ objKey = fieldAndValue.keys()
+
+ set1 = set(classField)
+ set2 = set(objKey) # list转set 顺序会乱了
+
+ setExt = set2 - set1
+
+ # 默认删除动态加的属性
+ for k in setExt:
+ fieldAndValue.pop(k, None)
+
+ # 若对象的属性的值是None,则使用类级别的
+ for name, value in fieldAndValue.items():
+ if value is None:
+ fieldAndValue[name] = classFieldAndValue[name]
+
+ # 当对象的属性没有相应的值,而类的属性有,则使用类级的属性
+ for name, value in classFieldAndValue.items():
+ if value is not None and fieldAndValue.get(name, None) is None:
+ fieldAndValue[name] = value
+
+ #排除value为None的项
+ fieldAndValue = {key: value for key, value in fieldAndValue.items() if value is not None}
+
+ return fieldAndValue, classField
+
+ def __getPlaceholder(self):
+ return HoneyContext.get_placeholder()
+
+
+ def __build_update_sql(self, table_name, set_dict, conditions):
+ ph=self.__getPlaceholder()
+ if self.__getPlaceholderType() == 3:
+ updateSet = ', '.join(f"{key} = {ph}{key}" for key in set_dict.keys())
+ condition_str = " AND ".join(f"{key} = {ph}{key}" for key in conditions.keys())
+ else:
+ updateSet = ', '.join(f"{key} = {ph}" for key in set_dict.keys())
+ condition_str = " AND ".join(f"{key} = {ph}" for key in conditions.keys())
+
+ sql = f"UPDATE {table_name} SET {updateSet} WHERE {condition_str}"
+ params = list(set_dict.values()) + list(conditions.values())
+ return sql, params
+
+
+ def __build_insert_sql(self, table_name, data):
+ ph=self.__getPlaceholder()
+ columns = ', '.join(data.keys())
+ if self.__getPlaceholderType() == 3:
+ placeholders = ', '.join(f" {ph}{key}" for key in data.keys())
+ else:
+ placeholders = ', '.join(f"{ph}" for _ in data)
+ sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
+ return sql, list(data.values())
+
+ def __build_where_condition(self, conditions):
+ ph=self.__getPlaceholder()
+ if self.__getPlaceholderType() == 3:
+ condition_str = " AND ".join(f"{key} = {ph}{key}" for key in conditions.keys())
+ else:
+ condition_str = " AND ".join(f"{key} = {ph}" for key in conditions.keys())
+ return condition_str
+
+ def __build_select_sql(self, table_name, classField, conditions=None):
+ # sql = f"SELECT * FROM {table_name}"
+ sql = f"SELECT {', '.join(classField)} FROM {table_name}"
+
+ #where part
+ params = []
+ if conditions:
+ condition_str=self.__build_where_condition(conditions)
+ sql += f" WHERE {condition_str}"
+ params = list(conditions.values())
+ return sql, params
+
+
+ def __build_delete_sql(self, table_name, conditions):
+
+ sql = f"DELETE FROM {table_name}"
+ params = []
+ if conditions:
+ condition_str=self.__build_where_condition(conditions)
+ sql += f" WHERE {condition_str}"
+ params = list(conditions.values())
+ return sql, params
+
+ def __get_dbName(self):
+ honeyConfig=HoneyConfig()
+ return honeyConfig.get_dbName()
+
+ def __getPlaceholderType(self):
+
+ # sql = "SELECT * FROM employees WHERE employee_id = :emp_id"
+ # cursor.execute(sql, emp_id=emp_id)
+ # sql = "INSERT INTO employees (employee_id, employee_name, salary) VALUES (:emp_id, :emp_name, :emp_salary)"
+ # cursor.execute(sql, emp_id=emp_id, emp_name=emp_name, emp_salary=emp_salary)
+ if DatabaseConst.ORACLE.lower() == self.__get_dbName():
+ return 3
diff --git a/bee/osql/__init__.py b/bee/osql/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bee/osql/const.py b/bee/osql/const.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a138c358cf6031882ad9e98d2537771a6c41cae
--- /dev/null
+++ b/bee/osql/const.py
@@ -0,0 +1,49 @@
+
+
+class DatabaseConst:
+ MYSQL = "MySQL"
+ MariaDB = "MariaDB"
+ ORACLE = "Oracle"
+ SQLSERVER = "Microsoft SQL Server"
+ MsAccess = "Microsoft Access" # Microsoft Access
+ AzureSQL = SQLSERVER
+
+ H2 = "H2"
+ SQLite = "SQLite"
+ PostgreSQL = "PostgreSQL"
+
+ Cubrid = "Cubrid"
+ DB2400 = "DB2 UDB for AS/400"
+ DB2 = "DB2"
+ Derby = "Apache Derby"
+ Firebird = "Firebird"
+ FrontBase = "FrontBase"
+
+ HSQL = "HSQL Database Engine"
+ HSQLDB = "HSQL Database"
+ Informix = "Informix Dynamic Server"
+ Ingres = "Ingres"
+ JDataStore = "JDataStore"
+ Mckoi = "Mckoi"
+ MimerSQL = "MimerSQL"
+ Pointbase = "Pointbase"
+
+ SAPDB = "SAPDB"
+ Sybase = "Sybase SQL Server"
+ Teradata = "Teradata"
+ TimesTen = "TimesTen"
+
+ DM = "DM DBMS"
+ Kingbase = "KingbaseES"
+ GaussDB = "GaussDB"
+
+ OceanBase = "OceanBase"
+
+ # NoSql
+ Cassandra = "Cassandra"
+ Hbase = "Hbase"
+ Hypertable = "Hypertable"
+ DynamoDB = "DynamoDB"
+
+ MongoDB = "MongoDB"
+ CouchDB = "CouchDB"
diff --git a/bee/osql/logger.py b/bee/osql/logger.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0995813944a0efb54d0830bf2411b8ebd4a9c98
--- /dev/null
+++ b/bee/osql/logger.py
@@ -0,0 +1,24 @@
+
+
+class Logger:
+
+ @staticmethod
+ def debug(msg):
+ print(msg)
+
+ @staticmethod
+ def info(msg):
+ print(msg)
+
+ @staticmethod
+ def warn(msg):
+ print(msg)
+
+ @staticmethod
+ def error(msg):
+ print(msg)
+
+ @staticmethod
+ def logsql(*msg):
+ print(*msg)
+
diff --git a/bee/osql/upperkey.py b/bee/osql/upperkey.py
new file mode 100644
index 0000000000000000000000000000000000000000..5750fe1113d1d073adea07b6b1054c6fc85958bb
--- /dev/null
+++ b/bee/osql/upperkey.py
@@ -0,0 +1,5 @@
+
+
+class UpperKey:
+ SPACE = " "
+ SELECT = "SELECT"
diff --git a/bee/paging.py b/bee/paging.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef9049525cf7df04cf9d092986ee334f599df839
--- /dev/null
+++ b/bee/paging.py
@@ -0,0 +1,25 @@
+from bee.config import HoneyConfig
+from bee.osql.const import DatabaseConst
+
+
+class Paging:
+
+ def to_page_sql(self, sql, start, size):
+ config = HoneyConfig()
+ dbName = config.get_dbName()
+ if dbName is None:
+ # 使用配置的dbName TODO 抛异常
+ return sql
+ elif dbName == DatabaseConst.MYSQL.lower():
+ return self.__toPageSqlForMySql(sql, start, size)
+ elif dbName == DatabaseConst.SQLite.lower():
+ return self.__toLimitOffsetPaging(sql, start, size)
+
+ def __toPageSqlForMySql(self, sql, start, size):
+ limitStament = " " + "limit" + " " + str(start) + ", " + str(size)
+ sql += limitStament
+ return sql
+
+ def __toLimitOffsetPaging(self, sql, offset, size):
+ return sql + " " + "limit" + " " + str(size) + " " + "offset" + " " + str(offset)
+
diff --git a/bee/sqllib.py b/bee/sqllib.py
new file mode 100644
index 0000000000000000000000000000000000000000..208f5347b30a42bc105754908aed48594092e468
--- /dev/null
+++ b/bee/sqllib.py
@@ -0,0 +1,59 @@
+from bee.context import HoneyContext
+from bee.util import HoneyUtil
+
+class BeeSql:
+
+ def select(self, sql, entityClass, params=None):
+ # def select(self, sql: str, entityClass: type, params=None) -> list:
+
+ conn = self.__getConn()
+ if conn is None:
+ return None
+
+ rs_list = []
+ cursor = conn.cursor()
+ try:
+ ## with conn.cursor() as cursor: # SQLite不支持with语法
+ # 执行 SQL 查询
+ cursor.execute(sql, params or [])
+ # 获取列名
+ column_names = [description[0] for description in cursor.description]
+ # 获取所有结果
+ results = cursor.fetchall()
+
+ for row in results:
+ # 将行数据映射到新创建的实体对象
+ target_obj = HoneyUtil.transform_result(row, column_names, entityClass)
+ rs_list.append(target_obj)
+
+ except Exception as err: # TODO 异常处理
+ print(f"Error: {err}")
+ finally:
+ # 清理资源
+ if conn is not None:
+ conn.close()
+ return rs_list
+
+
+ """ 执行 UPDATE/INSERT/DELETE 操作 """
+ # def modify(self, sql: str, params=None) -> int:
+ def modify(self, sql, params=None):
+ conn = self.__getConn()
+ if conn is None:
+ return None # TODO抛异常
+ cursor = conn.cursor()
+ try:
+ cursor.execute(sql, params or [])
+ conn.commit()
+ return cursor.rowcount # 返回受影响的行数
+ except Exception as e:
+ print(f"Error in modify: {e}")
+ conn.rollback()
+ return 0
+ finally:
+ if conn is not None:
+ conn.close()
+
+ def __getConn(self):
+ return HoneyContext.get_connection()
+
diff --git a/bee/util.py b/bee/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..0679de8fb29def149241b832c8fb6f985be17972
--- /dev/null
+++ b/bee/util.py
@@ -0,0 +1,135 @@
+from bee.key import Key
+
+
+class HoneyUtil:
+
+ """返回给定对象的属性字典,如果没有则返回None"""
+
+ @staticmethod
+ def get_obj_field_value(obj):
+ if hasattr(obj, '__dict__'):
+ # print(obj.__dict__)
+ return obj.__dict__
+ else:
+ return None
+
+ @staticmethod
+ def get_class_field_value(cls):
+
+ if hasattr(cls, '__dict__'):
+ # 并去掉前缀__和_ 只是__开前开头,会变化的。
+ class_name = cls.__name__
+ prefix="_"+class_name+"__"
+ kv = { key[len(prefix):] if key.startswith(prefix) else key[1:] if key.startswith('_') else key: value
+ for key, value in cls.__dict__.items() if not (key.startswith('__') and key.endswith('__'))}
+ for key, value in kv.items():
+ if isinstance(value, property):
+ kv[key]=None #使用get/set,暂时不能获取到bean的类级别的值。 TODO 应用使用_或__前缀
+ # kv[key]=getattr(cls, key)
+ return kv
+ else:
+ return None
+
+
+
+ # if hasattr(cls, '__dict__'):
+ # print(cls.__dict__)
+ # return {key: value for key, value in cls.__dict__.items() if (not (key.startswith('__') and key.endswith('__'))) and not isinstance(value, property) }
+ # else:
+ # return None
+
+ # if hasattr(cls, '__dict__'):
+ # return {
+ # key: (getattr(cls, key)() if isinstance(getattr(cls, key), property) else getattr(cls, key))
+ # for key in cls.__dict__.keys()
+ # if not (key.startswith('__') and key.endswith('__')) # 排除私有属性
+ # }
+ # else:
+ # return None
+
+ # result = {}
+ # for key in cls.__class__.__dict__:
+ # # 排除私有属性
+ # if not (key.startswith('__') and key.endswith('__')):
+ # value = getattr(cls, key)
+ # # 如果是property类型,则获取其值
+ # if isinstance(value, property):
+ # result[key] = getattr(cls, key) # 通过实例获取属性值
+ # else:
+ # result[key] = value
+ # print(result)
+ # return result
+ # dict: {'id': , 'name': , 'remark': }
+
+ """ 返回给定类的属性字典,但不包括系统的 """
+
+ @staticmethod
+ def get_class_field(cls):
+ if hasattr(cls, '__dict__'):
+ # 过滤掉以__开头和结尾的键,并去掉前缀__和_ 只是__开前开头,会变化的。
+ class_name = cls.__name__
+ prefix="_"+class_name+"__"
+ return [
+ key[len(prefix):] if key.startswith(prefix) else key[1:] if key.startswith('_') else key
+ for key in cls.__dict__.keys()
+ if not (key.startswith('__') and key.endswith('__'))
+ ]
+ else:
+ return None
+
+ # if hasattr(cls, '__dict__'):
+ # # 排除__开头且__结尾的
+ # return [key for key in cls.__dict__.keys() if not (key.startswith('__') and key.endswith('__'))]
+ # else:
+ # return None
+
+ # 对象的不会改
+ """ remove __ or _ prefix """
+ @staticmethod
+ def remove_prefix(dict_obj):
+ if dict_obj is None:
+ return dict_obj
+
+ fieldAndValue = {
+ key[2:] if key.startswith('__') else key[1:] if key.startswith('_') else key: value
+ # key[1:] if key.startswith('_') else key: value
+ for key, value in dict_obj.items()
+ }
+ return fieldAndValue
+
+ @staticmethod
+ def get_table_name(obj):
+ cls = obj.__class__
+ # print(cls)
+ # temp_name=cls.__tablename__
+ temp_name = getattr(cls, '__tablename__', None)
+ if temp_name is not None and not temp_name.isspace():
+ return temp_name
+ class_name = cls.__name__
+ table_name = class_name.lower() # 还要应用多种转换规则 TODO
+ return table_name
+
+ """ get pk from bean"""
+
+ @staticmethod
+ def get_pk(obj):
+ cls = obj.__class__
+ temp_name = getattr(cls, Key.pk, None)
+ if temp_name is not None and not temp_name.isspace():
+ return temp_name
+ else:
+ temp_name = getattr(cls, Key.primary_key, None)
+ if temp_name is not None and not temp_name.isspace():
+ return temp_name
+ return None
+
+ """将结果集的一行转换为实体对象"""
+ @staticmethod
+ def transform_result(row, column_names, entity_class):
+
+ # 创建实体类的新实例
+ obj = entity_class()
+ for i in range(len(column_names)):
+ setattr(obj, column_names[i], row[i]) # 像时间等类型,是否也可以自动设置??? TODO
+ return obj
+