Skip to content

Commit

Permalink
Merge pull request #7 from baluyotraf/feature/pre-release
Browse files Browse the repository at this point in the history
Prepare repository for first release
  • Loading branch information
baluyotraf authored Mar 21, 2024
2 parents 2a3c899 + d496c3b commit f9e1ebe
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 34 deletions.
13 changes: 2 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
[![qa](https://github.com/baluyotraf/altqq/actions/workflows/qa.yml/badge.svg)](https://github.com/baluyotraf/altqq/actions/workflows/qa.yml)
[![release](https://github.com/baluyotraf/altqq/actions/workflows/release.yml/badge.svg)](https://github.com/baluyotraf/altqq/actions/workflows/release.yml)

# Alternative Queries

Alternative queries is a library created to help with handcrafted SQL queries.
It works by providing a class that represent the queries, with parameters type
checked by `Pydantic`.

The library is currently still in development and has an alpha release.

## Installation

The library is available in PyPI
Expand Down Expand Up @@ -128,12 +128,3 @@ Running the code above should give the result below:

['arietta', 20]
```

## Road Map

Below is the list of things planned for the library

- Documentation Page
- Tests
- Expansion of Supported Version
- Support for other Python Database Tooling
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ convention = "google"

[tool.poetry]
name = "altqq"
version = "0.0.1a2"
description = "Alternative Queries: Typed and Composable Tool for Handwritten SQL"
version = "0.0.1"
description = "Alternative Queries: Typed and Reusable Handcrafted SQL"
authors = ["baluyotraf <baluyotraf@outlook.com>"]
maintainers = ["baluyotraf <baluyotraf@outlook.com>"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions src/altqq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Main entry point for the altqq library."""

from altqq.structs import Calculated as Calculated
from altqq.structs import Query
from altqq.translators.plain_text import PlainTextTranslator
from altqq.translators.pyodbc import PyODBCQuery, PyODBCTranslator
Expand Down
8 changes: 6 additions & 2 deletions src/altqq/structs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Structures used for defining queries."""

import dataclasses as dc
from typing import Any, ClassVar, Dict, Tuple

import pydantic.dataclasses as dc
import pydantic.dataclasses as pdc
from typing_extensions import dataclass_transform

QUERY_ATTRIB = "__query__"
Expand Down Expand Up @@ -42,7 +43,7 @@ def __new__(cls, name: str, bases: Tuple[type, ...], dct: Dict[str, Any]):
dataclass = super().__new__(cls, name, bases, dct)
if not cls._check_query_attribute(dataclass, dct):
raise ValueError(f"A string {QUERY_ATTRIB} must be provided")
return dc.dataclass(dataclass)
return pdc.dataclass(dataclass)


class Query(metaclass=QueryMeta):
Expand All @@ -53,3 +54,6 @@ class metaclass.
"""

__query__: ClassVar[str]


Calculated = dc.field(init=False)
68 changes: 59 additions & 9 deletions tests/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


@dc.dataclass
class TestQuery:
class SampleQuery:
"""Defines the conversion of query to different translations."""

query: altqq.Query
Expand All @@ -32,7 +32,7 @@ class OrderQuery(altqq.Query):
"""Test query that orders a query."""

__query__ = """
SELECT * FROM ({subquery}) AS tbl
SELECT * FROM ( {subquery} ) AS tbl
ORDER BY "{order_column}" {order}
"""

Expand All @@ -45,21 +45,71 @@ class UnionAllQuery(altqq.Query):
"""Test query that union all two queries."""

__query__ = """
SELECT * FROM ({query1}) AS tbl1
SELECT * FROM ( {query1} ) AS tbl1
UNION ALL
SELECT * FROM ({query2}) AS tbl2
SELECT * FROM ( {query2} ) AS tbl2
"""

query1: altqq.Query
query2: altqq.Query


TEST_DATA = [
TestQuery(
SelectTableByFilter("Users", "name", "arietta"),
SampleQuery(
SelectTableByFilter("Users", "age", 25),
pyodbc=altqq.PyODBCQuery(
query="""SELECT * FROM "Users" WHERE "name" = ?""", parameters=["arietta"]
query="""
SELECT * FROM "Users" WHERE "age" = ?
""",
parameters=[25],
),
plain_text="""SELECT * FROM "Users" WHERE "name" = 'arietta'""",
)
plain_text="""
SELECT * FROM "Users" WHERE "age" = 25
""",
),
SampleQuery(
OrderQuery(SelectTableByFilter("Users", "last_name", "Fine"), "age", "asc"),
pyodbc=altqq.PyODBCQuery(
query="""
SELECT * FROM (
SELECT * FROM "Users" WHERE "last_name" = ?
) AS tbl
ORDER BY "age" asc
""",
parameters=["Fine"],
),
plain_text="""
SELECT * FROM (
SELECT * FROM "Users" WHERE "last_name" = 'Fine'
) AS tbl
ORDER BY "age" asc
""",
),
SampleQuery(
UnionAllQuery(
SelectTableByFilter("Music", "title", "Secret"),
SelectTableByFilter("Cities", "name", "Piova"),
),
pyodbc=altqq.PyODBCQuery(
query="""
SELECT * FROM (
SELECT * FROM "Music" WHERE "title" = ?
) AS tbl1
UNION ALL
SELECT * FROM (
SELECT * FROM "Cities" WHERE "name" = ?
) AS tbl2
""",
parameters=["Secret", "Piova"],
),
plain_text="""
SELECT * FROM (
SELECT * FROM "Music" WHERE "title" = 'Secret'
) AS tbl1
UNION ALL
SELECT * FROM (
SELECT * FROM "Cities" WHERE "name" = 'Piova'
) AS tbl2
""",
),
]
20 changes: 10 additions & 10 deletions tests/test_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
import altqq
import pytest

from tests.queries import TEST_DATA, TestQuery
from tests.queries import TEST_DATA, SampleQuery
from tests.utils import clean_whitespaces as cws


@pytest.mark.parametrize("test_query", TEST_DATA)
def test_to_pyodbc__proper_query__correct_pyodbc_object(test_query: TestQuery):
@pytest.mark.parametrize("query", TEST_DATA)
def test_to_pyodbc__proper_query__correct_pyodbc_object(query: SampleQuery):
"""If the query parameters are correct, the pyodbc object is returned."""
res = altqq.to_pyodbc(test_query.query)
assert cws(test_query.pyodbc.query) == cws(res.query)
assert test_query.pyodbc.parameters == res.parameters
res = altqq.to_pyodbc(query.query)
assert cws(query.pyodbc.query) == cws(res.query)
assert query.pyodbc.parameters == res.parameters


@pytest.mark.parametrize("test_query", TEST_DATA)
def test_to_plain_text__proper_query__correct_sqlt(test_query: TestQuery):
@pytest.mark.parametrize("query", TEST_DATA)
def test_to_plain_text__proper_query__correct_sqlt(query: SampleQuery):
"""If the query parameters are correct, the sql is returned."""
sql = altqq.to_plain_text(test_query.query)
assert cws(test_query.plain_text) == cws(sql)
sql = altqq.to_plain_text(query.query)
assert cws(query.plain_text) == cws(sql)

0 comments on commit f9e1ebe

Please sign in to comment.