python-sql-query-builder
Advanced tools
+13
-7
| Metadata-Version: 2.4 | ||
| Name: python-sql-query-builder | ||
| Version: 0.1.1 | ||
| Version: 0.1.2 | ||
| Summary: A fluent Python SQL query builder with support for joins, where clauses, inserts, updates, and more | ||
@@ -29,8 +29,14 @@ Author-email: Omer Menashe <unspecified@mail.com> | ||
| - Supports: | ||
| - `SELECT`, `INSERT`, `UPDATE`, `DELETE` | ||
| - `WHERE`, `AND`, `OR`, `IN`, `HAVING`, `GROUP BY`, `ORDER BY` | ||
| - `JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, `INNER JOIN` | ||
| - `LIMIT`, `OFFSET`, `ON CONFLICT DO NOTHING` | ||
| - Simple Python dependency — no external libraries | ||
| - Useful for prototyping, dynamic query generation, or learning SQL | ||
| - SELECT: SELECT, SELECT DISTINCT | ||
| - Data Manipulation: INSERT INTO, UPDATE, DELETE FROM | ||
| - Conditions: WHERE, AND, OR, IN, HAVING | ||
| - Grouping & Ordering: GROUP BY, ORDER BY, LIMIT, OFFSET | ||
| - Joins: LEFT JOIN, RIGHT JOIN, INNER JOIN, FULL JOIN | ||
| - Transactions & Savepoints: COMMIT, ROLLBACK, SAVEPOINT | ||
| - Table Operations: CREATE TABLE, DROP TABLE, ALTER TABLE, RENAME TABLE, ADD COLUMN, DROP COLUMN | ||
| - Index Operations: CREATE INDEX | ||
| - Permissions: GRANT, REVOKE | ||
| - Set Operations: UNION, INTERSECT, EXCEPT | ||
| - Conflict Handling: ON CONFLICT DO NOTHING | ||
| - Value Operations: VALUES, IN CLAUSE | ||
@@ -37,0 +43,0 @@ --- |
+1
-1
@@ -7,3 +7,3 @@ [build-system] | ||
| name = "python-sql-query-builder" | ||
| version = "0.1.1" | ||
| version = "0.1.2" | ||
| description = "A fluent Python SQL query builder with support for joins, where clauses, inserts, updates, and more" | ||
@@ -10,0 +10,0 @@ readme = "README.md" |
| Metadata-Version: 2.4 | ||
| Name: python-sql-query-builder | ||
| Version: 0.1.1 | ||
| Version: 0.1.2 | ||
| Summary: A fluent Python SQL query builder with support for joins, where clauses, inserts, updates, and more | ||
@@ -29,8 +29,14 @@ Author-email: Omer Menashe <unspecified@mail.com> | ||
| - Supports: | ||
| - `SELECT`, `INSERT`, `UPDATE`, `DELETE` | ||
| - `WHERE`, `AND`, `OR`, `IN`, `HAVING`, `GROUP BY`, `ORDER BY` | ||
| - `JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, `INNER JOIN` | ||
| - `LIMIT`, `OFFSET`, `ON CONFLICT DO NOTHING` | ||
| - Simple Python dependency — no external libraries | ||
| - Useful for prototyping, dynamic query generation, or learning SQL | ||
| - SELECT: SELECT, SELECT DISTINCT | ||
| - Data Manipulation: INSERT INTO, UPDATE, DELETE FROM | ||
| - Conditions: WHERE, AND, OR, IN, HAVING | ||
| - Grouping & Ordering: GROUP BY, ORDER BY, LIMIT, OFFSET | ||
| - Joins: LEFT JOIN, RIGHT JOIN, INNER JOIN, FULL JOIN | ||
| - Transactions & Savepoints: COMMIT, ROLLBACK, SAVEPOINT | ||
| - Table Operations: CREATE TABLE, DROP TABLE, ALTER TABLE, RENAME TABLE, ADD COLUMN, DROP COLUMN | ||
| - Index Operations: CREATE INDEX | ||
| - Permissions: GRANT, REVOKE | ||
| - Set Operations: UNION, INTERSECT, EXCEPT | ||
| - Conflict Handling: ON CONFLICT DO NOTHING | ||
| - Value Operations: VALUES, IN CLAUSE | ||
@@ -37,0 +43,0 @@ --- |
+12
-6
@@ -11,8 +11,14 @@ ## SQLQuery | ||
| - Supports: | ||
| - `SELECT`, `INSERT`, `UPDATE`, `DELETE` | ||
| - `WHERE`, `AND`, `OR`, `IN`, `HAVING`, `GROUP BY`, `ORDER BY` | ||
| - `JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, `INNER JOIN` | ||
| - `LIMIT`, `OFFSET`, `ON CONFLICT DO NOTHING` | ||
| - Simple Python dependency — no external libraries | ||
| - Useful for prototyping, dynamic query generation, or learning SQL | ||
| - SELECT: SELECT, SELECT DISTINCT | ||
| - Data Manipulation: INSERT INTO, UPDATE, DELETE FROM | ||
| - Conditions: WHERE, AND, OR, IN, HAVING | ||
| - Grouping & Ordering: GROUP BY, ORDER BY, LIMIT, OFFSET | ||
| - Joins: LEFT JOIN, RIGHT JOIN, INNER JOIN, FULL JOIN | ||
| - Transactions & Savepoints: COMMIT, ROLLBACK, SAVEPOINT | ||
| - Table Operations: CREATE TABLE, DROP TABLE, ALTER TABLE, RENAME TABLE, ADD COLUMN, DROP COLUMN | ||
| - Index Operations: CREATE INDEX | ||
| - Permissions: GRANT, REVOKE | ||
| - Set Operations: UNION, INTERSECT, EXCEPT | ||
| - Conflict Handling: ON CONFLICT DO NOTHING | ||
| - Value Operations: VALUES, IN CLAUSE | ||
@@ -19,0 +25,0 @@ --- |
+107
-30
@@ -11,2 +11,3 @@ from typing import List | ||
| # Basic Query Clauses | ||
| def select(self, *columns: str, distinct: bool = False) -> 'SQLQueryBuilder': | ||
@@ -26,2 +27,42 @@ columns_str = ', '.join(columns) if columns else '*' | ||
| def group_by(self, *columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(columns) | ||
| self.__query_segments.append(f'GROUP BY {columns_str}') | ||
| return self | ||
| def order_by(self, *columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(columns) | ||
| self.__query_segments.append(f'ORDER BY {columns_str}') | ||
| return self | ||
| def limit(self, n: int) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'LIMIT {n}') | ||
| return self | ||
| def offset(self, n: int) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'OFFSET {n}') | ||
| return self | ||
| def in_clause(self, column: str, *values: str) -> 'SQLQueryBuilder': | ||
| values_str = ', '.join(str(v) for v in values) | ||
| self.__query_segments.append(f'WHERE {column} IN ({values_str})') | ||
| return self | ||
| def and_where(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'AND {condition}') | ||
| return self | ||
| def or_where(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'OR {condition}') | ||
| return self | ||
| def having(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'HAVING {condition}') | ||
| return self | ||
| def on_conflict_do_nothing(self) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append('ON CONFLICT DO NOTHING') | ||
| return self | ||
| # Joins | ||
| def left_join(self, table: str, on_condition: str) -> 'SQLQueryBuilder': | ||
@@ -43,16 +84,3 @@ self.__query_segments.append(f'LEFT JOIN {table} ON {on_condition}') | ||
| def group_by(self, *columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(columns) | ||
| self.__query_segments.append(f'GROUP BY {columns_str}') | ||
| return self | ||
| def order_by(self, *columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(columns) | ||
| self.__query_segments.append(f'ORDER BY {columns_str}') | ||
| return self | ||
| def limit(self, n: int) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'LIMIT {n}') | ||
| return self | ||
| # Data Modification | ||
| def insert_into(self, table: str, **columns: str) -> 'SQLQueryBuilder': | ||
@@ -73,32 +101,81 @@ column_names = ', '.join(columns.keys()) | ||
| def in_clause(self, column: str, *values: str) -> 'SQLQueryBuilder': | ||
| values_str = ', '.join(str(v) for v in values) | ||
| self.__query_segments.append(f'WHERE {column} IN ({values_str})') | ||
| def values(self, *rows: List[str]) -> 'SQLQueryBuilder': | ||
| rows_str = ', '.join(f"({', '.join(row)})" for row in rows) | ||
| self.__query_segments.append(f'VALUES {rows_str}') | ||
| return self | ||
| def and_where(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'AND {condition}') | ||
| # Transactions | ||
| def commit(self) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append('COMMIT') | ||
| return self | ||
| def or_where(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'OR {condition}') | ||
| def rollback(self) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append('ROLLBACK') | ||
| return self | ||
| def having(self, condition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'HAVING {condition}') | ||
| def savepoint(self, savepoint_name: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'SAVEPOINT {savepoint_name}') | ||
| return self | ||
| def on_conflict_do_nothing(self) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append('ON CONFLICT DO NOTHING') | ||
| # DDL Statements (Create, Alter, Drop) | ||
| def drop(self, object_type: str, object_name: str, if_exists: bool = False) -> 'SQLQueryBuilder': | ||
| exists_clause = 'IF EXISTS' if if_exists else None | ||
| self.__query_segments.append(f'DROP {exists_clause + ' ' if exists_clause else ''}{object_type} {object_name}') | ||
| return self | ||
| def offset(self, n: int) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'OFFSET {n}') | ||
| def create_table(self, table: str, **columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(f"{name} {datatype}" for name, datatype in columns.items()) | ||
| self.__query_segments.append(f'CREATE TABLE {table} ({columns_str})') | ||
| return self | ||
| def values(self, *rows: List[str]) -> 'SQLQueryBuilder': | ||
| rows_str = ', '.join(f"({', '.join(row)})" for row in rows) | ||
| self.__query_segments.append(f'VALUES {rows_str}') | ||
| def create_index(self, index_name: str, table: str, *columns: str) -> 'SQLQueryBuilder': | ||
| columns_str = ', '.join(columns) | ||
| self.__query_segments.append(f'CREATE INDEX {index_name} ON {table} ({columns_str})') | ||
| return self | ||
| def add_column(self, column_name: str, column_definition: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'ADD COLUMN {column_name} {column_definition}') | ||
| return self | ||
| def drop_column(self, column_name: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'DROP COLUMN {column_name}') | ||
| return self | ||
| def alter_table(self, table: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'ALTER TABLE {table}') | ||
| return self | ||
| def rename_table(self, old_name: str, new_name: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'RENAME TABLE {old_name} TO {new_name}') | ||
| return self | ||
| def rename_column(self, table: str, old_name: str, new_name: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'ALTER TABLE {table} RENAME COLUMN {old_name} TO {new_name}') | ||
| return self | ||
| # Permissions | ||
| def grant(self, permission: str, table: str, user: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'GRANT {permission} ON {table} TO {user}') | ||
| return self | ||
| def revoke(self, permission: str, table: str, user: str) -> 'SQLQueryBuilder': | ||
| self.__query_segments.append(f'REVOKE {permission} ON {table} FROM {user}') | ||
| return self | ||
| # Set Operations | ||
| def union(self, query: str, union_all: bool = False) -> 'SQLQueryBuilder': | ||
| all_clause = 'ALL' if union_all else None | ||
| self.__query_segments.append(f'UNION {all_clause + ' ' if all_clause else ''}{query}') | ||
| return self | ||
| def intersect(self, query: str, intersect_all: bool = False) -> 'SQLQueryBuilder': | ||
| all_clause = 'ALL' if intersect_all else None | ||
| self.__query_segments.append(f'INTERSECT {all_clause + ' ' if all_clause else ''}{query}') | ||
| return self | ||
| def except_clause(self, query: str, except_all: bool = False) -> 'SQLQueryBuilder': | ||
| all_clause = 'ALL' if except_all else None | ||
| self.__query_segments.append(f'EXCEPT {all_clause + ' ' if all_clause else ''}{query}') | ||
| return self | ||
| def __str__(self) -> str: | ||
@@ -105,0 +182,0 @@ return self.build() |
| import unittest | ||
| from sql_query_builder import SQLQueryBuilder | ||
@@ -7,2 +6,3 @@ | ||
| class TestSQLQueryBuilder(unittest.TestCase): | ||
| def test_select_specific_columns(self): | ||
@@ -52,4 +52,69 @@ query = SQLQueryBuilder().select('id', 'name', 'email').from_table('users').build() | ||
| def test_drop_table_query(self): | ||
| query = SQLQueryBuilder().drop("TABLE", "users").build() | ||
| self.assertEqual(query, 'DROP TABLE users') | ||
| # New tests for the remaining methods | ||
| def test_create_table_query(self): | ||
| query = SQLQueryBuilder().create_table('users', id='INT', name='VARCHAR(100)', email='VARCHAR(100)').build() | ||
| self.assertEqual(query, 'CREATE TABLE users (id INT, name VARCHAR(100), email VARCHAR(100))') | ||
| def test_create_index_query(self): | ||
| query = SQLQueryBuilder().create_index('idx_name', 'users', 'name').build() | ||
| self.assertEqual(query, 'CREATE INDEX idx_name ON users (name)') | ||
| def test_grant_query(self): | ||
| query = SQLQueryBuilder().grant('SELECT', 'users', 'admin').build() | ||
| self.assertEqual(query, 'GRANT SELECT ON users TO admin') | ||
| def test_revoke_query(self): | ||
| query = SQLQueryBuilder().revoke('SELECT', 'users', 'admin').build() | ||
| self.assertEqual(query, 'REVOKE SELECT ON users FROM admin') | ||
| def test_commit_query(self): | ||
| query = SQLQueryBuilder().commit().build() | ||
| self.assertEqual(query, 'COMMIT') | ||
| def test_rollback_query(self): | ||
| query = SQLQueryBuilder().rollback().build() | ||
| self.assertEqual(query, 'ROLLBACK') | ||
| def test_savepoint_query(self): | ||
| query = SQLQueryBuilder().savepoint('sp1').build() | ||
| self.assertEqual(query, 'SAVEPOINT sp1') | ||
| def test_union_query(self): | ||
| query = SQLQueryBuilder().union('SELECT * FROM users').build() | ||
| self.assertEqual(query, 'UNION SELECT * FROM users') | ||
| def test_intersect_query(self): | ||
| query = SQLQueryBuilder().intersect('SELECT * FROM users').build() | ||
| self.assertEqual(query, 'INTERSECT SELECT * FROM users') | ||
| def test_except_query(self): | ||
| query = SQLQueryBuilder().except_clause('SELECT * FROM users').build() | ||
| self.assertEqual(query, 'EXCEPT SELECT * FROM users') | ||
| def test_add_column_query(self): | ||
| query = SQLQueryBuilder().alter_table('users').add_column('age', 'INT').build() | ||
| self.assertEqual(query, 'ALTER TABLE users ADD COLUMN age INT') | ||
| def test_drop_column_query(self): | ||
| query = SQLQueryBuilder().alter_table('users').drop_column('age').build() | ||
| self.assertEqual(query, 'ALTER TABLE users DROP COLUMN age') | ||
| def test_alter_table_query(self): | ||
| query = SQLQueryBuilder().alter_table('users').build() | ||
| self.assertEqual(query, 'ALTER TABLE users') | ||
| def test_rename_table_query(self): | ||
| query = SQLQueryBuilder().rename_table('users', 'customers').build() | ||
| self.assertEqual(query, 'RENAME TABLE users TO customers') | ||
| def test_rename_column_query(self): | ||
| query = SQLQueryBuilder().rename_column('users', 'age', 'birthdate').build() | ||
| self.assertEqual(query, 'ALTER TABLE users RENAME COLUMN age TO birthdate') | ||
| if __name__ == '__main__': | ||
| unittest.main() |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
20877
50.95%227
94.02%