Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jobs:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
mongodb-version: ['7.0', '8.0']
# Test against representative SQLAlchemy series (1.x and 2.x)
sqlalchemy-version: ['1.4.*', '2.*']

services:
mongodb:
Expand Down Expand Up @@ -41,9 +43,9 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-py${{ matrix.python-version }}-mongo${{ matrix.mongodb-version }}-pip-${{ hashFiles('**/requirements-test.txt', 'pyproject.toml') }}
key: ${{ runner.os }}-py${{ matrix.python-version }}-mongo${{ matrix.mongodb-version }}-sqlalchemy-${{ matrix.sqlalchemy-version }}-pip-${{ hashFiles('**/requirements-test.txt', 'pyproject.toml') }}
restore-keys: |
${{ runner.os }}-py${{ matrix.python-version }}-mongo${{ matrix.mongodb-version }}-pip-
${{ runner.os }}-py${{ matrix.python-version }}-mongo${{ matrix.mongodb-version }}-sqlalchemy-${{ matrix.sqlalchemy-version }}-pip-

- name: Install MongoDB shell
run: |
Expand All @@ -55,6 +57,9 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Install the target SQLAlchemy version for this matrix entry first to ensure
# tests run against both 1.x and 2.x series.
pip install "SQLAlchemy==${{ matrix.sqlalchemy-version }}"
pip install -r requirements-test.txt
pip install black isort

Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ include requirements-test.txt

# Include configuration files
include pyproject.toml
include .flake8

# Exclude unnecessary files
global-exclude *.pyc
Expand Down
88 changes: 15 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
# PyMongoSQL

[![PyPI](https://img.shields.io/pypi/v/pymongosql)](https://pypi.org/project/pymongosql/)
[![Test](https://github.com/passren/PyMongoSQL/actions/workflows/ci.yml/badge.svg)](https://github.com/passren/PyMongoSQL/actions/workflows/ci.yml)
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![codecov](https://codecov.io/gh/passren/PyMongoSQL/branch/main/graph/badge.svg?token=2CTRL80NP2)](https://codecov.io/gh/passren/PyMongoSQL)
[![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](https://github.com/passren/PyMongoSQL/blob/0.1.2/LICENSE)
[![Python Version](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![MongoDB](https://img.shields.io/badge/MongoDB-7.0+-green.svg)](https://www.mongodb.com/)
[![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-1.4+_2.0+-darkgreen.svg)](https://www.sqlalchemy.org/)

PyMongoSQL is a Python [DB API 2.0 (PEP 249)](https://www.python.org/dev/peps/pep-0249/) client for [MongoDB](https://www.mongodb.com/). It provides a familiar SQL interface to MongoDB, allowing developers to use SQL queries to interact with MongoDB collections.
PyMongoSQL is a Python [DB API 2.0 (PEP 249)](https://www.python.org/dev/peps/pep-0249/) client for [MongoDB](https://www.mongodb.com/). It provides a familiar SQL interface to MongoDB, allowing developers to use SQL to interact with MongoDB collections.

## Objectives

PyMongoSQL implements the DB API 2.0 interfaces to provide SQL-like access to MongoDB. The project aims to:

- Bridge the gap between SQL and NoSQL by providing SQL query capabilities for MongoDB
- Bridge the gap between SQL and NoSQL by providing SQL capabilities for MongoDB
- Support standard SQL DQL (Data Query Language) operations including SELECT statements with WHERE, ORDER BY, and LIMIT clauses
- Provide seamless integration with existing Python applications that expect DB API 2.0 compliance
- Enable easy migration from traditional SQL databases to MongoDB
- Support field aliasing and projection mapping for flexible result set handling
- Maintain high performance through direct `db.command()` execution instead of high-level APIs

## Features

- **DB API 2.0 Compliant**: Full compatibility with Python Database API 2.0 specification
- **SQLAlchemy Integration**: Complete ORM and Core support with dedicated MongoDB dialect
- **SQL Query Support**: SELECT statements with WHERE conditions, field selection, and aliases
- **MongoDB Native Integration**: Direct `db.command()` execution for optimal performance
- **Connection String Support**: MongoDB URI format for easy configuration
- **Result Set Handling**: Support for `fetchone()`, `fetchmany()`, and `fetchall()` operations
- **Field Aliasing**: SQL-style field aliases with automatic projection mapping
- **Context Manager Support**: Automatic resource management with `with` statements
- **Transaction Ready**: Architecture designed for future DML operation support (INSERT, UPDATE, DELETE)

## Requirements

- **Python**: 3.9, 3.10, 3.11, 3.12, 3.13+
- **MongoDB**: 4.0+
- **MongoDB**: 7.0+

## Dependencies

Expand All @@ -43,6 +40,11 @@ PyMongoSQL implements the DB API 2.0 interfaces to provide SQL-like access to Mo
- **ANTLR4** (SQL Parser Runtime)
- antlr4-python3-runtime >= 4.13.0

### Optional Dependencies

- **SQLAlchemy** (for ORM/Core support)
- sqlalchemy >= 1.4.0 (SQLAlchemy 1.4+ and 2.0+ supported)

## Installation

```bash
Expand All @@ -67,7 +69,7 @@ from pymongosql import connect
# Connect to MongoDB
connection = connect(
host="mongodb://localhost:27017",
database="test_db"
database="database"
)

cursor = connection.cursor()
Expand Down Expand Up @@ -97,44 +99,19 @@ for row in cursor:
```python
from pymongosql import connect

with connect(host="mongodb://localhost:27017", database="mydb") as conn:
with connect(host="mongodb://localhost:27017/database") as conn:
with conn.cursor() as cursor:
cursor.execute('SELECT COUNT(*) as total FROM users')
result = cursor.fetchone()
print(f"Total users: {result['total']}")
```

### Field Aliases and Projections

```python
from pymongosql import connect

connection = connect(host="mongodb://localhost:27017", database="ecommerce")
cursor = connection.cursor()

# Use field aliases for cleaner result sets
cursor.execute('''
SELECT
name AS product_name,
price AS cost,
category AS product_type
FROM products
WHERE in_stock = true
ORDER BY price DESC
LIMIT 10
''')

products = cursor.fetchall()
for product in products:
print(f"{product['product_name']}: ${product['cost']}")
```

### Query with Parameters

```python
from pymongosql import connect

connection = connect(host="mongodb://localhost:27017", database="blog")
connection = connect(host="mongodb://localhost:27017/database")
cursor = connection.cursor()

# Parameterized queries for security
Expand All @@ -159,7 +136,6 @@ while users:
### SELECT Statements
- Field selection: `SELECT name, age FROM users`
- Wildcards: `SELECT * FROM products`
- Field aliases: `SELECT name AS user_name, age AS user_age FROM users`

### WHERE Clauses
- Equality: `WHERE name = 'John'`
Expand All @@ -171,15 +147,6 @@ while users:
- LIMIT: `LIMIT 10`
- Combined: `ORDER BY created_at DESC LIMIT 5`

## Architecture

PyMongoSQL uses a multi-layer architecture:

1. **SQL Parser**: Built with ANTLR4 for robust SQL parsing
2. **Query Planner**: Converts SQL AST to MongoDB query plans
3. **Command Executor**: Direct `db.command()` execution for performance
4. **Result Processor**: Handles projection mapping and result set iteration

## Connection Options

```python
Expand All @@ -201,31 +168,6 @@ print(conn.database_name) # Database name
print(conn.is_connected) # Connection status
```

## Error Handling

```python
from pymongosql import connect
from pymongosql.error import ProgrammingError, SqlSyntaxError

try:
connection = connect(host="mongodb://localhost:27017", database="test")
cursor = connection.cursor()
cursor.execute("INVALID SQL SYNTAX")
except SqlSyntaxError as e:
print(f"SQL syntax error: {e}")
except ProgrammingError as e:
print(f"Programming error: {e}")
```

## Development Status

PyMongoSQL is currently focused on DQL (Data Query Language) operations. Future releases will include:

- **DML Operations**: INSERT, UPDATE, DELETE statements
- **Advanced SQL Features**: JOINs, subqueries, aggregations
- **Schema Operations**: CREATE/DROP collection commands
- **Transaction Support**: Multi-document ACID transactions

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Expand Down
14 changes: 13 additions & 1 deletion pymongosql/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
if TYPE_CHECKING:
from .connection import Connection

__version__: str = "0.1.2"
__version__: str = "0.2.0"

# Globals https://www.python.org/dev/peps/pep-0249/#globals
apilevel: str = "2.0"
Expand Down Expand Up @@ -40,3 +40,15 @@ def connect(*args, **kwargs) -> "Connection":
from .connection import Connection

return Connection(*args, **kwargs)


# SQLAlchemy integration (optional)
# For SQLAlchemy functionality, import from pymongosql.sqlalchemy_mongodb:
# from pymongosql.sqlalchemy_mongodb import create_engine_url, create_engine_from_mongodb_uri
try:
from .sqlalchemy_mongodb import __sqlalchemy_version__, __supports_sqlalchemy_2x__, __supports_sqlalchemy__
except ImportError:
# SQLAlchemy integration not available
__sqlalchemy_version__ = None
__supports_sqlalchemy__ = False
__supports_sqlalchemy_2x__ = False
Loading