# SQL Optimizer Python Package
Python обертка для Java-оптимизатора SQL запросов на базе Apache Calcite.
## Возможности
- **Python API**: Простой в использовании Python интерфейс для оптимизации SQL
- **Java Backend**: Использует мощь Apache Calcite для оптимизации запросов
- **Поддержка метаданных**: Определение пользовательских схем таблиц и типов данных
- **Правила оптимизации**: Применение пользовательских стратегий оптимизации
- **CLI интерфейс**: Командная строка для быстрой оптимизации
- **Автономный пакет**: Включает Java JAR файл - не требует отдельной установки Java
## Требования
- Python 3.8 или выше
- Java 1.8 или выше (автоопределяется)
## Установка
### Из Wheel пакета
```bash
pip install sql-optimizer-1.0.0-py3-none-any.whl
```
### Из исходного кода
```bash
# Клонирование репозитория
git clone https://github.com/sql-optimizer/sql-optimizer-python.git
cd sql-optimizer-python
# Установка в режиме разработки
pip install -e .
```
## Quick Start
### Basic Usage
```python
from sql_optimizer_python import SqlOptimizer
# Initialize optimizer
optimizer = SqlOptimizer()
# Optimize a simple query
result = optimizer.optimize("SELECT * FROM employees")
print(result)
```
### With Custom Metadata
```python
# Define table metadata
metadata = {
"custom_table": {
"columns": {
"id": {"type": "INTEGER"},
"name": {"type": "VARCHAR"},
"age": {"type": "INTEGER"}
},
"rowCount": 1000
}
}
# Optimize with metadata
result = optimizer.optimize(
"SELECT * FROM custom_table WHERE age > 25",
metadata=metadata
)
```
### With Optimization Rules
```python
from sql_optimizer_python import OptimizationRule
# Create optimization rules
rules = [
OptimizationRule(
name="push_down_filter",
description="Push filter operations down",
priority=100,
conditions=[{"type": "node_type", "operator": "contains", "value": "TableScan"}],
transformations=[{"action": "push_down", "target": "filter", "cost_reduction": 25.0}]
)
]
# Optimize with rules
result = optimizer.optimize(
"SELECT * FROM employees WHERE salary > 50000",
optimization_rules=rules
)
```
## Command Line Interface
### Basic Optimization
```bash
sql-optimizer "SELECT * FROM employees"
```
### With Metadata File
```bash
sql-optimizer "SELECT * FROM custom_table" --metadata-file examples/custom_table_metadata.json
```
### With Optimization Rules
```bash
sql-optimizer "SELECT * FROM employees" --rules-file examples/basic_optimization_rules.json
```
### Check Java Runtime
```bash
sql-optimizer --check-java
```
### Pretty Print Output
```bash
sql-optimizer "SELECT * FROM employees" --pretty
```
## API Reference
### SqlOptimizer
Main class for SQL query optimization.
```python
class SqlOptimizer:
def __init__(self, java_home: Optional[str] = None)
def optimize(self, sql_query: str,
metadata: Optional[Union[Dict, str]] = None,
optimization_rules: Optional[Union[List[OptimizationRule], str]] = None,
metadata_file: Optional[str] = None,
rules_file: Optional[str] = None) -> Dict[str, Any]
def optimize_from_files(self, sql_query: str,
metadata_file: Optional[str] = None,
rules_file: Optional[str] = None) -> Dict[str, Any]
def get_version(self) -> str
def get_java_info(self) -> Dict[str, str]
```
### OptimizationRule
Represents an optimization rule.
```python
class OptimizationRule:
def __init__(self, name: str, description: str, priority: int = 100,
enabled: bool = True, conditions: Optional[List[Dict]] = None,
transformations: Optional[List[Dict]] = None,
metadata: Optional[Dict] = None)
def to_dict(self) -> Dict[str, Any]
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'OptimizationRule'
```
### OptimizationEngine
Manages optimization rules.
```python
class OptimizationEngine:
def __init__(self)
def add_rule(self, rule: OptimizationRule) -> None
def add_rules_from_file(self, file_path: str) -> None
def add_rules_from_json(self, rules_json: str) -> None
def get_rules_json(self) -> str
def clear_rules(self) -> None
```
## Metadata Format
Table metadata is defined in JSON format:
```json
{
"table_name": {
"columns": {
"column_name": {
"type": "INTEGER|VARCHAR|DOUBLE|BOOLEAN",
"nullable": true|false
}
},
"rowCount": 1000
}
}
```
## Optimization Rules Format
Optimization rules are defined in JSON format:
```json
[
{
"name": "rule_name",
"description": "Rule description",
"priority": 100,
"enabled": true,
"conditions": [
{
"type": "node_type|table_name|cost_threshold|field_count",
"operator": "equals|contains|greater_than|less_than",
"value": "value",
"negated": false
}
],
"transformations": [
{
"action": "push_down|reorder|optimize|prune|replace",
"target": "filter|projection|join|scan|aggregate",
"parameters": {},
"cost_reduction": 25.0
}
],
"metadata": {
"category": "filter_optimization",
"author": "system"
}
}
]
```
## Output Format
The optimizer returns a JSON object with the following structure:
```json
{
"originalQuery": "SELECT * FROM employees",
"metadata": { /* table metadata if provided */ },
"optimizedPlan": {
"relType": "LogicalTableScan",
"rowType": {
"fieldCount": 4,
"nullable": false,
"fields": {
"id": "INTEGER",
"name": "VARCHAR",
"department": "VARCHAR",
"salary": "INTEGER"
}
},
"cost": {
"cpu": 101.0,
"io": 0.0,
"rows": 100.0,
"infinite": false
}
},
"optimizationStats": {
"appliedRules": ["push_down_filter"],
"totalRulesConsidered": 3,
"optimizationDetails": {}
},
"explanation": "LogicalTableScan(table=[[TEST, employees]])"
}
```
## Examples
### Example 1: Basic Query Optimization
```python
from sql_optimizer_python import SqlOptimizer
optimizer = SqlOptimizer()
result = optimizer.optimize("SELECT * FROM employees WHERE salary > 50000")
print(result["optimizedPlan"]["relType"])
```
### Example 2: Custom Table with Metadata
```python
metadata = {
"users": {
"columns": {
"id": {"type": "INTEGER"},
"username": {"type": "VARCHAR"},
"email": {"type": "VARCHAR"},
"active": {"type": "BOOLEAN"}
},
"rowCount": 10000
}
}
result = optimizer.optimize(
"SELECT username, email FROM users WHERE active = true",
metadata=metadata
)
```
### Example 3: Custom Optimization Rules
```python
from sql_optimizer_python import OptimizationRule
rules = [
OptimizationRule(
name="index_scan_optimization",
description="Use index scan for large tables",
priority=80,
conditions=[
{"type": "node_type", "operator": "equals", "value": "LogicalTableScan"},
{"type": "cost_threshold", "operator": "greater_than", "value": 1000.0}
],
transformations=[
{"action": "optimize", "target": "scan", "cost_reduction": 50.0}
]
)
]
result = optimizer.optimize(
"SELECT * FROM large_table",
optimization_rules=rules
)
```
## Error Handling
The package provides custom exceptions for different error types:
```python
from sql_optimizer_python import (
SqlOptimizerError, JavaRuntimeError, OptimizationError,
MetadataError, RulesError
)
try:
result = optimizer.optimize("SELECT * FROM table")
except JavaRuntimeError as e:
print(f"Java runtime issue: {e}")
except OptimizationError as e:
print(f"Optimization failed: {e}")
except MetadataError as e:
print(f"Metadata error: {e}")
except RulesError as e:
print(f"Rules error: {e}")
```
## Development
### Running Tests
```bash
pytest tests/
```
### Building Wheel
```bash
python setup.py bdist_wheel
```
### Installing in Development Mode
```bash
pip install -e .
```
## License
MIT License - see LICENSE file for details.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
## Support
- Documentation: https://sql-optimizer-python.readthedocs.io/
- Issues: https://github.com/sql-optimizer/sql-optimizer-python/issues
- Discussions: https://github.com/sql-optimizer/sql-optimizer-python/discussions
Raw data
{
"_id": null,
"home_page": "https://github.com/sql-optimizer/sql-optimizer-python",
"name": "sql-optimizer",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "SQL Optimizer Team <team@sql-optimizer.com>",
"keywords": "sql, optimizer, calcite, java, database, query, optimization",
"author": "SQL Optimizer Team",
"author_email": "SQL Optimizer Team <team@sql-optimizer.com>",
"download_url": null,
"platform": null,
"description": "# SQL Optimizer Python Package\n\nPython \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f Java-\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0431\u0430\u0437\u0435 Apache Calcite.\n\n## \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n\n- **Python API**: \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Python \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 SQL\n- **Java Backend**: \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043c\u043e\u0449\u044c Apache Calcite \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\n- **\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445**: \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0441\u0445\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445\n- **\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438**: \u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438\n- **CLI \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441**: \u041a\u043e\u043c\u0430\u043d\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438\n- **\u0410\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442**: \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 Java JAR \u0444\u0430\u0439\u043b - \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Java\n\n## \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\n\n- Python 3.8 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435\n- Java 1.8 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435 (\u0430\u0432\u0442\u043e\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f)\n\n## \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\n\n### \u0418\u0437 Wheel \u043f\u0430\u043a\u0435\u0442\u0430\n\n```bash\npip install sql-optimizer-1.0.0-py3-none-any.whl\n```\n\n### \u0418\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430\n\n```bash\n# \u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\ngit clone https://github.com/sql-optimizer/sql-optimizer-python.git\ncd sql-optimizer-python\n\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438\npip install -e .\n```\n\n## Quick Start\n\n### Basic Usage\n\n```python\nfrom sql_optimizer_python import SqlOptimizer\n\n# Initialize optimizer\noptimizer = SqlOptimizer()\n\n# Optimize a simple query\nresult = optimizer.optimize(\"SELECT * FROM employees\")\nprint(result)\n```\n\n### With Custom Metadata\n\n```python\n# Define table metadata\nmetadata = {\n \"custom_table\": {\n \"columns\": {\n \"id\": {\"type\": \"INTEGER\"},\n \"name\": {\"type\": \"VARCHAR\"},\n \"age\": {\"type\": \"INTEGER\"}\n },\n \"rowCount\": 1000\n }\n}\n\n# Optimize with metadata\nresult = optimizer.optimize(\n \"SELECT * FROM custom_table WHERE age > 25\",\n metadata=metadata\n)\n```\n\n### With Optimization Rules\n\n```python\nfrom sql_optimizer_python import OptimizationRule\n\n# Create optimization rules\nrules = [\n OptimizationRule(\n name=\"push_down_filter\",\n description=\"Push filter operations down\",\n priority=100,\n conditions=[{\"type\": \"node_type\", \"operator\": \"contains\", \"value\": \"TableScan\"}],\n transformations=[{\"action\": \"push_down\", \"target\": \"filter\", \"cost_reduction\": 25.0}]\n )\n]\n\n# Optimize with rules\nresult = optimizer.optimize(\n \"SELECT * FROM employees WHERE salary > 50000\",\n optimization_rules=rules\n)\n```\n\n## Command Line Interface\n\n### Basic Optimization\n\n```bash\nsql-optimizer \"SELECT * FROM employees\"\n```\n\n### With Metadata File\n\n```bash\nsql-optimizer \"SELECT * FROM custom_table\" --metadata-file examples/custom_table_metadata.json\n```\n\n### With Optimization Rules\n\n```bash\nsql-optimizer \"SELECT * FROM employees\" --rules-file examples/basic_optimization_rules.json\n```\n\n### Check Java Runtime\n\n```bash\nsql-optimizer --check-java\n```\n\n### Pretty Print Output\n\n```bash\nsql-optimizer \"SELECT * FROM employees\" --pretty\n```\n\n## API Reference\n\n### SqlOptimizer\n\nMain class for SQL query optimization.\n\n```python\nclass SqlOptimizer:\n def __init__(self, java_home: Optional[str] = None)\n \n def optimize(self, sql_query: str, \n metadata: Optional[Union[Dict, str]] = None,\n optimization_rules: Optional[Union[List[OptimizationRule], str]] = None,\n metadata_file: Optional[str] = None,\n rules_file: Optional[str] = None) -> Dict[str, Any]\n \n def optimize_from_files(self, sql_query: str, \n metadata_file: Optional[str] = None,\n rules_file: Optional[str] = None) -> Dict[str, Any]\n \n def get_version(self) -> str\n def get_java_info(self) -> Dict[str, str]\n```\n\n### OptimizationRule\n\nRepresents an optimization rule.\n\n```python\nclass OptimizationRule:\n def __init__(self, name: str, description: str, priority: int = 100, \n enabled: bool = True, conditions: Optional[List[Dict]] = None,\n transformations: Optional[List[Dict]] = None, \n metadata: Optional[Dict] = None)\n \n def to_dict(self) -> Dict[str, Any]\n @classmethod\n def from_dict(cls, data: Dict[str, Any]) -> 'OptimizationRule'\n```\n\n### OptimizationEngine\n\nManages optimization rules.\n\n```python\nclass OptimizationEngine:\n def __init__(self)\n \n def add_rule(self, rule: OptimizationRule) -> None\n def add_rules_from_file(self, file_path: str) -> None\n def add_rules_from_json(self, rules_json: str) -> None\n def get_rules_json(self) -> str\n def clear_rules(self) -> None\n```\n\n## Metadata Format\n\nTable metadata is defined in JSON format:\n\n```json\n{\n \"table_name\": {\n \"columns\": {\n \"column_name\": {\n \"type\": \"INTEGER|VARCHAR|DOUBLE|BOOLEAN\",\n \"nullable\": true|false\n }\n },\n \"rowCount\": 1000\n }\n}\n```\n\n## Optimization Rules Format\n\nOptimization rules are defined in JSON format:\n\n```json\n[\n {\n \"name\": \"rule_name\",\n \"description\": \"Rule description\",\n \"priority\": 100,\n \"enabled\": true,\n \"conditions\": [\n {\n \"type\": \"node_type|table_name|cost_threshold|field_count\",\n \"operator\": \"equals|contains|greater_than|less_than\",\n \"value\": \"value\",\n \"negated\": false\n }\n ],\n \"transformations\": [\n {\n \"action\": \"push_down|reorder|optimize|prune|replace\",\n \"target\": \"filter|projection|join|scan|aggregate\",\n \"parameters\": {},\n \"cost_reduction\": 25.0\n }\n ],\n \"metadata\": {\n \"category\": \"filter_optimization\",\n \"author\": \"system\"\n }\n }\n]\n```\n\n## Output Format\n\nThe optimizer returns a JSON object with the following structure:\n\n```json\n{\n \"originalQuery\": \"SELECT * FROM employees\",\n \"metadata\": { /* table metadata if provided */ },\n \"optimizedPlan\": {\n \"relType\": \"LogicalTableScan\",\n \"rowType\": {\n \"fieldCount\": 4,\n \"nullable\": false,\n \"fields\": {\n \"id\": \"INTEGER\",\n \"name\": \"VARCHAR\",\n \"department\": \"VARCHAR\",\n \"salary\": \"INTEGER\"\n }\n },\n \"cost\": {\n \"cpu\": 101.0,\n \"io\": 0.0,\n \"rows\": 100.0,\n \"infinite\": false\n }\n },\n \"optimizationStats\": {\n \"appliedRules\": [\"push_down_filter\"],\n \"totalRulesConsidered\": 3,\n \"optimizationDetails\": {}\n },\n \"explanation\": \"LogicalTableScan(table=[[TEST, employees]])\"\n}\n```\n\n## Examples\n\n### Example 1: Basic Query Optimization\n\n```python\nfrom sql_optimizer_python import SqlOptimizer\n\noptimizer = SqlOptimizer()\nresult = optimizer.optimize(\"SELECT * FROM employees WHERE salary > 50000\")\nprint(result[\"optimizedPlan\"][\"relType\"])\n```\n\n### Example 2: Custom Table with Metadata\n\n```python\nmetadata = {\n \"users\": {\n \"columns\": {\n \"id\": {\"type\": \"INTEGER\"},\n \"username\": {\"type\": \"VARCHAR\"},\n \"email\": {\"type\": \"VARCHAR\"},\n \"active\": {\"type\": \"BOOLEAN\"}\n },\n \"rowCount\": 10000\n }\n}\n\nresult = optimizer.optimize(\n \"SELECT username, email FROM users WHERE active = true\",\n metadata=metadata\n)\n```\n\n### Example 3: Custom Optimization Rules\n\n```python\nfrom sql_optimizer_python import OptimizationRule\n\nrules = [\n OptimizationRule(\n name=\"index_scan_optimization\",\n description=\"Use index scan for large tables\",\n priority=80,\n conditions=[\n {\"type\": \"node_type\", \"operator\": \"equals\", \"value\": \"LogicalTableScan\"},\n {\"type\": \"cost_threshold\", \"operator\": \"greater_than\", \"value\": 1000.0}\n ],\n transformations=[\n {\"action\": \"optimize\", \"target\": \"scan\", \"cost_reduction\": 50.0}\n ]\n )\n]\n\nresult = optimizer.optimize(\n \"SELECT * FROM large_table\",\n optimization_rules=rules\n)\n```\n\n## Error Handling\n\nThe package provides custom exceptions for different error types:\n\n```python\nfrom sql_optimizer_python import (\n SqlOptimizerError, JavaRuntimeError, OptimizationError, \n MetadataError, RulesError\n)\n\ntry:\n result = optimizer.optimize(\"SELECT * FROM table\")\nexcept JavaRuntimeError as e:\n print(f\"Java runtime issue: {e}\")\nexcept OptimizationError as e:\n print(f\"Optimization failed: {e}\")\nexcept MetadataError as e:\n print(f\"Metadata error: {e}\")\nexcept RulesError as e:\n print(f\"Rules error: {e}\")\n```\n\n## Development\n\n### Running Tests\n\n```bash\npytest tests/\n```\n\n### Building Wheel\n\n```bash\npython setup.py bdist_wheel\n```\n\n### Installing in Development Mode\n\n```bash\npip install -e .\n```\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests\n5. Submit a pull request\n\n## Support\n\n- Documentation: https://sql-optimizer-python.readthedocs.io/\n- Issues: https://github.com/sql-optimizer/sql-optimizer-python/issues\n- Discussions: https://github.com/sql-optimizer/sql-optimizer-python/discussions\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f Java-\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0431\u0430\u0437\u0435 Apache Calcite",
"version": "1.0.3",
"project_urls": {
"Bug Tracker": "https://github.com/sql-optimizer/sql-optimizer-python/issues",
"Documentation": "https://sql-optimizer-python.readthedocs.io/",
"Homepage": "https://github.com/sql-optimizer/sql-optimizer-python",
"Repository": "https://github.com/sql-optimizer/sql-optimizer-python"
},
"split_keywords": [
"sql",
" optimizer",
" calcite",
" java",
" database",
" query",
" optimization"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "cda7d2556d1c30695828feda433c9aa29281d562072009e819e7a10b569821c1",
"md5": "11eed3597e949b44498028b0a5b0b6ca",
"sha256": "07c16a9fa9741a2a5a14160587924de8f4009ea0c68953dcdee73a07c75322c9"
},
"downloads": -1,
"filename": "sql_optimizer-1.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "11eed3597e949b44498028b0a5b0b6ca",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 18606576,
"upload_time": "2025-08-23T23:37:01",
"upload_time_iso_8601": "2025-08-23T23:37:01.752529Z",
"url": "https://files.pythonhosted.org/packages/cd/a7/d2556d1c30695828feda433c9aa29281d562072009e819e7a10b569821c1/sql_optimizer-1.0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-23 23:37:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sql-optimizer",
"github_project": "sql-optimizer-python",
"github_not_found": true,
"lcname": "sql-optimizer"
}