mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: add OceanBase doc engine (#11228)
### What problem does this PR solve? Add OceanBase doc engine. Close #5350 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -27,6 +27,7 @@ from common.constants import SVR_QUEUE_NAME, Storage
|
|||||||
import rag.utils
|
import rag.utils
|
||||||
import rag.utils.es_conn
|
import rag.utils.es_conn
|
||||||
import rag.utils.infinity_conn
|
import rag.utils.infinity_conn
|
||||||
|
import rag.utils.ob_conn
|
||||||
import rag.utils.opensearch_conn
|
import rag.utils.opensearch_conn
|
||||||
from rag.utils.azure_sas_conn import RAGFlowAzureSasBlob
|
from rag.utils.azure_sas_conn import RAGFlowAzureSasBlob
|
||||||
from rag.utils.azure_spn_conn import RAGFlowAzureSpnBlob
|
from rag.utils.azure_spn_conn import RAGFlowAzureSpnBlob
|
||||||
@ -103,6 +104,7 @@ INFINITY = {}
|
|||||||
AZURE = {}
|
AZURE = {}
|
||||||
S3 = {}
|
S3 = {}
|
||||||
MINIO = {}
|
MINIO = {}
|
||||||
|
OB = {}
|
||||||
OSS = {}
|
OSS = {}
|
||||||
OS = {}
|
OS = {}
|
||||||
|
|
||||||
@ -227,7 +229,7 @@ def init_settings():
|
|||||||
FEISHU_OAUTH = get_base_config("oauth", {}).get("feishu")
|
FEISHU_OAUTH = get_base_config("oauth", {}).get("feishu")
|
||||||
OAUTH_CONFIG = get_base_config("oauth", {})
|
OAUTH_CONFIG = get_base_config("oauth", {})
|
||||||
|
|
||||||
global DOC_ENGINE, docStoreConn, ES, OS, INFINITY
|
global DOC_ENGINE, docStoreConn, ES, OB, OS, INFINITY
|
||||||
DOC_ENGINE = os.environ.get("DOC_ENGINE", "elasticsearch")
|
DOC_ENGINE = os.environ.get("DOC_ENGINE", "elasticsearch")
|
||||||
# DOC_ENGINE = os.environ.get('DOC_ENGINE', "opensearch")
|
# DOC_ENGINE = os.environ.get('DOC_ENGINE', "opensearch")
|
||||||
lower_case_doc_engine = DOC_ENGINE.lower()
|
lower_case_doc_engine = DOC_ENGINE.lower()
|
||||||
@ -240,6 +242,9 @@ def init_settings():
|
|||||||
elif lower_case_doc_engine == "opensearch":
|
elif lower_case_doc_engine == "opensearch":
|
||||||
OS = get_base_config("os", {})
|
OS = get_base_config("os", {})
|
||||||
docStoreConn = rag.utils.opensearch_conn.OSConnection()
|
docStoreConn = rag.utils.opensearch_conn.OSConnection()
|
||||||
|
elif lower_case_doc_engine == "oceanbase":
|
||||||
|
OB = get_base_config("oceanbase", {})
|
||||||
|
docStoreConn = rag.utils.ob_conn.OBConnection()
|
||||||
else:
|
else:
|
||||||
raise Exception(f"Not supported doc engine: {DOC_ENGINE}")
|
raise Exception(f"Not supported doc engine: {DOC_ENGINE}")
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,14 @@ os:
|
|||||||
infinity:
|
infinity:
|
||||||
uri: 'localhost:23817'
|
uri: 'localhost:23817'
|
||||||
db_name: 'default_db'
|
db_name: 'default_db'
|
||||||
|
oceanbase:
|
||||||
|
scheme: 'oceanbase' # set 'mysql' to create connection using mysql config
|
||||||
|
config:
|
||||||
|
db_name: 'test'
|
||||||
|
user: 'root@ragflow'
|
||||||
|
password: 'infini_rag_flow'
|
||||||
|
host: 'localhost'
|
||||||
|
port: 2881
|
||||||
redis:
|
redis:
|
||||||
db: 1
|
db: 1
|
||||||
password: 'infini_rag_flow'
|
password: 'infini_rag_flow'
|
||||||
|
|||||||
22
docker/.env
22
docker/.env
@ -7,6 +7,7 @@
|
|||||||
# Available options:
|
# Available options:
|
||||||
# - `elasticsearch` (default)
|
# - `elasticsearch` (default)
|
||||||
# - `infinity` (https://github.com/infiniflow/infinity)
|
# - `infinity` (https://github.com/infiniflow/infinity)
|
||||||
|
# - `oceanbase` (https://github.com/oceanbase/oceanbase)
|
||||||
# - `opensearch` (https://github.com/opensearch-project/OpenSearch)
|
# - `opensearch` (https://github.com/opensearch-project/OpenSearch)
|
||||||
DOC_ENGINE=${DOC_ENGINE:-elasticsearch}
|
DOC_ENGINE=${DOC_ENGINE:-elasticsearch}
|
||||||
|
|
||||||
@ -62,6 +63,27 @@ INFINITY_THRIFT_PORT=23817
|
|||||||
INFINITY_HTTP_PORT=23820
|
INFINITY_HTTP_PORT=23820
|
||||||
INFINITY_PSQL_PORT=5432
|
INFINITY_PSQL_PORT=5432
|
||||||
|
|
||||||
|
# The hostname where the OceanBase service is exposed
|
||||||
|
OCEANBASE_HOST=oceanbase
|
||||||
|
# The port used to expose the OceanBase service
|
||||||
|
OCEANBASE_PORT=2881
|
||||||
|
# The username for OceanBase
|
||||||
|
OCEANBASE_USER=root@ragflow
|
||||||
|
# The password for OceanBase
|
||||||
|
OCEANBASE_PASSWORD=infini_rag_flow
|
||||||
|
# The doc database of the OceanBase service to use
|
||||||
|
OCEANBASE_DOC_DBNAME=ragflow_doc
|
||||||
|
|
||||||
|
# OceanBase container configuration
|
||||||
|
OB_CLUSTER_NAME=${OB_CLUSTER_NAME:-ragflow}
|
||||||
|
OB_TENANT_NAME=${OB_TENANT_NAME:-ragflow}
|
||||||
|
OB_SYS_PASSWORD=${OCEANBASE_PASSWORD:-infini_rag_flow}
|
||||||
|
OB_TENANT_PASSWORD=${OCEANBASE_PASSWORD:-infini_rag_flow}
|
||||||
|
OB_MEMORY_LIMIT=${OB_MEMORY_LIMIT:-10G}
|
||||||
|
OB_SYSTEM_MEMORY=${OB_SYSTEM_MEMORY:-2G}
|
||||||
|
OB_DATAFILE_SIZE=${OB_DATAFILE_SIZE:-20G}
|
||||||
|
OB_LOG_DISK_SIZE=${OB_LOG_DISK_SIZE:-20G}
|
||||||
|
|
||||||
# The password for MySQL.
|
# The password for MySQL.
|
||||||
MYSQL_PASSWORD=infini_rag_flow
|
MYSQL_PASSWORD=infini_rag_flow
|
||||||
# The hostname where the MySQL service is exposed
|
# The hostname where the MySQL service is exposed
|
||||||
|
|||||||
@ -138,6 +138,15 @@ The [.env](./.env) file contains important environment variables for Docker.
|
|||||||
- `password`: The password for MinIO.
|
- `password`: The password for MinIO.
|
||||||
- `host`: The MinIO serving IP *and* port inside the Docker container. Defaults to `minio:9000`.
|
- `host`: The MinIO serving IP *and* port inside the Docker container. Defaults to `minio:9000`.
|
||||||
|
|
||||||
|
- `oceanbase`
|
||||||
|
- `scheme`: The connection scheme. Set to `mysql` to use mysql config, or other values to use config below.
|
||||||
|
- `config`:
|
||||||
|
- `db_name`: The OceanBase database name.
|
||||||
|
- `user`: The username for OceanBase.
|
||||||
|
- `password`: The password for OceanBase.
|
||||||
|
- `host`: The hostname of the OceanBase service.
|
||||||
|
- `port`: The port of OceanBase.
|
||||||
|
|
||||||
- `oss`
|
- `oss`
|
||||||
- `access_key`: The access key ID used to authenticate requests to the OSS service.
|
- `access_key`: The access key ID used to authenticate requests to the OSS service.
|
||||||
- `secret_key`: The secret access key used to authenticate requests to the OSS service.
|
- `secret_key`: The secret access key used to authenticate requests to the OSS service.
|
||||||
|
|||||||
@ -96,6 +96,31 @@ services:
|
|||||||
retries: 120
|
retries: 120
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
||||||
|
oceanbase:
|
||||||
|
profiles:
|
||||||
|
- oceanbase
|
||||||
|
image: oceanbase/oceanbase-ce:4.4.1.0-100000032025101610
|
||||||
|
volumes:
|
||||||
|
- ./oceanbase/data:/root/ob
|
||||||
|
- ./oceanbase/conf:/root/.obd/cluster
|
||||||
|
- ./oceanbase/init.d:/root/boot/init.d
|
||||||
|
ports:
|
||||||
|
- ${OCEANBASE_PORT:-2881}:2881
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
- MODE=normal
|
||||||
|
- OB_SERVER_IP=127.0.0.1
|
||||||
|
mem_limit: ${MEM_LIMIT}
|
||||||
|
healthcheck:
|
||||||
|
test: [ 'CMD-SHELL', 'obclient -h127.0.0.1 -P2881 -uroot@${OB_TENANT_NAME:-ragflow} -p${OB_TENANT_PASSWORD:-infini_rag_flow} -e "CREATE DATABASE IF NOT EXISTS ${OCEANBASE_DOC_DBNAME:-ragflow_doc};"' ]
|
||||||
|
interval: 10s
|
||||||
|
retries: 30
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
networks:
|
||||||
|
- ragflow
|
||||||
|
restart: on-failure
|
||||||
|
|
||||||
sandbox-executor-manager:
|
sandbox-executor-manager:
|
||||||
profiles:
|
profiles:
|
||||||
- sandbox
|
- sandbox
|
||||||
@ -256,6 +281,8 @@ volumes:
|
|||||||
driver: local
|
driver: local
|
||||||
infinity_data:
|
infinity_data:
|
||||||
driver: local
|
driver: local
|
||||||
|
ob_data:
|
||||||
|
driver: local
|
||||||
mysql_data:
|
mysql_data:
|
||||||
driver: local
|
driver: local
|
||||||
minio_data:
|
minio_data:
|
||||||
|
|||||||
1
docker/oceanbase/init.d/vec_memory.sql
Normal file
1
docker/oceanbase/init.d/vec_memory.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
|
||||||
@ -28,6 +28,14 @@ os:
|
|||||||
infinity:
|
infinity:
|
||||||
uri: '${INFINITY_HOST:-infinity}:23817'
|
uri: '${INFINITY_HOST:-infinity}:23817'
|
||||||
db_name: 'default_db'
|
db_name: 'default_db'
|
||||||
|
oceanbase:
|
||||||
|
scheme: 'oceanbase' # set 'mysql' to create connection using mysql config
|
||||||
|
config:
|
||||||
|
db_name: '${OCEANBASE_DOC_DBNAME:-test}'
|
||||||
|
user: '${OCEANBASE_USER:-root@ragflow}'
|
||||||
|
password: '${OCEANBASE_PASSWORD:-infini_rag_flow}'
|
||||||
|
host: '${OCEANBASE_HOST:-oceanbase}'
|
||||||
|
port: ${OCEANBASE_PORT:-2881}
|
||||||
redis:
|
redis:
|
||||||
db: 1
|
db: 1
|
||||||
password: '${REDIS_PASSWORD:-infini_rag_flow}'
|
password: '${REDIS_PASSWORD:-infini_rag_flow}'
|
||||||
|
|||||||
@ -149,6 +149,7 @@ dependencies = [
|
|||||||
"captcha>=0.7.1",
|
"captcha>=0.7.1",
|
||||||
"pip>=25.2",
|
"pip>=25.2",
|
||||||
"pypandoc>=1.16",
|
"pypandoc>=1.16",
|
||||||
|
"pyobvector==0.2.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
|||||||
@ -83,6 +83,7 @@ class FulltextQueryer:
|
|||||||
return txt
|
return txt
|
||||||
|
|
||||||
def question(self, txt, tbl="qa", min_match: float = 0.6):
|
def question(self, txt, tbl="qa", min_match: float = 0.6):
|
||||||
|
original_query = txt
|
||||||
txt = FulltextQueryer.add_space_between_eng_zh(txt)
|
txt = FulltextQueryer.add_space_between_eng_zh(txt)
|
||||||
txt = re.sub(
|
txt = re.sub(
|
||||||
r"[ :|\r\n\t,,。??/`!!&^%%()\[\]{}<>]+",
|
r"[ :|\r\n\t,,。??/`!!&^%%()\[\]{}<>]+",
|
||||||
@ -127,7 +128,7 @@ class FulltextQueryer:
|
|||||||
q.append(txt)
|
q.append(txt)
|
||||||
query = " ".join(q)
|
query = " ".join(q)
|
||||||
return MatchTextExpr(
|
return MatchTextExpr(
|
||||||
self.query_fields, query, 100
|
self.query_fields, query, 100, {"original_query": original_query}
|
||||||
), keywords
|
), keywords
|
||||||
|
|
||||||
def need_fine_grained_tokenize(tk):
|
def need_fine_grained_tokenize(tk):
|
||||||
@ -212,7 +213,7 @@ class FulltextQueryer:
|
|||||||
if not query:
|
if not query:
|
||||||
query = otxt
|
query = otxt
|
||||||
return MatchTextExpr(
|
return MatchTextExpr(
|
||||||
self.query_fields, query, 100, {"minimum_should_match": min_match}
|
self.query_fields, query, 100, {"minimum_should_match": min_match, "original_query": original_query}
|
||||||
), keywords
|
), keywords
|
||||||
return None, keywords
|
return None, keywords
|
||||||
|
|
||||||
@ -259,6 +260,7 @@ class FulltextQueryer:
|
|||||||
content_tks = [c.strip() for c in content_tks.strip() if c.strip()]
|
content_tks = [c.strip() for c in content_tks.strip() if c.strip()]
|
||||||
tks_w = self.tw.weights(content_tks, preprocess=False)
|
tks_w = self.tw.weights(content_tks, preprocess=False)
|
||||||
|
|
||||||
|
origin_keywords = keywords.copy()
|
||||||
keywords = [f'"{k.strip()}"' for k in keywords]
|
keywords = [f'"{k.strip()}"' for k in keywords]
|
||||||
for tk, w in sorted(tks_w, key=lambda x: x[1] * -1)[:keywords_topn]:
|
for tk, w in sorted(tks_w, key=lambda x: x[1] * -1)[:keywords_topn]:
|
||||||
tk_syns = self.syn.lookup(tk)
|
tk_syns = self.syn.lookup(tk)
|
||||||
@ -274,4 +276,4 @@ class FulltextQueryer:
|
|||||||
keywords.append(f"{tk}^{w}")
|
keywords.append(f"{tk}^{w}")
|
||||||
|
|
||||||
return MatchTextExpr(self.query_fields, " ".join(keywords), 100,
|
return MatchTextExpr(self.query_fields, " ".join(keywords), 100,
|
||||||
{"minimum_should_match": min(3, len(keywords) // 10)})
|
{"minimum_should_match": min(3, len(keywords) / 10), "original_query": " ".join(origin_keywords)})
|
||||||
|
|||||||
1562
rag/utils/ob_conn.py
Normal file
1562
rag/utils/ob_conn.py
Normal file
File diff suppressed because it is too large
Load Diff
68
uv.lock
generated
68
uv.lock
generated
@ -108,6 +108,18 @@ wheels = [
|
|||||||
{ url = "https://mirrors.aliyun.com/pypi/packages/f3/ba/df6e8e1045aebc4778d19b8a3a9bc1808adb1619ba94ca354d9ba17d86c3/aiolimiter-1.2.1-py3-none-any.whl", hash = "sha256:d3f249e9059a20badcb56b61601a83556133655c11d1eb3dd3e04ff069e5f3c7" },
|
{ url = "https://mirrors.aliyun.com/pypi/packages/f3/ba/df6e8e1045aebc4778d19b8a3a9bc1808adb1619ba94ca354d9ba17d86c3/aiolimiter-1.2.1-py3-none-any.whl", hash = "sha256:d3f249e9059a20badcb56b61601a83556133655c11d1eb3dd3e04ff069e5f3c7" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aiomysql"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pymysql" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/e0/302aeffe8d90853556f47f3106b89c16cc2ec2a4d269bdfd82e3f4ae12cc/aiomysql-0.3.2.tar.gz", hash = "sha256:72d15ef5cfc34c03468eb41e1b90adb9fd9347b0b589114bd23ead569a02ac1a", size = 108311, upload-time = "2025-10-22T00:15:21.278Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/af/aae0153c3e28712adaf462328f6c7a3c196a1c1c27b491de4377dd3e6b52/aiomysql-0.3.2-py3-none-any.whl", hash = "sha256:c82c5ba04137d7afd5c693a258bea8ead2aad77101668044143a991e04632eb2", size = 71834, upload-time = "2025-10-22T00:15:15.905Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aiosignal"
|
name = "aiosignal"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -4884,6 +4896,23 @@ wheels = [
|
|||||||
{ url = "https://mirrors.aliyun.com/pypi/packages/d2/53/d23a97e0a2c690d40b165d1062e2c4ccc796be458a1ce59f6ba030434663/pynndescent-0.5.13-py3-none-any.whl", hash = "sha256:69aabb8f394bc631b6ac475a1c7f3994c54adf3f51cd63b2730fefba5771b949" },
|
{ url = "https://mirrors.aliyun.com/pypi/packages/d2/53/d23a97e0a2c690d40b165d1062e2c4ccc796be458a1ce59f6ba030434663/pynndescent-0.5.13-py3-none-any.whl", hash = "sha256:69aabb8f394bc631b6ac475a1c7f3994c54adf3f51cd63b2730fefba5771b949" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyobvector"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "aiomysql" },
|
||||||
|
{ name = "numpy" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "pymysql" },
|
||||||
|
{ name = "sqlalchemy" },
|
||||||
|
{ name = "sqlglot" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/33/adf722744a88eb75b4422129cbc4fe9b05738064ee79762348e285d93520/pyobvector-0.2.18.tar.gz", hash = "sha256:58ca2765ab99de188e99c815aab914ab9efd003cfa1ce9c5f2e41d0e2b4878be", size = 43035, upload-time = "2025-11-05T06:18:36.747Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/1f/73fa42b215722ec36172ac155626db5d2b95ea9f884cf9fb0624492e303b/pyobvector-0.2.18-py3-none-any.whl", hash = "sha256:93e34b7796e4cbc6ad139118d655eb127d1e7a0f5df76df66e25520533a15488", size = 58129, upload-time = "2025-11-05T06:18:35.326Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyodbc"
|
name = "pyodbc"
|
||||||
version = "5.2.0"
|
version = "5.2.0"
|
||||||
@ -5375,6 +5404,7 @@ dependencies = [
|
|||||||
{ name = "pycryptodomex" },
|
{ name = "pycryptodomex" },
|
||||||
{ name = "pyicu" },
|
{ name = "pyicu" },
|
||||||
{ name = "pymysql" },
|
{ name = "pymysql" },
|
||||||
|
{ name = "pyobvector" },
|
||||||
{ name = "pyodbc" },
|
{ name = "pyodbc" },
|
||||||
{ name = "pypandoc" },
|
{ name = "pypandoc" },
|
||||||
{ name = "pypdf" },
|
{ name = "pypdf" },
|
||||||
@ -5534,6 +5564,7 @@ requires-dist = [
|
|||||||
{ name = "pycryptodomex", specifier = "==3.20.0" },
|
{ name = "pycryptodomex", specifier = "==3.20.0" },
|
||||||
{ name = "pyicu", specifier = ">=2.15.3,<3.0.0" },
|
{ name = "pyicu", specifier = ">=2.15.3,<3.0.0" },
|
||||||
{ name = "pymysql", specifier = ">=1.1.1,<2.0.0" },
|
{ name = "pymysql", specifier = ">=1.1.1,<2.0.0" },
|
||||||
|
{ name = "pyobvector", specifier = "==0.2.18" },
|
||||||
{ name = "pyodbc", specifier = ">=5.2.0,<6.0.0" },
|
{ name = "pyodbc", specifier = ">=5.2.0,<6.0.0" },
|
||||||
{ name = "pypandoc", specifier = ">=1.16" },
|
{ name = "pypandoc", specifier = ">=1.16" },
|
||||||
{ name = "pypdf", specifier = "==6.0.0" },
|
{ name = "pypdf", specifier = "==6.0.0" },
|
||||||
@ -6430,6 +6461,43 @@ wheels = [
|
|||||||
{ url = "https://mirrors.aliyun.com/pypi/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331" },
|
{ url = "https://mirrors.aliyun.com/pypi/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sqlalchemy"
|
||||||
|
version = "2.0.44"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f0/f2/840d7b9496825333f532d2e3976b8eadbf52034178aac53630d09fe6e1ef/sqlalchemy-2.0.44.tar.gz", hash = "sha256:0ae7454e1ab1d780aee69fd2aae7d6b8670a581d8847f2d1e0f7ddfbf47e5a22", size = 9819830, upload-time = "2025-10-10T14:39:12.935Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/a7/e9ccfa7eecaf34c6f57d8cb0bb7cbdeeff27017cc0f5d0ca90fdde7a7c0d/sqlalchemy-2.0.44-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c77f3080674fc529b1bd99489378c7f63fcb4ba7f8322b79732e0258f0ea3ce", size = 2137282, upload-time = "2025-10-10T15:36:10.965Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/e1/50bc121885bdf10833a4f65ecbe9fe229a3215f4d65a58da8a181734cae3/sqlalchemy-2.0.44-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26ef74ba842d61635b0152763d057c8d48215d5be9bb8b7604116a059e9985", size = 2127322, upload-time = "2025-10-10T15:36:12.428Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/f2/a8573b7230a3ce5ee4b961a2d510d71b43872513647398e595b744344664/sqlalchemy-2.0.44-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4a172b31785e2f00780eccab00bc240ccdbfdb8345f1e6063175b3ff12ad1b0", size = 3214772, upload-time = "2025-10-10T15:34:15.09Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/d8/c63d8adb6a7edaf8dcb6f75a2b1e9f8577960a1e489606859c4d73e7d32b/sqlalchemy-2.0.44-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9480c0740aabd8cb29c329b422fb65358049840b34aba0adf63162371d2a96e", size = 3214434, upload-time = "2025-10-10T15:47:00.473Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/a6/243d277a4b54fae74d4797957a7320a5c210c293487f931cbe036debb697/sqlalchemy-2.0.44-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:17835885016b9e4d0135720160db3095dc78c583e7b902b6be799fb21035e749", size = 3155365, upload-time = "2025-10-10T15:34:17.932Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/f8/6a39516ddd75429fd4ee5a0d72e4c80639fab329b2467c75f363c2ed9751/sqlalchemy-2.0.44-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cbe4f85f50c656d753890f39468fcd8190c5f08282caf19219f684225bfd5fd2", size = 3178910, upload-time = "2025-10-10T15:47:02.346Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/f0/118355d4ad3c39d9a2f5ee4c7304a9665b3571482777357fa9920cd7a6b4/sqlalchemy-2.0.44-cp310-cp310-win32.whl", hash = "sha256:2fcc4901a86ed81dc76703f3b93ff881e08761c63263c46991081fd7f034b165", size = 2105624, upload-time = "2025-10-10T15:38:15.552Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/83/6ae5f9466f8aa5d0dcebfff8c9c33b98b27ce23292df3b990454b3d434fd/sqlalchemy-2.0.44-cp310-cp310-win_amd64.whl", hash = "sha256:9919e77403a483ab81e3423151e8ffc9dd992c20d2603bf17e4a8161111e55f5", size = 2129240, upload-time = "2025-10-10T15:38:17.175Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/81/15d7c161c9ddf0900b076b55345872ed04ff1ed6a0666e5e94ab44b0163c/sqlalchemy-2.0.44-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fe3917059c7ab2ee3f35e77757062b1bea10a0b6ca633c58391e3f3c6c488dd", size = 2140517, upload-time = "2025-10-10T15:36:15.64Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/d5/4abd13b245c7d91bdf131d4916fd9e96a584dac74215f8b5bc945206a974/sqlalchemy-2.0.44-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:de4387a354ff230bc979b46b2207af841dc8bf29847b6c7dbe60af186d97aefa", size = 2130738, upload-time = "2025-10-10T15:36:16.91Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/3c/8418969879c26522019c1025171cefbb2a8586b6789ea13254ac602986c0/sqlalchemy-2.0.44-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3678a0fb72c8a6a29422b2732fe423db3ce119c34421b5f9955873eb9b62c1e", size = 3304145, upload-time = "2025-10-10T15:34:19.569Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/2d/fdb9246d9d32518bda5d90f4b65030b9bf403a935cfe4c36a474846517cb/sqlalchemy-2.0.44-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cf6872a23601672d61a68f390e44703442639a12ee9dd5a88bbce52a695e46e", size = 3304511, upload-time = "2025-10-10T15:47:05.088Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/fb/40f2ad1da97d5c83f6c1269664678293d3fe28e90ad17a1093b735420549/sqlalchemy-2.0.44-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:329aa42d1be9929603f406186630135be1e7a42569540577ba2c69952b7cf399", size = 3235161, upload-time = "2025-10-10T15:34:21.193Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/cb/7cf4078b46752dca917d18cf31910d4eff6076e5b513c2d66100c4293d83/sqlalchemy-2.0.44-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:70e03833faca7166e6a9927fbee7c27e6ecde436774cd0b24bbcc96353bce06b", size = 3261426, upload-time = "2025-10-10T15:47:07.196Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/3b/55c09b285cb2d55bdfa711e778bdffdd0dc3ffa052b0af41f1c5d6e582fa/sqlalchemy-2.0.44-cp311-cp311-win32.whl", hash = "sha256:253e2f29843fb303eca6b2fc645aca91fa7aa0aa70b38b6950da92d44ff267f3", size = 2105392, upload-time = "2025-10-10T15:38:20.051Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/23/907193c2f4d680aedbfbdf7bf24c13925e3c7c292e813326c1b84a0b878e/sqlalchemy-2.0.44-cp311-cp311-win_amd64.whl", hash = "sha256:7a8694107eb4308a13b425ca8c0e67112f8134c846b6e1f722698708741215d5", size = 2130293, upload-time = "2025-10-10T15:38:21.601Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/c4/59c7c9b068e6813c898b771204aad36683c96318ed12d4233e1b18762164/sqlalchemy-2.0.44-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72fea91746b5890f9e5e0997f16cbf3d53550580d76355ba2d998311b17b2250", size = 2139675, upload-time = "2025-10-10T16:03:31.064Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/ae/eeb0920537a6f9c5a3708e4a5fc55af25900216bdb4847ec29cfddf3bf3a/sqlalchemy-2.0.44-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:585c0c852a891450edbb1eaca8648408a3cc125f18cf433941fa6babcc359e29", size = 2127726, upload-time = "2025-10-10T16:03:35.934Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/d5/2ebbabe0379418eda8041c06b0b551f213576bfe4c2f09d77c06c07c8cc5/sqlalchemy-2.0.44-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b94843a102efa9ac68a7a30cd46df3ff1ed9c658100d30a725d10d9c60a2f44", size = 3327603, upload-time = "2025-10-10T15:35:28.322Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/e5/5aa65852dadc24b7d8ae75b7efb8d19303ed6ac93482e60c44a585930ea5/sqlalchemy-2.0.44-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:119dc41e7a7defcefc57189cfa0e61b1bf9c228211aba432b53fb71ef367fda1", size = 3337842, upload-time = "2025-10-10T15:43:45.431Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/92/648f1afd3f20b71e880ca797a960f638d39d243e233a7082c93093c22378/sqlalchemy-2.0.44-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0765e318ee9179b3718c4fd7ba35c434f4dd20332fbc6857a5e8df17719c24d7", size = 3264558, upload-time = "2025-10-10T15:35:29.93Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/cf/e27d7ee61a10f74b17740918e23cbc5bc62011b48282170dc4c66da8ec0f/sqlalchemy-2.0.44-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2e7b5b079055e02d06a4308d0481658e4f06bc7ef211567edc8f7d5dce52018d", size = 3301570, upload-time = "2025-10-10T15:43:48.407Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/3d/3116a9a7b63e780fb402799b6da227435be878b6846b192f076d2f838654/sqlalchemy-2.0.44-cp312-cp312-win32.whl", hash = "sha256:846541e58b9a81cce7dee8329f352c318de25aa2f2bbe1e31587eb1f057448b4", size = 2103447, upload-time = "2025-10-10T15:03:21.678Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/83/24690e9dfc241e6ab062df82cc0df7f4231c79ba98b273fa496fb3dd78ed/sqlalchemy-2.0.44-cp312-cp312-win_amd64.whl", hash = "sha256:7cbcb47fd66ab294703e1644f78971f6f2f1126424d2b300678f419aa73c7b6e", size = 2130912, upload-time = "2025-10-10T15:03:24.656Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/5e/6a29fa884d9fb7ddadf6b69490a9d45fded3b38541713010dad16b77d015/sqlalchemy-2.0.44-py3-none-any.whl", hash = "sha256:19de7ca1246fbef9f9d1bff8f1ab25641569df226364a0e40457dc5457c54b05", size = 1928718, upload-time = "2025-10-10T15:29:45.32Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlglot"
|
name = "sqlglot"
|
||||||
version = "27.29.0"
|
version = "27.29.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user