sql-blocks


Namesql-blocks JSON
Version 0.1.1 PyPI version JSON
download
home_pagehttps://github.com/julio-cascalles/sql_blocks
SummaryAllows you to create objects for parts of SQL query commands. Also to combine these objects by joining them, adding or removing parts...
upload_time2024-09-10 16:19:19
maintainerNone
docs_urlNone
authorJúlio Cascalles
requires_python>=3.8
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # SQL_Blocks

### 1 - You can assemble a simple object that will then be converted into an SQL command:

> a = Select('Actor') # --> SELECT * FROM Actor act

_Note that an alias "act" has been added._

You can specify your own alias:  `a = Select('Actor a')`

---
### 2 - You can also add a field, like this...

* a = Select('Actor a', **name=Field**)

* Here are another ways to add a field:
    - Select('Actor a', name=Distinct )

    - Select('Actor a', name=NamedField('actors_name'))

    - Select(
        'Actor a', 
        name=NamedField('actors_name', Distinct)
    )


    2.1 -- Using expression as a field:
```
    Select(
        'Product',
        due_date=NamedField(
            'YEAR_ref',
            ExpressionField('extract(year from %)') #  <<---
        )
    )
```
...should return: 
**SELECT extract(year from due_date) as YEAR_ref...**

---

### 3 - To set conditions, use **Where**:
* For example, `a = Select(... age=Where.gt(45) )`

    Some possible conditions:
    * field=Where.eq(value) - ...the field is EQUAL to the value;
    * field=Where.gt(value) - ...the field is GREATER than the value;
    * field=Where.lt(value) - ...the field is LESS than the value;

    3.1 -- If you want to filter the field on a range of values:
    
    `a = Select( 'Actor a', age=Between(45, 69) )`

    3.2 -- Sub-queries:
```
query = Select('Movie m', title=Field,
    id=SelectIN(
        'Review r',
        rate=Where.gt(4.5),
        movie_id=Distinct
    )
)
```

**>> print(query)** 

        SELECT
            m.title
        FROM
            Movie m
        WHERE
            m.id IN (
                SELECT DISTINCT r.movie
                FROM Review r WHERE r.rate > 4.5
            )
    
3.3 -- Optional conditions:
```
    OR=Options(
        genre=Where.eq("Sci-Fi"),
        awards=Where.like("Oscar")
    )
```
> Could be AND=Options(...)

3.4 -- Negative conditions use the _Not_ class instead of _Where_
```
based_on_book=Not.is_null()
```

3.5 -- List of values
```
hash_tag=Where.list(['space', 'monster', 'gore'])
```

---
### 4 - A field can be two things at the same time:

* m = Select('Movie m' release_date=[Field, OrderBy])
    - This means that the field will appear in the results and also that the query will be ordered by that field.
* Applying **GROUP BY** to item 3.2, it would look like this:
    ```    
    SelectIN(
        'Review r', movie=[GroupBy, Distinct],
        rate=Having.avg(Where.gt(4.5))
    )
    ```
---
### 5 - Relationships:
```
    query = Select('Actor a', name=Field,
        cast=Select('Cast c', id=PrimaryKey)
    )
```
**>> print(query)**    
```
SELECT
    a.name
FROM
    Actor a
    JOIN Cast c ON (a.cast = c.id)    
```

---
### 6 - The reverse process (parse):
```
text = """
        SELECT
                cas.role,
                m.title,
                m.release_date,
                a.name as actors_name
        FROM
                Actor a
                LEFT JOIN Cast cas ON (a.cast = cas.id)
                LEFT JOIN Movie m ON (cas.movie = m.id)
        WHERE
                (
                    m.genre = 'Sci-Fi'
                    OR
                    m.awards LIKE '%Oscar%'
                )
                AND a.age <= 69 AND a.age >= 45
        ORDER BY
                m.release_date DESC
"""
```

`a, c, m = Select.parse(text)`

**6.1  --- print(a)**
```
    SELECT
            a.name as actors_name
    FROM
            Actor a
    WHERE
            a.age <= 69
            AND a.age >= 45
```

**6.2 --- print(c)**

    SELECT
            c.role
    FROM
            Cast c

**6.3 --- print(m)**

    SELECT
            m.title,
            m.release_date
    FROM
            Movie m
    WHERE
            ( m.genre = 'Sci-Fi' OR m.awards LIKE '%Oscar%' )
    ORDER BY
            m.release_date DESC



**6.4 --- print(a+c)**

    SELECT
            a.name as actors_name,
            cas.role
    FROM
            Actor a
            JOIN Cast cas ON (a.cast = cas.id)
    WHERE
            a.age >= 45
            AND a.age <= 69

**6.5 --- print(c+m)** 
> `... or  print(m+c)`

    SELECT
            cas.role,
            m.title,
            m.release_date,
            m.director
    FROM
            Cast cas
            JOIN Movie m ON (cas.movie = m.id)
    WHERE
            ( m.genre = 'Sci-Fi' OR m.awards LIKE '%Oscar%' )
            AND m.director LIKE '%Coppola%'
    ORDER BY
            m.release_date,
            m.director
---

### 7 - You can add or delete attributes directly in objects:
* a(gender=Field)
* m.delete('director')

---

### 8 - Defining relationship on separate objects:
```
a = Select...
c = Select...
m = Select...
```
`a + c => ERROR: "No relationship found between Actor and Cast"`

8.1 - But...

    a( cast=ForeignKey('Cast') )
    c(id=PrimaryKey)

**a + c => Ok!**

8.2

    c( movie=ForeignKey('Movie') )
    m(id=PrimaryKey)

> **c + m => Ok!**
>> **m + c => Ok!**


---

### 9 - Comparing objects

9.1
```
        a1 = Select.parse('''
                SELECT gender, Max(act.age) FROM Actor act
                WHERE act.age <= 69 AND act.age >= 45
                GROUP BY gender
            ''')[0]

        a2 = Select('Actor',
            age=[ Between(45, 69), Max ],
            gender=[GroupBy, Field]
        )       
```
> **a1 == a2 # --- True!**



9.2
```
    m1 = Select.parse("""
        SELECT title, release_date FROM Movie m ORDER BY release_date 
        WHERE m.genre = 'Sci-Fi' AND m.awards LIKE '%Oscar%'
    """)[0]

    m2 = Select.parse("""
        SELECT release_date, title
        FROM Movie m
        WHERE m.awards LIKE '%Oscar%' AND m.genre = 'Sci-Fi'
        ORDER BY release_date 
    """)[0]
```

**m1 == m2  #  --- True!**


9.3
```
best_movies = SelectIN(
    Review=Table('role'),
    rate=[GroupBy, Having.avg(Where.gt(4.5))]
)
m1 = Select(
    Movie=Table('title,release_date),
    id=best_movies
)

sql = "SELECT rev.role FROM Review rev GROUP BY rev.rate HAVING Avg(rev.rate) > 4.5"
m2 = Select(
    'Movie', release_date=Field, title=Field,
    id=Where(f"IN ({sql})")
)
```
**m1 == m2 # --- True!**

---

### 10 - CASE...WHEN...THEN
    Select(
        'Product',
        label=Case('price').when(
            lt(50), 'cheap'
        ).when(
            gt(100), 'expensive'
        ).else_value(
            'normal'
        )
    )

---

### 11 - optimize method
    p1 = Select.parse("""
            SELECT * FROM Product p
            WHERE (p.category = 'Gizmo'
                    OR p.category = 'Gadget'
                    OR p.category = 'Doohickey')
                AND NOT price <= 387.64
                AND YEAR(last_sale) = 2024
            ORDER BY
                category
        """)[0]
        p1.optimize() #  <<===============
        p2 = Select.parse("""
            SELECT category FROM Product p
            WHERE category IN ('Gizmo','Gadget','Doohickey')
                and p.price > 387.64
                and p.last_sale >= '2024-01-01'
                and p.last_sale <= '2024-12-31'
            ORDER BY p.category LIMIT 100
        """)[0]
        p1 == p2 # --- True!

 This will...
* Replace `OR` conditions to `SELECT IN ...`
* Put `LIMIT` if no fields or conditions defined;
* Normalizes inverted conditions;
* Auto includes fields present in `ORDER/GROUP BY`;
* Replace `YEAR` function with date range comparison.

> The method allows you to select which rules you want to apply in the optimization...Or define your own rules!

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/julio-cascalles/sql_blocks",
    "name": "sql-blocks",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "J\u00falio Cascalles",
    "author_email": "Julio Cascalles <julio.cascalles@outlook.com>",
    "download_url": "https://files.pythonhosted.org/packages/26/bd/bf52b3470b183700c757b1cf580da5bb626252891f4446d7754d32fb6b81/sql_blocks-0.1.1.tar.gz",
    "platform": null,
    "description": "# SQL_Blocks\r\n\r\n### 1 - You can assemble a simple object that will then be converted into an SQL command:\r\n\r\n> a = Select('Actor') # --> SELECT * FROM Actor act\r\n\r\n_Note that an alias \"act\" has been added._\r\n\r\nYou can specify your own alias:  `a = Select('Actor a')`\r\n\r\n---\r\n### 2 - You can also add a field, like this...\r\n\r\n* a = Select('Actor a', **name=Field**)\r\n\r\n* Here are another ways to add a field:\r\n    - Select('Actor a', name=Distinct )\r\n\r\n    - Select('Actor a', name=NamedField('actors_name'))\r\n\r\n    - Select(\r\n        'Actor a', \r\n        name=NamedField('actors_name', Distinct)\r\n    )\r\n\r\n\r\n    2.1 -- Using expression as a field:\r\n```\r\n    Select(\r\n        'Product',\r\n        due_date=NamedField(\r\n            'YEAR_ref',\r\n            ExpressionField('extract(year from %)') #  <<---\r\n        )\r\n    )\r\n```\r\n...should return: \r\n**SELECT extract(year from due_date) as YEAR_ref...**\r\n\r\n---\r\n\r\n### 3 - To set conditions, use **Where**:\r\n* For example, `a = Select(... age=Where.gt(45) )`\r\n\r\n    Some possible conditions:\r\n    * field=Where.eq(value) - ...the field is EQUAL to the value;\r\n    * field=Where.gt(value) - ...the field is GREATER than the value;\r\n    * field=Where.lt(value) - ...the field is LESS than the value;\r\n\r\n    3.1 -- If you want to filter the field on a range of values:\r\n    \r\n    `a = Select( 'Actor a', age=Between(45, 69) )`\r\n\r\n    3.2 -- Sub-queries:\r\n```\r\nquery = Select('Movie m', title=Field,\r\n    id=SelectIN(\r\n        'Review r',\r\n        rate=Where.gt(4.5),\r\n        movie_id=Distinct\r\n    )\r\n)\r\n```\r\n\r\n**>> print(query)** \r\n\r\n        SELECT\r\n            m.title\r\n        FROM\r\n            Movie m\r\n        WHERE\r\n            m.id IN (\r\n                SELECT DISTINCT r.movie\r\n                FROM Review r WHERE r.rate > 4.5\r\n            )\r\n    \r\n3.3 -- Optional conditions:\r\n```\r\n    OR=Options(\r\n        genre=Where.eq(\"Sci-Fi\"),\r\n        awards=Where.like(\"Oscar\")\r\n    )\r\n```\r\n> Could be AND=Options(...)\r\n\r\n3.4 -- Negative conditions use the _Not_ class instead of _Where_\r\n```\r\nbased_on_book=Not.is_null()\r\n```\r\n\r\n3.5 -- List of values\r\n```\r\nhash_tag=Where.list(['space', 'monster', 'gore'])\r\n```\r\n\r\n---\r\n### 4 - A field can be two things at the same time:\r\n\r\n* m = Select('Movie m' release_date=[Field, OrderBy])\r\n    - This means that the field will appear in the results and also that the query will be ordered by that field.\r\n* Applying **GROUP BY** to item 3.2, it would look like this:\r\n    ```    \r\n    SelectIN(\r\n        'Review r', movie=[GroupBy, Distinct],\r\n        rate=Having.avg(Where.gt(4.5))\r\n    )\r\n    ```\r\n---\r\n### 5 - Relationships:\r\n```\r\n    query = Select('Actor a', name=Field,\r\n        cast=Select('Cast c', id=PrimaryKey)\r\n    )\r\n```\r\n**>> print(query)**    \r\n```\r\nSELECT\r\n    a.name\r\nFROM\r\n    Actor a\r\n    JOIN Cast c ON (a.cast = c.id)    \r\n```\r\n\r\n---\r\n### 6 - The reverse process (parse):\r\n```\r\ntext = \"\"\"\r\n        SELECT\r\n                cas.role,\r\n                m.title,\r\n                m.release_date,\r\n                a.name as actors_name\r\n        FROM\r\n                Actor a\r\n                LEFT JOIN Cast cas ON (a.cast = cas.id)\r\n                LEFT JOIN Movie m ON (cas.movie = m.id)\r\n        WHERE\r\n                (\r\n                    m.genre = 'Sci-Fi'\r\n                    OR\r\n                    m.awards LIKE '%Oscar%'\r\n                )\r\n                AND a.age <= 69 AND a.age >= 45\r\n        ORDER BY\r\n                m.release_date DESC\r\n\"\"\"\r\n```\r\n\r\n`a, c, m = Select.parse(text)`\r\n\r\n**6.1  --- print(a)**\r\n```\r\n    SELECT\r\n            a.name as actors_name\r\n    FROM\r\n            Actor a\r\n    WHERE\r\n            a.age <= 69\r\n            AND a.age >= 45\r\n```\r\n\r\n**6.2 --- print(c)**\r\n\r\n    SELECT\r\n            c.role\r\n    FROM\r\n            Cast c\r\n\r\n**6.3 --- print(m)**\r\n\r\n    SELECT\r\n            m.title,\r\n            m.release_date\r\n    FROM\r\n            Movie m\r\n    WHERE\r\n            ( m.genre = 'Sci-Fi' OR m.awards LIKE '%Oscar%' )\r\n    ORDER BY\r\n            m.release_date DESC\r\n\r\n\r\n\r\n**6.4 --- print(a+c)**\r\n\r\n    SELECT\r\n            a.name as actors_name,\r\n            cas.role\r\n    FROM\r\n            Actor a\r\n            JOIN Cast cas ON (a.cast = cas.id)\r\n    WHERE\r\n            a.age >= 45\r\n            AND a.age <= 69\r\n\r\n**6.5 --- print(c+m)** \r\n> `... or  print(m+c)`\r\n\r\n    SELECT\r\n            cas.role,\r\n            m.title,\r\n            m.release_date,\r\n            m.director\r\n    FROM\r\n            Cast cas\r\n            JOIN Movie m ON (cas.movie = m.id)\r\n    WHERE\r\n            ( m.genre = 'Sci-Fi' OR m.awards LIKE '%Oscar%' )\r\n            AND m.director LIKE '%Coppola%'\r\n    ORDER BY\r\n            m.release_date,\r\n            m.director\r\n---\r\n\r\n### 7 - You can add or delete attributes directly in objects:\r\n* a(gender=Field)\r\n* m.delete('director')\r\n\r\n---\r\n\r\n### 8 - Defining relationship on separate objects:\r\n```\r\na = Select...\r\nc = Select...\r\nm = Select...\r\n```\r\n`a + c => ERROR: \"No relationship found between Actor and Cast\"`\r\n\r\n8.1 - But...\r\n\r\n    a( cast=ForeignKey('Cast') )\r\n    c(id=PrimaryKey)\r\n\r\n**a + c => Ok!**\r\n\r\n8.2\r\n\r\n    c( movie=ForeignKey('Movie') )\r\n    m(id=PrimaryKey)\r\n\r\n> **c + m => Ok!**\r\n>> **m + c => Ok!**\r\n\r\n\r\n---\r\n\r\n### 9 - Comparing objects\r\n\r\n9.1\r\n```\r\n        a1 = Select.parse('''\r\n                SELECT gender, Max(act.age) FROM Actor act\r\n                WHERE act.age <= 69 AND act.age >= 45\r\n                GROUP BY gender\r\n            ''')[0]\r\n\r\n        a2 = Select('Actor',\r\n            age=[ Between(45, 69), Max ],\r\n            gender=[GroupBy, Field]\r\n        )       \r\n```\r\n> **a1 == a2 # --- True!**\r\n\r\n\r\n\r\n9.2\r\n```\r\n    m1 = Select.parse(\"\"\"\r\n        SELECT title, release_date FROM Movie m ORDER BY release_date \r\n        WHERE m.genre = 'Sci-Fi' AND m.awards LIKE '%Oscar%'\r\n    \"\"\")[0]\r\n\r\n    m2 = Select.parse(\"\"\"\r\n        SELECT release_date, title\r\n        FROM Movie m\r\n        WHERE m.awards LIKE '%Oscar%' AND m.genre = 'Sci-Fi'\r\n        ORDER BY release_date \r\n    \"\"\")[0]\r\n```\r\n\r\n**m1 == m2  #  --- True!**\r\n\r\n\r\n9.3\r\n```\r\nbest_movies = SelectIN(\r\n    Review=Table('role'),\r\n    rate=[GroupBy, Having.avg(Where.gt(4.5))]\r\n)\r\nm1 = Select(\r\n    Movie=Table('title,release_date),\r\n    id=best_movies\r\n)\r\n\r\nsql = \"SELECT rev.role FROM Review rev GROUP BY rev.rate HAVING Avg(rev.rate) > 4.5\"\r\nm2 = Select(\r\n    'Movie', release_date=Field, title=Field,\r\n    id=Where(f\"IN ({sql})\")\r\n)\r\n```\r\n**m1 == m2 # --- True!**\r\n\r\n---\r\n\r\n### 10 - CASE...WHEN...THEN\r\n    Select(\r\n        'Product',\r\n        label=Case('price').when(\r\n            lt(50), 'cheap'\r\n        ).when(\r\n            gt(100), 'expensive'\r\n        ).else_value(\r\n            'normal'\r\n        )\r\n    )\r\n\r\n---\r\n\r\n### 11 - optimize method\r\n    p1 = Select.parse(\"\"\"\r\n            SELECT * FROM Product p\r\n            WHERE (p.category = 'Gizmo'\r\n                    OR p.category = 'Gadget'\r\n                    OR p.category = 'Doohickey')\r\n                AND NOT price <= 387.64\r\n                AND YEAR(last_sale) = 2024\r\n            ORDER BY\r\n                category\r\n        \"\"\")[0]\r\n        p1.optimize() #  <<===============\r\n        p2 = Select.parse(\"\"\"\r\n            SELECT category FROM Product p\r\n            WHERE category IN ('Gizmo','Gadget','Doohickey')\r\n                and p.price > 387.64\r\n                and p.last_sale >= '2024-01-01'\r\n                and p.last_sale <= '2024-12-31'\r\n            ORDER BY p.category LIMIT 100\r\n        \"\"\")[0]\r\n        p1 == p2 # --- True!\r\n\r\n This will...\r\n* Replace `OR` conditions to `SELECT IN ...`\r\n* Put `LIMIT` if no fields or conditions defined;\r\n* Normalizes inverted conditions;\r\n* Auto includes fields present in `ORDER/GROUP BY`;\r\n* Replace `YEAR` function with date range comparison.\r\n\r\n> The method allows you to select which rules you want to apply in the optimization...Or define your own rules!\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Allows you to create objects for parts of SQL query commands. Also to combine these objects by joining them, adding or removing parts...",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://github.com/julio-cascalles/sql_blocks"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6e52f1bc275c391e33b450c1c868e1c3a273686b381860236f5c9d4083ded98a",
                "md5": "b0d0433f4b0890542b1b816d22584198",
                "sha256": "55a0c31fbc832ad91a77ea32ddf57263f101f96c9ff0f3780b0ec25de287fe3e"
            },
            "downloads": -1,
            "filename": "sql_blocks-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b0d0433f4b0890542b1b816d22584198",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 10364,
            "upload_time": "2024-09-10T16:19:18",
            "upload_time_iso_8601": "2024-09-10T16:19:18.203567Z",
            "url": "https://files.pythonhosted.org/packages/6e/52/f1bc275c391e33b450c1c868e1c3a273686b381860236f5c9d4083ded98a/sql_blocks-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "26bdbf52b3470b183700c757b1cf580da5bb626252891f4446d7754d32fb6b81",
                "md5": "bcf4d8aa06e9cd7df4f24bc001cc9bbd",
                "sha256": "1044c9ea279bd9e4b9242cfa34f0ce1c66a1208690fc4958b394f0fc3926b4e2"
            },
            "downloads": -1,
            "filename": "sql_blocks-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "bcf4d8aa06e9cd7df4f24bc001cc9bbd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 12867,
            "upload_time": "2024-09-10T16:19:19",
            "upload_time_iso_8601": "2024-09-10T16:19:19.209872Z",
            "url": "https://files.pythonhosted.org/packages/26/bd/bf52b3470b183700c757b1cf580da5bb626252891f4446d7754d32fb6b81/sql_blocks-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-10 16:19:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "julio-cascalles",
    "github_project": "sql_blocks",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "sql-blocks"
}
        
Elapsed time: 0.30894s