sqlspec 0.11.0__py3-none-any.whl → 0.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sqlspec might be problematic. Click here for more details.

Files changed (155) hide show
  1. sqlspec/__init__.py +16 -3
  2. sqlspec/_serialization.py +3 -10
  3. sqlspec/_sql.py +1147 -0
  4. sqlspec/_typing.py +343 -41
  5. sqlspec/adapters/adbc/__init__.py +2 -6
  6. sqlspec/adapters/adbc/config.py +474 -149
  7. sqlspec/adapters/adbc/driver.py +330 -644
  8. sqlspec/adapters/aiosqlite/__init__.py +2 -6
  9. sqlspec/adapters/aiosqlite/config.py +143 -57
  10. sqlspec/adapters/aiosqlite/driver.py +269 -462
  11. sqlspec/adapters/asyncmy/__init__.py +3 -8
  12. sqlspec/adapters/asyncmy/config.py +247 -202
  13. sqlspec/adapters/asyncmy/driver.py +217 -451
  14. sqlspec/adapters/asyncpg/__init__.py +4 -7
  15. sqlspec/adapters/asyncpg/config.py +329 -176
  16. sqlspec/adapters/asyncpg/driver.py +418 -498
  17. sqlspec/adapters/bigquery/__init__.py +2 -2
  18. sqlspec/adapters/bigquery/config.py +407 -0
  19. sqlspec/adapters/bigquery/driver.py +592 -634
  20. sqlspec/adapters/duckdb/__init__.py +4 -1
  21. sqlspec/adapters/duckdb/config.py +432 -321
  22. sqlspec/adapters/duckdb/driver.py +393 -436
  23. sqlspec/adapters/oracledb/__init__.py +3 -8
  24. sqlspec/adapters/oracledb/config.py +625 -0
  25. sqlspec/adapters/oracledb/driver.py +549 -942
  26. sqlspec/adapters/psqlpy/__init__.py +4 -7
  27. sqlspec/adapters/psqlpy/config.py +372 -203
  28. sqlspec/adapters/psqlpy/driver.py +197 -550
  29. sqlspec/adapters/psycopg/__init__.py +3 -8
  30. sqlspec/adapters/psycopg/config.py +741 -0
  31. sqlspec/adapters/psycopg/driver.py +732 -733
  32. sqlspec/adapters/sqlite/__init__.py +2 -6
  33. sqlspec/adapters/sqlite/config.py +146 -81
  34. sqlspec/adapters/sqlite/driver.py +243 -426
  35. sqlspec/base.py +220 -825
  36. sqlspec/config.py +354 -0
  37. sqlspec/driver/__init__.py +22 -0
  38. sqlspec/driver/_async.py +252 -0
  39. sqlspec/driver/_common.py +338 -0
  40. sqlspec/driver/_sync.py +261 -0
  41. sqlspec/driver/mixins/__init__.py +17 -0
  42. sqlspec/driver/mixins/_pipeline.py +523 -0
  43. sqlspec/driver/mixins/_result_utils.py +122 -0
  44. sqlspec/driver/mixins/_sql_translator.py +35 -0
  45. sqlspec/driver/mixins/_storage.py +993 -0
  46. sqlspec/driver/mixins/_type_coercion.py +131 -0
  47. sqlspec/exceptions.py +299 -7
  48. sqlspec/extensions/aiosql/__init__.py +10 -0
  49. sqlspec/extensions/aiosql/adapter.py +474 -0
  50. sqlspec/extensions/litestar/__init__.py +1 -6
  51. sqlspec/extensions/litestar/_utils.py +1 -5
  52. sqlspec/extensions/litestar/config.py +5 -6
  53. sqlspec/extensions/litestar/handlers.py +13 -12
  54. sqlspec/extensions/litestar/plugin.py +22 -24
  55. sqlspec/extensions/litestar/providers.py +37 -55
  56. sqlspec/loader.py +528 -0
  57. sqlspec/service/__init__.py +3 -0
  58. sqlspec/service/base.py +24 -0
  59. sqlspec/service/pagination.py +26 -0
  60. sqlspec/statement/__init__.py +21 -0
  61. sqlspec/statement/builder/__init__.py +54 -0
  62. sqlspec/statement/builder/_ddl_utils.py +119 -0
  63. sqlspec/statement/builder/_parsing_utils.py +135 -0
  64. sqlspec/statement/builder/base.py +328 -0
  65. sqlspec/statement/builder/ddl.py +1379 -0
  66. sqlspec/statement/builder/delete.py +80 -0
  67. sqlspec/statement/builder/insert.py +274 -0
  68. sqlspec/statement/builder/merge.py +95 -0
  69. sqlspec/statement/builder/mixins/__init__.py +65 -0
  70. sqlspec/statement/builder/mixins/_aggregate_functions.py +151 -0
  71. sqlspec/statement/builder/mixins/_case_builder.py +91 -0
  72. sqlspec/statement/builder/mixins/_common_table_expr.py +91 -0
  73. sqlspec/statement/builder/mixins/_delete_from.py +34 -0
  74. sqlspec/statement/builder/mixins/_from.py +61 -0
  75. sqlspec/statement/builder/mixins/_group_by.py +119 -0
  76. sqlspec/statement/builder/mixins/_having.py +35 -0
  77. sqlspec/statement/builder/mixins/_insert_from_select.py +48 -0
  78. sqlspec/statement/builder/mixins/_insert_into.py +36 -0
  79. sqlspec/statement/builder/mixins/_insert_values.py +69 -0
  80. sqlspec/statement/builder/mixins/_join.py +110 -0
  81. sqlspec/statement/builder/mixins/_limit_offset.py +53 -0
  82. sqlspec/statement/builder/mixins/_merge_clauses.py +405 -0
  83. sqlspec/statement/builder/mixins/_order_by.py +46 -0
  84. sqlspec/statement/builder/mixins/_pivot.py +82 -0
  85. sqlspec/statement/builder/mixins/_returning.py +37 -0
  86. sqlspec/statement/builder/mixins/_select_columns.py +60 -0
  87. sqlspec/statement/builder/mixins/_set_ops.py +122 -0
  88. sqlspec/statement/builder/mixins/_unpivot.py +80 -0
  89. sqlspec/statement/builder/mixins/_update_from.py +54 -0
  90. sqlspec/statement/builder/mixins/_update_set.py +91 -0
  91. sqlspec/statement/builder/mixins/_update_table.py +29 -0
  92. sqlspec/statement/builder/mixins/_where.py +374 -0
  93. sqlspec/statement/builder/mixins/_window_functions.py +86 -0
  94. sqlspec/statement/builder/protocols.py +20 -0
  95. sqlspec/statement/builder/select.py +206 -0
  96. sqlspec/statement/builder/update.py +178 -0
  97. sqlspec/statement/filters.py +571 -0
  98. sqlspec/statement/parameters.py +736 -0
  99. sqlspec/statement/pipelines/__init__.py +67 -0
  100. sqlspec/statement/pipelines/analyzers/__init__.py +9 -0
  101. sqlspec/statement/pipelines/analyzers/_analyzer.py +649 -0
  102. sqlspec/statement/pipelines/base.py +315 -0
  103. sqlspec/statement/pipelines/context.py +119 -0
  104. sqlspec/statement/pipelines/result_types.py +41 -0
  105. sqlspec/statement/pipelines/transformers/__init__.py +8 -0
  106. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +256 -0
  107. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +623 -0
  108. sqlspec/statement/pipelines/transformers/_remove_comments.py +66 -0
  109. sqlspec/statement/pipelines/transformers/_remove_hints.py +81 -0
  110. sqlspec/statement/pipelines/validators/__init__.py +23 -0
  111. sqlspec/statement/pipelines/validators/_dml_safety.py +275 -0
  112. sqlspec/statement/pipelines/validators/_parameter_style.py +297 -0
  113. sqlspec/statement/pipelines/validators/_performance.py +703 -0
  114. sqlspec/statement/pipelines/validators/_security.py +990 -0
  115. sqlspec/statement/pipelines/validators/base.py +67 -0
  116. sqlspec/statement/result.py +527 -0
  117. sqlspec/statement/splitter.py +701 -0
  118. sqlspec/statement/sql.py +1198 -0
  119. sqlspec/storage/__init__.py +15 -0
  120. sqlspec/storage/backends/__init__.py +0 -0
  121. sqlspec/storage/backends/base.py +166 -0
  122. sqlspec/storage/backends/fsspec.py +315 -0
  123. sqlspec/storage/backends/obstore.py +464 -0
  124. sqlspec/storage/protocol.py +170 -0
  125. sqlspec/storage/registry.py +315 -0
  126. sqlspec/typing.py +157 -36
  127. sqlspec/utils/correlation.py +155 -0
  128. sqlspec/utils/deprecation.py +3 -6
  129. sqlspec/utils/fixtures.py +6 -11
  130. sqlspec/utils/logging.py +135 -0
  131. sqlspec/utils/module_loader.py +45 -43
  132. sqlspec/utils/serializers.py +4 -0
  133. sqlspec/utils/singleton.py +6 -8
  134. sqlspec/utils/sync_tools.py +15 -27
  135. sqlspec/utils/text.py +58 -26
  136. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/METADATA +100 -26
  137. sqlspec-0.12.0.dist-info/RECORD +145 -0
  138. sqlspec/adapters/bigquery/config/__init__.py +0 -3
  139. sqlspec/adapters/bigquery/config/_common.py +0 -40
  140. sqlspec/adapters/bigquery/config/_sync.py +0 -87
  141. sqlspec/adapters/oracledb/config/__init__.py +0 -9
  142. sqlspec/adapters/oracledb/config/_asyncio.py +0 -186
  143. sqlspec/adapters/oracledb/config/_common.py +0 -131
  144. sqlspec/adapters/oracledb/config/_sync.py +0 -186
  145. sqlspec/adapters/psycopg/config/__init__.py +0 -19
  146. sqlspec/adapters/psycopg/config/_async.py +0 -169
  147. sqlspec/adapters/psycopg/config/_common.py +0 -56
  148. sqlspec/adapters/psycopg/config/_sync.py +0 -168
  149. sqlspec/filters.py +0 -330
  150. sqlspec/mixins.py +0 -306
  151. sqlspec/statement.py +0 -378
  152. sqlspec-0.11.0.dist-info/RECORD +0 -69
  153. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/WHEEL +0 -0
  154. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/licenses/LICENSE +0 -0
  155. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/utils/text.py CHANGED
@@ -6,25 +6,20 @@ from functools import lru_cache
6
6
  from typing import Optional
7
7
 
8
8
  # Compiled regex for slugify
9
- _SLUGIFY_REMOVE_INVALID_CHARS_RE = re.compile(r"[^\w\s-]")
10
- _SLUGIFY_COLLAPSE_SEPARATORS_RE = re.compile(r"[-\s]+")
9
+ _SLUGIFY_REMOVE_NON_ALPHANUMERIC = re.compile(r"[^\w]+", re.UNICODE)
10
+ _SLUGIFY_HYPHEN_COLLAPSE = re.compile(r"-+")
11
11
 
12
12
  # Compiled regex for snake_case
13
- # Handles sequences like "HTTPRequest" -> "HTTP_Request" or "SSLError" -> "SSL_Error"
14
- _SNAKE_CASE_RE_ACRONYM_SEQUENCE = re.compile(r"([A-Z\d]+)([A-Z][a-z])")
15
- # Handles transitions like "camelCase" -> "camel_Case" or "PascalCase" -> "Pascal_Case" (partially)
16
- _SNAKE_CASE_RE_LOWER_UPPER_TRANSITION = re.compile(r"([a-z\d])([A-Z])")
17
- # Replaces hyphens, spaces, and dots with a single underscore
18
- _SNAKE_CASE_RE_REPLACE_SEP = re.compile(r"[-\s.]+")
19
- # Cleans up multiple consecutive underscores
20
- _SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE = re.compile(r"__+")
21
-
22
- __all__ = (
23
- "camelize",
24
- "check_email",
25
- "slugify",
26
- "snake_case",
27
- )
13
+ # Insert underscore between lowercase/digit and uppercase letter
14
+ _SNAKE_CASE_LOWER_OR_DIGIT_TO_UPPER = re.compile(r"(?<=[a-z0-9])(?=[A-Z])", re.UNICODE)
15
+ # Insert underscore between uppercase letter and uppercase followed by lowercase
16
+ _SNAKE_CASE_UPPER_TO_UPPER_LOWER = re.compile(r"(?<=[A-Z])(?=[A-Z][a-z])", re.UNICODE)
17
+ # Replace hyphens, spaces, dots, and @ symbols with underscores for snake_case
18
+ _SNAKE_CASE_HYPHEN_SPACE = re.compile(r"[.\s@-]+", re.UNICODE)
19
+ # Collapse multiple underscores
20
+ _SNAKE_CASE_MULTIPLE_UNDERSCORES = re.compile(r"__+", re.UNICODE)
21
+
22
+ __all__ = ("camelize", "check_email", "slugify", "snake_case")
28
23
 
29
24
 
30
25
  def check_email(email: str) -> str:
@@ -68,10 +63,22 @@ def slugify(value: str, allow_unicode: bool = False, separator: Optional[str] =
68
63
  value = unicodedata.normalize("NFKC", value)
69
64
  else:
70
65
  value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
71
- value = _SLUGIFY_REMOVE_INVALID_CHARS_RE.sub("", value.lower())
72
- if separator is not None:
73
- return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_").replace("-", separator)
74
- return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_")
66
+ value = value.lower().strip()
67
+ sep = separator if separator is not None else "-"
68
+ if not sep:
69
+ # Remove all non-alphanumeric characters and return
70
+ return _SLUGIFY_REMOVE_NON_ALPHANUMERIC.sub("", value)
71
+ # Replace all runs of non-alphanumeric chars with the separator
72
+ value = _SLUGIFY_REMOVE_NON_ALPHANUMERIC.sub(sep, value)
73
+ # Remove leading/trailing separators and collapse multiple separators
74
+ # For dynamic separators, we need to use re.sub with escaped separator
75
+ if sep == "-":
76
+ # Use pre-compiled regex for common case
77
+ value = value.strip("-")
78
+ return _SLUGIFY_HYPHEN_COLLAPSE.sub("-", value)
79
+ # For other separators, use dynamic regex
80
+ value = re.sub(rf"^{re.escape(sep)}+|{re.escape(sep)}+$", "", value)
81
+ return re.sub(rf"{re.escape(sep)}+", sep, value)
75
82
 
76
83
 
77
84
  @lru_cache(maxsize=100)
@@ -94,6 +101,7 @@ def snake_case(string: str) -> str:
94
101
  Handles CamelCase, PascalCase, strings with spaces, hyphens, or dots
95
102
  as separators, and ensures single underscores. It also correctly
96
103
  handles acronyms (e.g., "HTTPRequest" becomes "http_request").
104
+ Handles Unicode letters and numbers.
97
105
 
98
106
  Args:
99
107
  string: The string to convert.
@@ -101,8 +109,32 @@ def snake_case(string: str) -> str:
101
109
  Returns:
102
110
  The snake_case version of the string.
103
111
  """
104
- s = _SNAKE_CASE_RE_ACRONYM_SEQUENCE.sub(r"\1_\2", string)
105
- s = _SNAKE_CASE_RE_LOWER_UPPER_TRANSITION.sub(r"\1_\2", s)
106
- s = _SNAKE_CASE_RE_REPLACE_SEP.sub("_", s).lower()
107
- s = _SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE.sub("_", s)
108
- return s.strip("_")
112
+ if not string:
113
+ return ""
114
+ # 1. Replace hyphens and spaces with underscores
115
+ s = _SNAKE_CASE_HYPHEN_SPACE.sub("_", string)
116
+
117
+ # 2. Remove all non-alphanumeric characters except underscores
118
+ # TODO: move to a compiled regex at the top of the file
119
+ s = re.sub(r"[^\w]+", "", s, flags=re.UNICODE)
120
+
121
+ # 3. Insert an underscore between a lowercase/digit and an uppercase letter.
122
+ # e.g., "helloWorld" -> "hello_World"
123
+ # e.g., "Python3IsGreat" -> "Python3_IsGreat"
124
+ # Uses a positive lookbehind `(?<=[...])` and a positive lookahead `(?=[...])`
125
+ s = _SNAKE_CASE_LOWER_OR_DIGIT_TO_UPPER.sub("_", s)
126
+
127
+ # 4. Insert an underscore between an uppercase letter and another
128
+ # uppercase letter followed by a lowercase letter.
129
+ # e.g., "HTTPRequest" -> "HTTP_Request"
130
+ # This handles acronyms gracefully.
131
+ s = _SNAKE_CASE_UPPER_TO_UPPER_LOWER.sub("_", s)
132
+
133
+ # 5. Convert the entire string to lowercase.
134
+ s = s.lower()
135
+
136
+ # 6. Remove any leading or trailing underscores that might have been created.
137
+ s = s.strip("_")
138
+
139
+ # 7. Collapse multiple consecutive underscores into a single one.
140
+ return _SNAKE_CASE_MULTIPLE_UNDERSCORES.sub("_", s)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: SQL Experiments in Python
5
5
  Project-URL: Discord, https://discord.gg/litestar
6
6
  Project-URL: Issue, https://github.com/litestar-org/sqlspec/issues/
@@ -11,14 +11,17 @@ License-Expression: MIT
11
11
  License-File: LICENSE
12
12
  License-File: NOTICE
13
13
  Requires-Python: <4.0,>=3.9
14
+ Requires-Dist: click
14
15
  Requires-Dist: eval-type-backport; python_version < '3.10'
15
- Requires-Dist: sqlglot
16
+ Requires-Dist: sqlglot>=19.9.0
16
17
  Requires-Dist: typing-extensions
17
18
  Provides-Extra: adbc
18
19
  Requires-Dist: adbc-driver-manager; extra == 'adbc'
19
20
  Requires-Dist: pyarrow; extra == 'adbc'
20
21
  Provides-Extra: aioodbc
21
22
  Requires-Dist: aioodbc; extra == 'aioodbc'
23
+ Provides-Extra: aiosql
24
+ Requires-Dist: aiosql; extra == 'aiosql'
22
25
  Provides-Extra: aiosqlite
23
26
  Requires-Dist: aiosqlite; extra == 'aiosqlite'
24
27
  Provides-Extra: asyncmy
@@ -27,25 +30,41 @@ Provides-Extra: asyncpg
27
30
  Requires-Dist: asyncpg; extra == 'asyncpg'
28
31
  Provides-Extra: bigquery
29
32
  Requires-Dist: google-cloud-bigquery; extra == 'bigquery'
33
+ Provides-Extra: cli
34
+ Requires-Dist: rich-click; extra == 'cli'
30
35
  Provides-Extra: duckdb
31
36
  Requires-Dist: duckdb; extra == 'duckdb'
32
37
  Provides-Extra: fastapi
33
38
  Requires-Dist: fastapi; extra == 'fastapi'
34
39
  Provides-Extra: flask
35
40
  Requires-Dist: flask; extra == 'flask'
41
+ Provides-Extra: fsspec
42
+ Requires-Dist: fsspec; extra == 'fsspec'
36
43
  Provides-Extra: litestar
37
44
  Requires-Dist: litestar; extra == 'litestar'
38
45
  Provides-Extra: msgspec
39
46
  Requires-Dist: msgspec; extra == 'msgspec'
40
47
  Provides-Extra: nanoid
41
48
  Requires-Dist: fastnanoid>=0.4.1; extra == 'nanoid'
49
+ Provides-Extra: obstore
50
+ Requires-Dist: obstore; extra == 'obstore'
51
+ Provides-Extra: opentelemetry
52
+ Requires-Dist: opentelemetry-instrumentation; extra == 'opentelemetry'
42
53
  Provides-Extra: oracledb
43
54
  Requires-Dist: oracledb; extra == 'oracledb'
44
55
  Provides-Extra: orjson
45
56
  Requires-Dist: orjson; extra == 'orjson'
57
+ Provides-Extra: pandas
58
+ Requires-Dist: pandas; extra == 'pandas'
59
+ Requires-Dist: pyarrow; extra == 'pandas'
46
60
  Provides-Extra: performance
47
61
  Requires-Dist: msgspec; extra == 'performance'
48
62
  Requires-Dist: sqlglot[rs]; extra == 'performance'
63
+ Provides-Extra: polars
64
+ Requires-Dist: polars; extra == 'polars'
65
+ Requires-Dist: pyarrow; extra == 'polars'
66
+ Provides-Extra: prometheus
67
+ Requires-Dist: prometheus-client; extra == 'prometheus'
49
68
  Provides-Extra: psqlpy
50
69
  Requires-Dist: psqlpy; extra == 'psqlpy'
51
70
  Provides-Extra: psycopg
@@ -60,7 +79,7 @@ Requires-Dist: pymysql; extra == 'pymysql'
60
79
  Provides-Extra: spanner
61
80
  Requires-Dist: google-cloud-spanner; extra == 'spanner'
62
81
  Provides-Extra: uuid
63
- Requires-Dist: uuid-utils>=0.6.1; extra == 'uuid'
82
+ Requires-Dist: uuid-utils; extra == 'uuid'
64
83
  Description-Content-Type: text/markdown
65
84
 
66
85
  # SQLSpec
@@ -69,18 +88,26 @@ Description-Content-Type: text/markdown
69
88
 
70
89
  SQLSpec is an experimental Python library designed to streamline and modernize your SQL interactions across a variety of database systems. While still in its early stages, SQLSpec aims to provide a flexible, typed, and extensible interface for working with SQL in Python.
71
90
 
72
- **Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
91
+ **Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
73
92
 
74
- ## Core Features (Planned but subject to change, removal or redesign)
93
+ ## Core Features (Current and Planned)
94
+
95
+ ### Currently Implemented
75
96
 
76
97
  - **Consistent Database Session Interface**: Provides a consistent connectivity interface for interacting with one or more database systems, including SQLite, Postgres, DuckDB, MySQL, Oracle, SQL Server, Spanner, BigQuery, and more.
77
- - **Emphasis on RAW SQL and Minimal Abstractions and Performance**: SQLSpec is a library for working with SQL in Python. It's goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
98
+ - **Emphasis on RAW SQL and Minimal Abstractions**: SQLSpec is a library for working with SQL in Python. Its goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
78
99
  - **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msgspec, Attrs, etc.
79
- - **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
80
- - **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on it's own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
81
- - **Dynamic Query Manipulation**: Easily apply filters to pre-defined queries with a fluent, Pythonic API. Safely manipulate queries without the risk of SQL injection.
82
- - **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
100
+ - **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
101
+ - **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on its own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
83
102
  - **Support for Async and Sync Database Drivers**: SQLSpec supports both async and sync database drivers, allowing you to choose the style that best fits your application.
103
+
104
+ ### Experimental Features (API will change rapidly)
105
+
106
+ - **SQL Builder API**: Type-safe query builder with method chaining (experimental and subject to significant changes)
107
+ - **Dynamic Query Manipulation**: Apply filters to pre-defined queries with a fluent API. Safely manipulate queries without SQL injection risk.
108
+ - **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
109
+ - **Storage Operations**: Direct export to Parquet, CSV, JSON with Arrow integration
110
+ - **Instrumentation**: OpenTelemetry and Prometheus metrics support
84
111
  - **Basic Migration Management**: A mechanism to generate empty migration files where you can add your own SQL and intelligently track which migrations have been applied.
85
112
 
86
113
  ## What SQLSpec Is Not (Yet)
@@ -91,16 +118,60 @@ SQLSpec is a work in progress. While it offers a solid foundation for modern SQL
91
118
 
92
119
  We've talked about what SQLSpec is not, so let's look at what it can do.
93
120
 
94
- These are just a few of the examples that demonstrate SQLSpec's flexibility and each of the bundled adapters offer the same config and driver interfaces.
121
+ These are just a few examples that demonstrate SQLSpec's flexibility. Each of the bundled adapters offers the same config and driver interfaces.
122
+
123
+ ### Basic Usage
124
+
125
+ ```python
126
+ from sqlspec import SQLSpec
127
+ from sqlspec.adapters.sqlite import SqliteConfig
128
+ from pydantic import BaseModel
129
+ # Create SQLSpec instance and configure database
130
+ sql = SQLSpec()
131
+ config = sql.add_config(SqliteConfig(database=":memory:"))
132
+
133
+ # Execute queries with automatic result mapping
134
+ with sql.provide_session(config) as session:
135
+ # Simple query
136
+ result = session.execute("SELECT 'Hello, SQLSpec!' as message")
137
+ print(result.get_first()) # {'message': 'Hello, SQLSpec!'}
138
+ ```
139
+
140
+ ### SQL Builder Example (Experimental)
141
+
142
+ **Warning**: The SQL Builder API is highly experimental and will change significantly.
143
+
144
+ ```python
145
+ from sqlspec import sql
146
+
147
+ # Build a simple query
148
+ query = sql.select("id", "name", "email").from_("users").where("active = ?", True)
149
+ print(query.build().sql) # SELECT id, name, email FROM users WHERE active = ?
150
+
151
+ # More complex example with joins
152
+ query = (
153
+ sql.select("u.name", "COUNT(o.id) as order_count")
154
+ .from_("users u")
155
+ .left_join("orders o", "u.id = o.user_id")
156
+ .where("u.created_at > ?", "2024-01-01")
157
+ .group_by("u.name")
158
+ .having("COUNT(o.id) > ?", 5)
159
+ .order_by("order_count", desc=True)
160
+ )
161
+
162
+ # Execute the built query
163
+ with sql.provide_session(config) as session:
164
+ results = session.execute(query.build())
165
+ ```
95
166
 
96
167
  ### DuckDB LLM
97
168
 
98
- This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
169
+ This is a quick implementation using some of the built-in Secret and Extension management features of SQLSpec's DuckDB integration.
99
170
 
100
- It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
171
+ It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This example:
101
172
 
102
173
  - auto installs the `open_prompt` DuckDB extensions
103
- - automatically creates the correct `open_prompt` comptaible secret required to use the extension
174
+ - automatically creates the correct `open_prompt` compatible secret required to use the extension
104
175
 
105
176
  ```py
106
177
  # /// script
@@ -145,12 +216,12 @@ with sql.provide_session(etl_config) as session:
145
216
 
146
217
  ### DuckDB Gemini Embeddings
147
218
 
148
- In this example, we are again using DuckDB. However, we are going to use the built in to call the Google Gemini embeddings service directly from the database.
219
+ In this example, we are again using DuckDB. However, we are going to use the built-in to call the Google Gemini embeddings service directly from the database.
149
220
 
150
- This example will
221
+ This example will:
151
222
 
152
223
  - auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
153
- - when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
224
+ - when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database
154
225
  - Execute a simple query to call the Google API
155
226
 
156
227
  ```py
@@ -196,8 +267,8 @@ etl_config = sql.add_config(
196
267
  )
197
268
  )
198
269
  with sql.provide_session(etl_config) as session:
199
- result = session.select_one("SELECT generate_embedding('example text')")
200
- print(result) # result is a dictionary when `schema_type` is omitted.
270
+ result = session.execute("SELECT generate_embedding('example text')")
271
+ print(result.get_first()) # result is a dictionary when `schema_type` is omitted.
201
272
  ```
202
273
 
203
274
  ### Basic Litestar Integration
@@ -212,11 +283,10 @@ In this example we are going to demonstrate how to create a basic configuration
212
283
  # ]
213
284
  # ///
214
285
 
215
- from aiosqlite import Connection
216
286
  from litestar import Litestar, get
217
287
 
218
288
  from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
219
- from sqlspec.extensions.litestar import SQLSpec
289
+ from sqlspec.extensions.litestar import DatabaseConfig, SQLSpec
220
290
 
221
291
 
222
292
  @get("/")
@@ -224,15 +294,18 @@ async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
224
294
  return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
225
295
 
226
296
 
227
- sqlspec = SQLSpec(config=DatabaseConfig(
228
- config=[AiosqliteConfig(), commit_mode="autocommit")],
297
+ sqlspec = SQLSpec(
298
+ config=DatabaseConfig(
299
+ config=AiosqliteConfig(),
300
+ commit_mode="autocommit"
301
+ )
229
302
  )
230
303
  app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
231
304
  ```
232
305
 
233
306
  ## Inspiration and Future Direction
234
307
 
235
- SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
308
+ SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executing SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
236
309
 
237
310
  ## Current Focus: Universal Connectivity
238
311
 
@@ -272,9 +345,10 @@ This list is not final. If you have a driver you'd like to see added, please ope
272
345
  - `litestar/`: Litestar framework integration ✅
273
346
  - `fastapi/`: Future home of `fastapi` integration.
274
347
  - `flask/`: Future home of `flask` integration.
275
- - `*/`: Future home of your favorite framework integration 🔌 ✨
348
+ - `*/`: Future home of your favorite framework integration
276
349
  - `base.py`: Contains base protocols for database configurations.
277
- - `filters.py`: Contains the `Filter` class which is used to apply filters to pre-defined SQL queries.
350
+ - `statement/`: Contains the SQL statement system with builders, validation, and transformation.
351
+ - `storage/`: Contains unified storage operations for data import/export.
278
352
  - `utils/`: Contains utility functions used throughout the project.
279
353
  - `exceptions.py`: Contains custom exceptions for SQLSpec.
280
354
  - `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.
@@ -0,0 +1,145 @@
1
+ sqlspec/__init__.py,sha256=hyVFQsYsgDWOZ2EPnW1LnATQVxGcYu3liBvSOvk4EQk,705
2
+ sqlspec/__metadata__.py,sha256=hNP3wXvtk8fQVPKGjRLpZ9mP-gaPJqzrmgm3UqpDIXQ,460
3
+ sqlspec/_serialization.py,sha256=7zox4G9zIps-DCdIEwYs4gwALfEOy1g_sWS4r5kpzO8,2604
4
+ sqlspec/_sql.py,sha256=VvSttObOgEDN_qECiOZu07_c3pgC1f9cdOORn-xWc88,42463
5
+ sqlspec/_typing.py,sha256=Vn1CTCfedAHZV3pKZP-l_mPw9pTxesCzRKVRypzNY_k,17903
6
+ sqlspec/base.py,sha256=a7adbCUzohf1MU-iP0TxazGsk9fsJhJmxuFKNWkgC6o,18355
7
+ sqlspec/config.py,sha256=a5VZj3UvK_St2XSchUw7NL3YBDpYp_FlaoVM8OkaI8I,13144
8
+ sqlspec/exceptions.py,sha256=Qdfd1k9Q4rTDH15zja2UzCOYAbR7idN3xGutDYGg3eg,13934
9
+ sqlspec/loader.py,sha256=1htipEcioTGrORu4sEYbK5w-zMnpWIZ4xSQlN-pJSf0,18336
10
+ sqlspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ sqlspec/typing.py,sha256=Wxc-ctN0hJ41U-qDzOaBA_HwTwAaQ7pN1nu0FpCNruA,20792
12
+ sqlspec/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ sqlspec/adapters/adbc/__init__.py,sha256=v9bs7501PgEyzR1XIsEpE2Wdrj9DOYkZ4grysw72UXk,218
14
+ sqlspec/adapters/adbc/config.py,sha256=-wkuxXj-cqTFeIA7_mnPD37oZCHrnVjkOYKIwTZkD1Y,20159
15
+ sqlspec/adapters/adbc/driver.py,sha256=22P16Pz6Bk399TSjoODLK1ZRcXxTHMGmjp_3KuCSUzM,16462
16
+ sqlspec/adapters/aiosqlite/__init__.py,sha256=7wPmhXQeu4jRi-LZzPxAPTdgRmgmyqCn9U-4wnCWoLM,258
17
+ sqlspec/adapters/aiosqlite/config.py,sha256=K8vPiGSDeSCTFIm4XgCEGbXG8uIAX6JjYHv2890RbTw,7174
18
+ sqlspec/adapters/aiosqlite/driver.py,sha256=DelxxH9_TKHmqYDG3HbXEs4ypk8r-FUdBnGZOBNvHek,12398
19
+ sqlspec/adapters/asyncmy/__init__.py,sha256=zYpebEt_PrNCifLcqXiCcWVm0Zl-LvWbFDromWwSTw8,270
20
+ sqlspec/adapters/asyncmy/config.py,sha256=ZCwg63zsa-SEiHjJjCZYvnu-hl5cdw-o8j3u01_r7W4,10402
21
+ sqlspec/adapters/asyncmy/driver.py,sha256=Q3dVCcm24z-Cvd2GcHaZKfP95cb5uk7u1-b8zuMQJpo,9982
22
+ sqlspec/adapters/asyncpg/__init__.py,sha256=svnbKlOin8jRL88AdAqflBEU-WEAzp0Thc2y50QsxIo,310
23
+ sqlspec/adapters/asyncpg/config.py,sha256=IHovVNGryGsu_ulYBY9TJrXaz_mPpqIgnh4c-juIglA,13033
24
+ sqlspec/adapters/asyncpg/driver.py,sha256=U32J4W4RXvW5iQfqBI6_uhVqc4Kyaj2IpUe9BRJS8r4,19105
25
+ sqlspec/adapters/bigquery/__init__.py,sha256=fWRH-BoCNX4rYwhU2DK64cXWpfkYpWIExddJAti0bxM,250
26
+ sqlspec/adapters/bigquery/config.py,sha256=bTmos8OcJcy7kPmBds-0EPLe5XyREnwOR0YYd5fkZjg,16971
27
+ sqlspec/adapters/bigquery/driver.py,sha256=46m5D-03mFnKM0rLwuvmeGAkRotbwm_qh6X0Re88H1I,28412
28
+ sqlspec/adapters/duckdb/__init__.py,sha256=I1f6szfpKKrq6WhyDoUXD3i3NN4yjsh94_fhP1URI5M,351
29
+ sqlspec/adapters/duckdb/config.py,sha256=az9WFJXyw1M0yiNw2tqf7GYM-9tblHj_0BHLYzFytXk,20413
30
+ sqlspec/adapters/duckdb/driver.py,sha256=Vnr6xYJtqBKHAf76xy9o18GYly_oexkEfAd25Jd_CZ4,17676
31
+ sqlspec/adapters/oracledb/__init__.py,sha256=nn3whn0UyBThoXnE1-5_byVuc9PJjvB2P896p7LpNZI,474
32
+ sqlspec/adapters/oracledb/config.py,sha256=HQpgGMf0oMSWr2k4q3uPEF4LWR7QPnzZE6lxLDq723U,22737
33
+ sqlspec/adapters/oracledb/driver.py,sha256=YQnudVnP1EizI4eN3_llITdJ7TjpbLNxFkYlkSJVaQs,25463
34
+ sqlspec/adapters/psqlpy/__init__.py,sha256=dp0-96V4SAbNEvOqlJ8PWEyJMYzZGElVoyneZqJ-fbQ,297
35
+ sqlspec/adapters/psqlpy/config.py,sha256=NKlHHDjKr5dF4LQprYA5ivJsNy2UXkvYg8B-kXOvvjE,16342
36
+ sqlspec/adapters/psqlpy/driver.py,sha256=xI89mFdkQulcntbH4ALTOOHn5b6_skCgSbjYDUfvyG4,8650
37
+ sqlspec/adapters/psycopg/__init__.py,sha256=ukkCUPrJPyAG78v4rOqcK4WZDs26PeB9Ra9qkFrGJ3E,484
38
+ sqlspec/adapters/psycopg/config.py,sha256=pNgh0FAB_5dpRHBY9zKEs9uofDtUod2IV4pjCY_jWK8,27723
39
+ sqlspec/adapters/psycopg/driver.py,sha256=oTdhj5OXx1gtnA0ZIS0Fdvqu8erXhItn1fl0-lRxatI,33474
40
+ sqlspec/adapters/sqlite/__init__.py,sha256=1lYrJ-DojUAOvXMoZRUJNEVyMmYhO41hMJnDWCEeXlw,234
41
+ sqlspec/adapters/sqlite/config.py,sha256=7yHe1eeVGFZvmTdxUPF2XcIiEcgZFUdncuGf_6qG8Xc,6153
42
+ sqlspec/adapters/sqlite/driver.py,sha256=aQ7JOWyC6pfSq2cRz3OrjQ67NChhU0UercgvgomU0Ec,10703
43
+ sqlspec/driver/__init__.py,sha256=0udRS5IlJ17HzOCvzapG8c_88yAwTQri1XLD_3fZxZU,671
44
+ sqlspec/driver/_async.py,sha256=JYn-8E_IQHBCpAPfZ3g0IpNc_0yCwYu98lKgcHxWdPU,10130
45
+ sqlspec/driver/_common.py,sha256=ceAvzvI9zV3xBotEAMCuJeEbCHaeV82UJyfYYNnrspk,14680
46
+ sqlspec/driver/_sync.py,sha256=8jyP-TInSM3iLNhyOMNthvoE6vNwPp2wV8oAQhObuqc,10255
47
+ sqlspec/driver/mixins/__init__.py,sha256=-FSWLYq644NftRsmjmXMA9Q7_l7tIFAIh1ZyK0yrba8,652
48
+ sqlspec/driver/mixins/_pipeline.py,sha256=XCr4PTUvvzvte2Yw1g-hqje5dg3bgrsi46kj8kdy8Hw,20083
49
+ sqlspec/driver/mixins/_result_utils.py,sha256=j6BrFCC9E6xbnn-mH0sd2JBlxZFjA30LWKrYZh8gjXM,4882
50
+ sqlspec/driver/mixins/_sql_translator.py,sha256=p_PR4KBg9NKNpRpiEqA0hcUIttpdillHpnLUVJEcxuE,1519
51
+ sqlspec/driver/mixins/_storage.py,sha256=yosmC_nJI-3dg4aVy6iloy4V-d9DBDoC_8G2RLTsenI,43106
52
+ sqlspec/driver/mixins/_type_coercion.py,sha256=17HC2Vsd70tRlUawO0CkUeoJUd2jG5R5Yb1A6Jr-1Tc,4716
53
+ sqlspec/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ sqlspec/extensions/aiosql/__init__.py,sha256=-9cefc9pYPf9vCgALoB-y1DtmcgRjKe2azfl6RIarAA,414
55
+ sqlspec/extensions/aiosql/adapter.py,sha256=EcMzTQ2-EzH-C2G1nJ6dw5O09rUzdAclmgbFb9wkJ8E,16993
56
+ sqlspec/extensions/litestar/__init__.py,sha256=aXF2g4-U86pdJHoOA6RCvZgnyHVBbjRhlWqcSuRX2gg,243
57
+ sqlspec/extensions/litestar/_utils.py,sha256=o-FuUj1_WkDrLxQxiP6hXDak66XfyRP3QLyEVKrIRjI,1954
58
+ sqlspec/extensions/litestar/config.py,sha256=vLXM425tCV3IbJiNO1ZG90ctjBTb9oQCuLsqCaUYmo8,4685
59
+ sqlspec/extensions/litestar/handlers.py,sha256=q-peGdWgvEI_s9rWt0SRIQvuhON_ItrjiVxIF2Pwm1U,10546
60
+ sqlspec/extensions/litestar/plugin.py,sha256=itsduzXN-YzDm1wVqUcJQLcYGp3ogF9Aw2IU3i46iqk,5596
61
+ sqlspec/extensions/litestar/providers.py,sha256=9wAr3c09ObOJmej1hQ3YizrK3YMN3S2xfBh23r-KSzE,21749
62
+ sqlspec/service/__init__.py,sha256=EfyTy8X8GXxV0drxaBMJ0aRRqg3ZnwD6iu5oCTAQc1k,79
63
+ sqlspec/service/base.py,sha256=vbJFO0EywWUgGr8WHHYxUCP-7sGF1Rxfi7ov51LWg50,521
64
+ sqlspec/service/pagination.py,sha256=ndLQwsvswoISWEE_3IG9nmdHt42OZkVMJvr-2HTWsLw,619
65
+ sqlspec/statement/__init__.py,sha256=NDvdrpr1EqAZXp4HmhTVaRnWVscahPSHpmSO8DHSoMY,536
66
+ sqlspec/statement/filters.py,sha256=SPDupr8mJK1Ua3z2sXvE8dWAkamDAhE2MHn6yEM_6uU,21850
67
+ sqlspec/statement/parameters.py,sha256=HjKg6Y-1ImBiigNlodGxsVOMPma1pBoJRISrQu_iqfM,31183
68
+ sqlspec/statement/result.py,sha256=rEShBX-NGK3-0K6q1XwB0zQvPEygVVB_-rXodiUMbSo,18307
69
+ sqlspec/statement/splitter.py,sha256=Y1eubbNSn3IRhvQhAZVzBB-oDZ5K5uoJYOGti1ds_5E,24850
70
+ sqlspec/statement/sql.py,sha256=7H2LOwQ8H2pONFPF7RcK6WkF7g_J-FUeuoiSXD05AUs,51033
71
+ sqlspec/statement/builder/__init__.py,sha256=7mITd7RG_Sc4RBgQJoAAosLAV9WdF4-E-CzvUA-hT0A,1584
72
+ sqlspec/statement/builder/_ddl_utils.py,sha256=or0DpLIUupCIxs3u6kMJQgmfj_P21TxMDHbM0rdSNnY,4745
73
+ sqlspec/statement/builder/_parsing_utils.py,sha256=OKOB-V1UhOCUNVoJHDArUl0WKIMVPshCFFrJcjKvs9Y,5613
74
+ sqlspec/statement/builder/base.py,sha256=swpCj0Oga3HyLKKmriwsu046puvkTxTZ528SPa9v_kk,12771
75
+ sqlspec/statement/builder/ddl.py,sha256=0GjjPc8u3FP_5kFza-J2kw0B0PBlibgjAu7kCgDMwXI,50394
76
+ sqlspec/statement/builder/delete.py,sha256=yv78i2vWpRZ0NbQCkJz1JAYekius2MOZ_zmiVaP4fcw,2423
77
+ sqlspec/statement/builder/insert.py,sha256=EduHjewraoauM4mH3r4OyrBc31FbCAad93B8vg9WpYc,9922
78
+ sqlspec/statement/builder/merge.py,sha256=tNV81MiDUmQJ9KiInP8rEGvxQ50JAD2Itmdbr5921vI,2811
79
+ sqlspec/statement/builder/protocols.py,sha256=ihy6uNv6lGdj1UHu-qWn08YhIn_YfjPup0qsBnaB1zU,575
80
+ sqlspec/statement/builder/select.py,sha256=13dNa7XXHjGlSeRsjWTrOCZX0uK61mMbiRzk1gTq8is,8436
81
+ sqlspec/statement/builder/update.py,sha256=K2DxlZM9e0DoO4T5MbeVNL9BCkhov7z8c6L9zuvjttc,5950
82
+ sqlspec/statement/builder/mixins/__init__.py,sha256=B5GhsdySb_-DN3SvBlA2oimmymAJX3Rf4A7Xnz3uNN4,2887
83
+ sqlspec/statement/builder/mixins/_aggregate_functions.py,sha256=RU91GKzwKABod-nHxhrT2nCoYFAf-kSE4VHmF23n__Y,6109
84
+ sqlspec/statement/builder/mixins/_case_builder.py,sha256=fGdevoEZxmoJjsDV9Wwfom8vu3lmgF9B_o5HXCf25Kg,3047
85
+ sqlspec/statement/builder/mixins/_common_table_expr.py,sha256=1e8KKoQjuMGKuutjZ4KFWhsH7mbRMhXsANqLLJ71SzA,3741
86
+ sqlspec/statement/builder/mixins/_delete_from.py,sha256=GtuTYfG7N9RPAbyXIGKCoirRTg_gcHyoGI6pAFhUkEY,1026
87
+ sqlspec/statement/builder/mixins/_from.py,sha256=YOYG-Bvpis9Wt2RI4byr_eRef35OXS6rBuigGsEOGW0,2618
88
+ sqlspec/statement/builder/mixins/_group_by.py,sha256=qefERqljQY58PmJ3Q0nF8NNSO31fa2XDbevIpjiPzJs,4190
89
+ sqlspec/statement/builder/mixins/_having.py,sha256=X8-hdwEeJg4RYxyjhaYLvlkpzE0AwIPl6t8SPGz5gi0,1112
90
+ sqlspec/statement/builder/mixins/_insert_from_select.py,sha256=XBahvM2VA-qwzx3PLTRaqT21fFaRYwHACOADQ6mZwUE,1851
91
+ sqlspec/statement/builder/mixins/_insert_into.py,sha256=7979JCYqKM_NRTHwkrJJY6l9lS2AQ-evZYRU8fs3yw0,1049
92
+ sqlspec/statement/builder/mixins/_insert_values.py,sha256=RE2ApSc6OwVqToXTVwy1bhRFomfNOmrnSte8fVjEINg,2923
93
+ sqlspec/statement/builder/mixins/_join.py,sha256=g3OxKMEiyNSGZRiBgdPT1Lvcr-h3u_3O0msN59B1Itg,5128
94
+ sqlspec/statement/builder/mixins/_limit_offset.py,sha256=nyeajD1cYj0Wvki1GLYJbsfQzfaH5tyMkeGVU9fGWL0,1762
95
+ sqlspec/statement/builder/mixins/_merge_clauses.py,sha256=3w22HImSoQvDMMTa9xJAHw4cx0-KrteLumFpQvg2o0I,16868
96
+ sqlspec/statement/builder/mixins/_order_by.py,sha256=pcqEQIkpJ-KgLNLIqXFQQgdzGypXw0Umndn-X8TgKis,1729
97
+ sqlspec/statement/builder/mixins/_pivot.py,sha256=GyLEFkhRlG_fxeRfzGRTVd5wZVtuA5HkNrvmOi7PF3Q,3442
98
+ sqlspec/statement/builder/mixins/_returning.py,sha256=O39j2MEIcqiiUhFFGnyGwIXhLS7KrGigfZ9kPxFjjtI,1349
99
+ sqlspec/statement/builder/mixins/_select_columns.py,sha256=6UXpHHDmka8NbrtbR-G-Xd1ux4DUazEonZndAXecWJI,2302
100
+ sqlspec/statement/builder/mixins/_set_ops.py,sha256=uWV32ZAi2tojbS9b6Q0ZDIn1Rhbx4cCE42jhbVdm90I,5291
101
+ sqlspec/statement/builder/mixins/_unpivot.py,sha256=dXdYk4UdFbDf7yNFRPrX3G5XtOgfw_BzaEI9au3ltKw,3296
102
+ sqlspec/statement/builder/mixins/_update_from.py,sha256=r8-_iy5Kdp79eo34oNmNVLSnWsy3WUvwETODnKzBgZY,2461
103
+ sqlspec/statement/builder/mixins/_update_set.py,sha256=tSnZ6cLKfta-OKHYAkoInQScMbxp9rxtFj0SBGnpGZ0,4041
104
+ sqlspec/statement/builder/mixins/_update_table.py,sha256=FX3KezuHdu7YLQI4i5iniHWk1Lbzph8MzLcOM6iTd70,936
105
+ sqlspec/statement/builder/mixins/_where.py,sha256=KZhOykAWrDYaD6p_W-nbVkh3-9ZS9paw77L3JttoeT8,19452
106
+ sqlspec/statement/builder/mixins/_window_functions.py,sha256=8ldy06gK6jOlGg31oa1dCrG7IkfCVYvVr_f-lx0YcgU,3745
107
+ sqlspec/statement/pipelines/__init__.py,sha256=vmFxkD7vnpyfMbuDsOF67B3DWDeCz183326pg1G0-5k,2206
108
+ sqlspec/statement/pipelines/base.py,sha256=ylXSyab6P4v9PY0tDPlcHeCEkdFPECDq0Jjooi3E2ek,13019
109
+ sqlspec/statement/pipelines/context.py,sha256=fhEKicpUcHXbyhgBpJnYnYPd4vWpkFoVuLWydsSB2dE,4371
110
+ sqlspec/statement/pipelines/result_types.py,sha256=G34HofWjcK0SFMTyqVBFv-t17jkWKP9cCugA4Rds4qk,1046
111
+ sqlspec/statement/pipelines/analyzers/__init__.py,sha256=RY7W0AiWG-8qdrTmRSGlEofjrPPJCJUnNK-LRukKt5Q,330
112
+ sqlspec/statement/pipelines/analyzers/_analyzer.py,sha256=8Cfxr4gZZlfmn4v3tatyqF4i10s6L9lFXRYwcVB_zn4,27741
113
+ sqlspec/statement/pipelines/transformers/__init__.py,sha256=wwhAWQQCCoL2WhVZQ7ptt9mn4B_AY8pK9M2SUjj5DtU,550
114
+ sqlspec/statement/pipelines/transformers/_expression_simplifier.py,sha256=90u62-WMG0l1_2S_u-93Oo3rVnAjvlTJkPf1IzgaP2E,11630
115
+ sqlspec/statement/pipelines/transformers/_literal_parameterizer.py,sha256=NMzSYZ6HfqoujOm_M5pS95oxOhF3_kWrQZjWln4UGEI,26624
116
+ sqlspec/statement/pipelines/transformers/_remove_comments.py,sha256=PW1q7B2D-E_x2V1mTEUw_Uijj9W5-B6OteWE96aH7i8,2781
117
+ sqlspec/statement/pipelines/transformers/_remove_hints.py,sha256=D13MDx9vG3n_y5VV6swTNx2z1zHnTAuRwOiKp0VYg2k,3334
118
+ sqlspec/statement/pipelines/validators/__init__.py,sha256=cdlwdLhOT2OwTbueIsA7bfRG2b6y-j7dw9pMzl5AP0M,747
119
+ sqlspec/statement/pipelines/validators/_dml_safety.py,sha256=FUfF7iWUc0tgmg-OwDgpYA3ZRy3z01PfGadDcaqENTM,10078
120
+ sqlspec/statement/pipelines/validators/_parameter_style.py,sha256=I6tTeYBQFeg2uPlQWDyy7sMRidm_tt7ItTzhauhNrWA,13583
121
+ sqlspec/statement/pipelines/validators/_performance.py,sha256=sSIknorC-VJghFJAATqfnnNUyUnQ0bN_GpXmmGZkkkA,25800
122
+ sqlspec/statement/pipelines/validators/_security.py,sha256=62k5F4RCz1O_bb1rIPjm2BjHyp3YDObq2hjv74zY8Ac,43589
123
+ sqlspec/statement/pipelines/validators/base.py,sha256=6xd0FCPOTpS77cn-abT1auubxASs5HPY2fgjhX1WZZQ,2166
124
+ sqlspec/storage/__init__.py,sha256=dS1Qt2cTJpIBOKnw3ih3Z7FPFePFPPSazhkEbkV5DxU,516
125
+ sqlspec/storage/protocol.py,sha256=4hiGGmWtMZFkwCaNYXHt416j-i281xha0Hj7-EynVBs,6430
126
+ sqlspec/storage/registry.py,sha256=it3S-jxf-rXcYwgquydiSo0AeXXqnBEhAVQ2Gk11GNU,11724
127
+ sqlspec/storage/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
+ sqlspec/storage/backends/base.py,sha256=34XYQuz1tQ-q_ZZwOz-Kimgvl088SR3VUYJoA-STslc,6350
129
+ sqlspec/storage/backends/fsspec.py,sha256=bCaNkubANlcb3UlUC0EchHn44XJRS3Z-99fnZMgW-yc,12527
130
+ sqlspec/storage/backends/obstore.py,sha256=HdnEGQOPvQY9q7xEsjdy7JIqj-tWNBLkmEmllbDgAWA,20659
131
+ sqlspec/utils/__init__.py,sha256=_Ya8IZuc2cZIstXr_xjgnSfxICXHXvu5mfWsi2USDrw,183
132
+ sqlspec/utils/correlation.py,sha256=qzqw3CnhasS14hv0uHKh9DehbOX3dEHuB_NNz6Kg6QQ,4457
133
+ sqlspec/utils/deprecation.py,sha256=zrmb_eKRlLWVA6dWrjUbN3Vz6D3_-Z_15Ixk4H-sDRk,3850
134
+ sqlspec/utils/fixtures.py,sha256=q_Pghpmw2VgJ9P0TfkyjSF5PvdaD5Y2Laha0Bj4IDrA,1838
135
+ sqlspec/utils/logging.py,sha256=g8lZXfbr79Ayu0YnnoOcwzGGeg9HUg_JyFpAbbUCd_0,4064
136
+ sqlspec/utils/module_loader.py,sha256=9LcmEhy4T0jgkCaDVkxX47PSgJOMeJ8IV67yXEWBp-U,3074
137
+ sqlspec/utils/serializers.py,sha256=TKsRryRcYMnb8Z8MGkYGClIxcYvC8CW7MsrPQTJqEcY,154
138
+ sqlspec/utils/singleton.py,sha256=KZ7481tlDAxq6gcAlpULVqPLNc9P0XkHOEp7hfWIHcI,1096
139
+ sqlspec/utils/sync_tools.py,sha256=9ZL_7wJks896ZsRGVB4mS8DgIwK3tKmZClvLblEx8q4,8954
140
+ sqlspec/utils/text.py,sha256=Bit0I0nBgETvfumzguOQFiqrqwplqaoTeEfGdLzgPOk,5083
141
+ sqlspec-0.12.0.dist-info/METADATA,sha256=fUqPZZSl8key5koLqohfDZ2IUlyJ1Z1qbokEcLYdSS8,16663
142
+ sqlspec-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
143
+ sqlspec-0.12.0.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
144
+ sqlspec-0.12.0.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
145
+ sqlspec-0.12.0.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- from sqlspec.adapters.bigquery.config._sync import BigQueryConfig, BigQueryConnectionConfig
2
-
3
- __all__ = ("BigQueryConfig", "BigQueryConnectionConfig")
@@ -1,40 +0,0 @@
1
- from dataclasses import dataclass, field
2
- from typing import TYPE_CHECKING, Optional
3
-
4
- from google.cloud.bigquery import LoadJobConfig, QueryJobConfig
5
-
6
- if TYPE_CHECKING:
7
- from google.api_core.client_info import ClientInfo
8
- from google.api_core.client_options import ClientOptions
9
- from google.auth.credentials import Credentials
10
-
11
- __all__ = ("BigQueryConnectionConfigCommon",)
12
-
13
-
14
- @dataclass
15
- class BigQueryConnectionConfigCommon:
16
- """Common configuration options for BigQuery."""
17
-
18
- project: "Optional[str]" = field(default=None)
19
- """Google Cloud project ID."""
20
- location: "Optional[str]" = field(default=None)
21
- """Default geographic location for jobs and datasets."""
22
- credentials: "Optional[Credentials]" = field(default=None, hash=False)
23
- """Credentials to use for authentication."""
24
- dataset_id: "Optional[str]" = field(default=None)
25
- """Default dataset ID to use if not specified in queries."""
26
- credentials_path: "Optional[str]" = field(default=None)
27
- """Path to Google Cloud service account key file (JSON). If None, attempts default authentication."""
28
- client_options: "Optional[ClientOptions]" = field(default=None, hash=False)
29
- """Client options used to set user options on the client (e.g., api_endpoint)."""
30
- default_query_job_config: "Optional[QueryJobConfig]" = field(default=None, hash=False)
31
- """Default QueryJobConfig settings."""
32
- default_load_job_config: "Optional[LoadJobConfig]" = field(default=None, hash=False)
33
- """Default LoadJobConfig settings."""
34
- client_info: "Optional[ClientInfo]" = field(default=None, hash=False)
35
- """Client info used to send a user-agent string along with API requests."""
36
-
37
- def __post_init__(self) -> None:
38
- """Post-initialization hook."""
39
- if self.default_query_job_config is None:
40
- self.default_query_job_config = QueryJobConfig(default_dataset=self.dataset_id)
@@ -1,87 +0,0 @@
1
- import contextlib
2
- from dataclasses import dataclass, field
3
- from typing import TYPE_CHECKING, Any, Optional
4
-
5
- from sqlspec.adapters.bigquery.config._common import BigQueryConnectionConfigCommon
6
- from sqlspec.adapters.bigquery.driver import BigQueryConnection, BigQueryDriver
7
- from sqlspec.base import NoPoolSyncConfig
8
- from sqlspec.typing import dataclass_to_dict
9
-
10
- if TYPE_CHECKING:
11
- from collections.abc import Iterator
12
-
13
- __all__ = ("BigQueryConfig", "BigQueryConnectionConfig")
14
-
15
-
16
- class BigQueryConnectionConfig(BigQueryConnectionConfigCommon):
17
- """BigQuery Connection Configuration."""
18
-
19
-
20
- @dataclass
21
- class BigQueryConfig(NoPoolSyncConfig["BigQueryConnection", "BigQueryDriver"]):
22
- """BigQuery Synchronous Driver Configuration."""
23
-
24
- connection_config: "BigQueryConnectionConfig" = field(default_factory=BigQueryConnectionConfig)
25
- """BigQuery Connection Configuration."""
26
- driver_type: "type[BigQueryDriver]" = field(init=False, repr=False, default=BigQueryDriver)
27
- """BigQuery Driver Type."""
28
- connection_type: "type[BigQueryConnection]" = field(init=False, repr=False, default=BigQueryConnection)
29
- """BigQuery Connection Type."""
30
- pool_instance: "None" = field(init=False, repr=False, default=None, hash=False)
31
- """This is set to have a init=False since BigQuery does not support pooling."""
32
- connection_instance: "Optional[BigQueryConnection]" = field(init=False, repr=False, default=None, hash=False)
33
- """BigQuery Connection Instance."""
34
-
35
- @property
36
- def connection_config_dict(self) -> "dict[str, Any]":
37
- """Return the connection configuration as a dict.
38
-
39
- Returns:
40
- A string keyed dict of config kwargs for the BigQueryConnection constructor.
41
- """
42
- return dataclass_to_dict(
43
- self.connection_config,
44
- exclude_empty=True,
45
- exclude_none=True,
46
- exclude={"dataset_id", "credentials_path"},
47
- )
48
-
49
- def create_connection(self) -> "BigQueryConnection":
50
- """Create a BigQuery Client instance.
51
-
52
- Returns:
53
- A BigQuery Client instance.
54
- """
55
- if self.connection_instance is not None:
56
- return self.connection_instance
57
-
58
- self.connection_instance = self.connection_type(**self.connection_config_dict)
59
- return self.connection_instance
60
-
61
- @contextlib.contextmanager
62
- def provide_connection(self, *args: Any, **kwargs: Any) -> "Iterator[BigQueryConnection]":
63
- """Provide a BigQuery client within a context manager.
64
-
65
- Args:
66
- *args: Additional arguments to pass to the connection.
67
- **kwargs: Additional keyword arguments to pass to the connection.
68
-
69
- Yields:
70
- An iterator of BigQuery Client instances.
71
- """
72
- conn = self.create_connection()
73
- yield conn
74
-
75
- @contextlib.contextmanager
76
- def provide_session(self, *args: Any, **kwargs: Any) -> "Iterator[BigQueryDriver]":
77
- """Provide a BigQuery driver session within a context manager.
78
-
79
- Args:
80
- *args: Additional arguments to pass to the driver.
81
- **kwargs: Additional keyword arguments to pass to the driver.
82
-
83
- Yields:
84
- An iterator of BigQueryDriver instances.
85
- """
86
- conn = self.create_connection()
87
- yield self.driver_type(connection=conn)