bugfix
This commit is contained in:
parent
0859f8162d
commit
472ce1647a
0
sqlor/__init__.py
Executable file → Normal file
0
sqlor/__init__.py
Executable file → Normal file
0
sqlor/aiopostgresqlor.py
Executable file → Normal file
0
sqlor/aiopostgresqlor.py
Executable file → Normal file
84
sqlor/aiosqliteor.py
Executable file → Normal file
84
sqlor/aiosqliteor.py
Executable file → Normal file
@ -1,7 +1,85 @@
|
||||
import re
|
||||
from .sqlite3or import SQLite3or
|
||||
import aiosqlite
|
||||
from .sor import SQLor
|
||||
|
||||
class Aiosqliteor(SQLite3or):
|
||||
select_stmt = """
|
||||
select
|
||||
$[fields]$
|
||||
from
|
||||
$[tables]$
|
||||
$[whereclause]$
|
||||
$[groupbyclause]$
|
||||
$[havingclause]$
|
||||
$[orderbyclause]$
|
||||
"""
|
||||
|
||||
class Aiosqliteor(SQLor):
|
||||
@classmethod
|
||||
def isMe(self,name):
|
||||
return name=='aiosqlite'
|
||||
|
||||
async def connect(self):
|
||||
"""
|
||||
dbdesc:
|
||||
path: 数据库文件路径(或 :memory:)
|
||||
"""
|
||||
dbdesc = self.dbdesc
|
||||
self.dbpath = dbdesc.get('path', ':memory:')
|
||||
self.conn = await aiosqlite.connect(self.dbpath)
|
||||
self.conn.row_factory = aiosqlite.Row # 支持 dict 访问
|
||||
self.dbname = self.dbpath
|
||||
|
||||
async def close(self):
|
||||
await self.conn.close()
|
||||
|
||||
async def enter(self):
|
||||
"""开启事务"""
|
||||
self.cur = await self.conn.cursor()
|
||||
|
||||
async def exit(self):
|
||||
"""释放 cursor"""
|
||||
try:
|
||||
await self.cur.close()
|
||||
except:
|
||||
pass
|
||||
self.cur = None
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select':select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self,varname,i):
|
||||
if varname=='__mainsql__' :
|
||||
return ''
|
||||
return '?'
|
||||
|
||||
def dataConvert(self,dataList):
|
||||
if type(dataList) == type({}):
|
||||
return dataList
|
||||
d = { i['name']:i['value'] for i in dataList }
|
||||
return d
|
||||
|
||||
def pagingSQLmodel(self):
|
||||
return u"""select * from (%s) page_s limit $[page_size]$ offset $[offset]$"""
|
||||
|
||||
def tablesSQL(self):
|
||||
sqlcmd = """SELECT name,sql as title FROM sqlite_master WHERE type='table'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self,tablename=None):
|
||||
sqlcmd="""PRAGMA table_info(%s);""" % tablename
|
||||
return sqlcmd
|
||||
|
||||
def fkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd = """PRAGMA foreign_key_list('%s');""" % tablename
|
||||
return sqlcmd
|
||||
|
||||
def pkSQL(self,tablename=None):
|
||||
tablename = tablename.lower()
|
||||
sqlcmd="""PRAGMA table_info('%s');""" % tablename
|
||||
return sqlcmd
|
||||
|
||||
def indexesSQL(self,tablename=None):
|
||||
sqlcmd = """PRAGMA index_list('%s');""" % tablename
|
||||
return sqlcmd
|
||||
0
sqlor/const.py
Executable file → Normal file
0
sqlor/const.py
Executable file → Normal file
0
sqlor/dbpools.old.py
Executable file → Normal file
0
sqlor/dbpools.old.py
Executable file → Normal file
0
sqlor/dbpools.py
Executable file → Normal file
0
sqlor/dbpools.py
Executable file → Normal file
0
sqlor/ddl_template_mysql.py
Executable file → Normal file
0
sqlor/ddl_template_mysql.py
Executable file → Normal file
0
sqlor/ddl_template_oracle.py
Executable file → Normal file
0
sqlor/ddl_template_oracle.py
Executable file → Normal file
0
sqlor/ddl_template_postgresql.py
Executable file → Normal file
0
sqlor/ddl_template_postgresql.py
Executable file → Normal file
0
sqlor/ddl_template_sqlite3.py
Executable file → Normal file
0
sqlor/ddl_template_sqlite3.py
Executable file → Normal file
0
sqlor/ddl_template_sqlserver.py
Executable file → Normal file
0
sqlor/ddl_template_sqlserver.py
Executable file → Normal file
0
sqlor/filter.py
Executable file → Normal file
0
sqlor/filter.py
Executable file → Normal file
41
sqlor/mssqlor.py
Executable file → Normal file
41
sqlor/mssqlor.py
Executable file → Normal file
@ -2,6 +2,17 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_sqlserver import sqlserver_ddl_tmpl
|
||||
|
||||
select_stmt = """
|
||||
select
|
||||
$[fields]$
|
||||
from
|
||||
$[tables]$
|
||||
$[whereclause]$
|
||||
$[groupbyclause]$
|
||||
$[havingclause]$
|
||||
$[orderbyclause]$
|
||||
"""
|
||||
|
||||
class MsSqlor(SQLor):
|
||||
ddl_template = sqlserver_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
@ -172,3 +183,33 @@ AND IDXC.Column_id=C.Column_id"""
|
||||
if tablename is not None:
|
||||
sqlcmd = sqlcmd + """ where lower(O.name)='%s'""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
async def connect(self):
|
||||
"""
|
||||
Note: pymssql is synchronous. For async support, consider using aioodbc.
|
||||
This implementation uses threading for now.
|
||||
"""
|
||||
import asyncio
|
||||
import pymssql
|
||||
|
||||
dbdesc = self.dbdesc
|
||||
# pymssql uses different parameter names
|
||||
conn_params = {
|
||||
'server': dbdesc.get('host', 'localhost'),
|
||||
'user': dbdesc.get('user'),
|
||||
'password': dbdesc.get('password'),
|
||||
'database': dbdesc.get('db'),
|
||||
'port': dbdesc.get('port', 1433)
|
||||
}
|
||||
# Remove None values
|
||||
conn_params = {k: v for k, v in conn_params.items() if v is not None}
|
||||
|
||||
# Use thread pool for synchronous pymssql
|
||||
loop = asyncio.get_event_loop()
|
||||
self.conn = await loop.run_in_executor(None, pymssql.connect, **conn_params)
|
||||
self.dbname = dbdesc.get('db', '')
|
||||
|
||||
async def close(self):
|
||||
import asyncio
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, self.conn.close)
|
||||
0
sqlor/mysqlor.py
Executable file → Normal file
0
sqlor/mysqlor.py
Executable file → Normal file
41
sqlor/oracleor.py
Executable file → Normal file
41
sqlor/oracleor.py
Executable file → Normal file
@ -1,5 +1,17 @@
|
||||
from .sor import SQLor
|
||||
from .ddl_template_oracle import oracle_ddl_tmpl
|
||||
|
||||
select_stmt = """
|
||||
select
|
||||
$[fields]$
|
||||
from
|
||||
$[tables]$
|
||||
$[whereclause]$
|
||||
$[groupbyclause]$
|
||||
$[havingclause]$
|
||||
$[orderbyclause]$
|
||||
"""
|
||||
|
||||
class Oracleor(SQLor):
|
||||
ddl_template = oracle_ddl_tmpl
|
||||
db2modelTypeMapping = {
|
||||
@ -131,3 +143,32 @@ where a.index_name = b.index_name"""
|
||||
sqlcmd += """ and lower(a.table_name) = lower('%s')""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
async def connect(self):
|
||||
"""
|
||||
Note: cx_Oracle is synchronous. Using thread pool for async support.
|
||||
"""
|
||||
import asyncio
|
||||
import cx_Oracle
|
||||
|
||||
dbdesc = self.dbdesc
|
||||
# cx_Oracle connection string format
|
||||
dsn = cx_Oracle.makedsn(
|
||||
host=dbdesc.get('host', 'localhost'),
|
||||
port=dbdesc.get('port', 1521),
|
||||
service_name=dbdesc.get('service_name', dbdesc.get('sid', 'XE'))
|
||||
)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
self.conn = await loop.run_in_executor(
|
||||
None,
|
||||
cx_Oracle.connect,
|
||||
dbdesc.get('user'),
|
||||
dbdesc.get('password'),
|
||||
dsn
|
||||
)
|
||||
self.dbname = dbdesc.get('service_name', dbdesc.get('sid', ''))
|
||||
|
||||
async def close(self):
|
||||
import asyncio
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, self.conn.close)
|
||||
23
sqlor/postgresqlor.py
Executable file → Normal file
23
sqlor/postgresqlor.py
Executable file → Normal file
@ -170,7 +170,7 @@ order by
|
||||
i.relname""" % tablename.lower()
|
||||
return sqlcmd
|
||||
|
||||
async def connect():
|
||||
async def connect(self):
|
||||
"""
|
||||
kwargs:
|
||||
dbname:
|
||||
@ -179,13 +179,22 @@ order by
|
||||
host:
|
||||
port:
|
||||
"""
|
||||
kwargs = self.dbdesc
|
||||
dns = ' '.join([f'{k}={v}' for k, v in kwargs.items()])
|
||||
self.conn = await self.connect(dns)
|
||||
self.cur = await self.conn.cursor()
|
||||
self.dbname = kwargs.dbname.lower()
|
||||
dbdesc = self.dbdesc
|
||||
self.conn = await aiopg.connect(**dbdesc)
|
||||
self.dbname = dbdesc.get('dbname', '').lower()
|
||||
|
||||
async def close():
|
||||
async def close(self):
|
||||
await self.cur.close()
|
||||
await self.conn.close()
|
||||
|
||||
async def enter(self):
|
||||
self.cur = await self.conn.cursor()
|
||||
|
||||
async def exit(self):
|
||||
try:
|
||||
await self.cur.fetchall()
|
||||
await self.cur.close()
|
||||
except:
|
||||
pass
|
||||
self.cur = None
|
||||
|
||||
|
||||
0
sqlor/records.py
Executable file → Normal file
0
sqlor/records.py
Executable file → Normal file
0
sqlor/sor.py
Executable file → Normal file
0
sqlor/sor.py
Executable file → Normal file
0
sqlor/sqlite3or.py
Executable file → Normal file
0
sqlor/sqlite3or.py
Executable file → Normal file
@ -4,6 +4,17 @@ from .sor import SQLor
|
||||
from .const import ROWS
|
||||
from .ddl_template_mysql import mysql_ddl_tmpl # ✅ 直接复用 MySQL 模板
|
||||
|
||||
select_stmt = """
|
||||
select
|
||||
$[fields]$
|
||||
from
|
||||
$[tables]$
|
||||
$[whereclause]$
|
||||
$[groupbyclause]$
|
||||
$[havingclause]$
|
||||
$[orderbyclause]$
|
||||
"""
|
||||
|
||||
class TiDBor(SQLor):
|
||||
ddl_template = mysql_ddl_tmpl
|
||||
|
||||
@ -50,7 +61,7 @@ class TiDBor(SQLor):
|
||||
|
||||
def grammar(self):
|
||||
return {
|
||||
'select': 'select * from {table} where {condition}',
|
||||
'select': select_stmt,
|
||||
}
|
||||
|
||||
def placeHolder(self, varname, pos=None):
|
||||
@ -71,14 +82,14 @@ class TiDBor(SQLor):
|
||||
|
||||
def tablesSQL(self):
|
||||
# ✅ TiDB 支持 INFORMATION_SCHEMA.TABLES
|
||||
dbname = self.dbdesc.get('dbname', 'unknown')
|
||||
dbname = self.dbdesc.get('db', 'unknown') # MySQL uses 'db', not 'dbname'
|
||||
sqlcmd = f"""SELECT lower(TABLE_NAME) AS name, TABLE_COMMENT AS title
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = '{dbname}'"""
|
||||
return sqlcmd
|
||||
|
||||
def fieldsSQL(self, tablename=None):
|
||||
dbname = self.dbdesc.get('dbname', 'unknown').lower()
|
||||
dbname = self.dbdesc.get('db', 'unknown').lower() # MySQL uses 'db'
|
||||
sqlcmd = f"""
|
||||
SELECT
|
||||
lower(column_name) AS name,
|
||||
@ -98,7 +109,7 @@ WHERE lower(TABLE_SCHEMA) = '{dbname}'
|
||||
|
||||
def fkSQL(self, tablename=None):
|
||||
# ✅ TiDB 兼容 MySQL 的 FK 元信息
|
||||
dbname = self.dbdesc.get('dbname', 'unknown').lower()
|
||||
dbname = self.dbdesc.get('db', 'unknown').lower()
|
||||
sqlcmd = f"""
|
||||
SELECT
|
||||
C.TABLE_SCHEMA AS owner,
|
||||
@ -121,7 +132,7 @@ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
||||
WHERE table_name='{tablename.lower()}' AND constraint_name='PRIMARY'"""
|
||||
|
||||
def indexesSQL(self, tablename=None):
|
||||
dbname = self.dbdesc.get('dbname', 'unknown')
|
||||
dbname = self.dbdesc.get('db', 'unknown')
|
||||
sqlcmd = f"""SELECT DISTINCT
|
||||
lower(index_name) AS index_name,
|
||||
CASE NON_UNIQUE WHEN 0 THEN 'unique' ELSE '' END AS is_unique,
|
||||
@ -132,3 +143,28 @@ WHERE table_schema = '{dbname}'"""
|
||||
sqlcmd += f" AND table_name = '{tablename.lower()}'"
|
||||
return sqlcmd
|
||||
|
||||
async def connect(self):
|
||||
"""
|
||||
TiDB 兼容 MySQL 协议,使用 aiomysql
|
||||
"""
|
||||
import aiomysql
|
||||
|
||||
dbdesc = self.dbdesc
|
||||
# TiDB 使用与 MySQL 相同的连接参数
|
||||
self.conn = await aiomysql.connect(**dbdesc)
|
||||
self.dbname = dbdesc.get('db', '')
|
||||
|
||||
async def close(self):
|
||||
await self.cur.close()
|
||||
await self.conn.close()
|
||||
|
||||
async def enter(self):
|
||||
self.cur = await self.conn.cursor()
|
||||
|
||||
async def exit(self):
|
||||
try:
|
||||
await self.cur.fetchall()
|
||||
await self.cur.close()
|
||||
except:
|
||||
pass
|
||||
self.cur = None
|
||||
Loading…
x
Reference in New Issue
Block a user