sql-testing-library 0.9.0__tar.gz → 0.10.1__tar.gz
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.
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/CHANGELOG.md +12 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/PKG-INFO +71 -9
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/README.md +70 -8
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/pyproject.toml +1 -1
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/bigquery.py +74 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_exceptions.py +14 -3
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_sql_utils.py +9 -1
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/LICENSE +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/__init__.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/__init__.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/athena.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/base.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/presto.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/redshift.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/snowflake.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/trino.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_core.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_mock_table.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_pytest_plugin.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_sql_logger.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_types.py +0 -0
- {sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/py.typed +0 -0
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.10.1 (2025-06-15)
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- run unittests against different os/python versions (#100)
|
|
13
|
+
|
|
14
|
+
## 0.10.0 (2025-06-15)
|
|
15
|
+
|
|
16
|
+
### Feat
|
|
17
|
+
|
|
18
|
+
- **bigquery**: add support for map in bigquery (#99)
|
|
19
|
+
|
|
8
20
|
## 0.9.0 (2025-06-10)
|
|
9
21
|
|
|
10
22
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sql-testing-library
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: A powerful Python framework for unit testing SQL queries across BigQuery, Snowflake, Redshift, Athena, and Trino with mock data
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: sql,testing,unit-testing,mock-data,database-testing,bigquery,snowflake,redshift,athena,trino,data-engineering,etl-testing,sql-validation,query-testing
|
|
@@ -136,14 +136,13 @@ The library supports different data types across database engines. All checkmark
|
|
|
136
136
|
| **Integer Array** | `List[int]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
137
137
|
| **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
138
138
|
| **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
139
|
-
| **Map/
|
|
140
|
-
| **Struct/Record** | `
|
|
139
|
+
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
|
140
|
+
| **Struct/Record** | `dataclass` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
141
141
|
| **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
142
|
-
| **JSON Objects** | `JSON` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
143
142
|
|
|
144
143
|
### Database-Specific Notes
|
|
145
144
|
|
|
146
|
-
- **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals
|
|
145
|
+
- **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings
|
|
147
146
|
- **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax
|
|
148
147
|
- **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit
|
|
149
148
|
- **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays and maps
|
|
@@ -843,20 +842,83 @@ The adapter_type parameter will use the configuration from the corresponding sec
|
|
|
843
842
|
|
|
844
843
|
## Development Setup
|
|
845
844
|
|
|
845
|
+
### Quick Start with Make
|
|
846
|
+
|
|
847
|
+
The project includes a Makefile for common development tasks:
|
|
848
|
+
|
|
849
|
+
```bash
|
|
850
|
+
# Install all dependencies
|
|
851
|
+
make install
|
|
852
|
+
|
|
853
|
+
# Run unit tests
|
|
854
|
+
make test
|
|
855
|
+
|
|
856
|
+
# Run linting and type checking
|
|
857
|
+
make lint
|
|
858
|
+
|
|
859
|
+
# Format code
|
|
860
|
+
make format
|
|
861
|
+
|
|
862
|
+
# Run all checks (lint + format check + tests)
|
|
863
|
+
make check
|
|
864
|
+
|
|
865
|
+
# See all available commands
|
|
866
|
+
make help
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
### Available Make Commands
|
|
870
|
+
|
|
871
|
+
| Command | Description |
|
|
872
|
+
|---------|-------------|
|
|
873
|
+
| `make install` | Install all dependencies with poetry |
|
|
874
|
+
| `make test` | Run unit tests with coverage |
|
|
875
|
+
| `make test-unit` | Run unit tests (excludes integration tests) |
|
|
876
|
+
| `make test-integration` | Run integration tests (requires DB credentials) |
|
|
877
|
+
| `make test-all` | Run all tests (unit + integration) |
|
|
878
|
+
| `make test-tox` | Run tests across all Python versions (3.9-3.12) |
|
|
879
|
+
| `make lint` | Run ruff and mypy checks |
|
|
880
|
+
| `make format` | Format code with black and ruff |
|
|
881
|
+
| `make check` | Run all checks (lint + format + tests) |
|
|
882
|
+
| `make clean` | Remove build artifacts and cache files |
|
|
883
|
+
| `make build` | Build distribution packages |
|
|
884
|
+
| `make docs` | Build documentation |
|
|
885
|
+
|
|
886
|
+
### Testing Across Python Versions
|
|
887
|
+
|
|
888
|
+
The project supports Python 3.9-3.12. You can test across all versions using:
|
|
889
|
+
|
|
890
|
+
```bash
|
|
891
|
+
# Using tox (automatically tests all Python versions)
|
|
892
|
+
make test-tox
|
|
893
|
+
|
|
894
|
+
# Or directly with tox
|
|
895
|
+
tox
|
|
896
|
+
|
|
897
|
+
# Test specific Python version
|
|
898
|
+
tox -e py39 # Python 3.9
|
|
899
|
+
tox -e py310 # Python 3.10
|
|
900
|
+
tox -e py311 # Python 3.11
|
|
901
|
+
tox -e py312 # Python 3.12
|
|
902
|
+
```
|
|
903
|
+
|
|
846
904
|
### Code Quality
|
|
847
905
|
|
|
848
906
|
The project uses comprehensive tools to ensure code quality:
|
|
849
907
|
|
|
850
908
|
1. **Ruff** for linting and formatting
|
|
851
|
-
2. **
|
|
852
|
-
3. **
|
|
909
|
+
2. **Black** for code formatting
|
|
910
|
+
3. **Mypy** for static type checking
|
|
911
|
+
4. **Pre-commit hooks** for automated checks
|
|
853
912
|
|
|
854
913
|
To set up the development environment:
|
|
855
914
|
|
|
856
915
|
1. Install development dependencies:
|
|
857
916
|
```bash
|
|
858
|
-
#
|
|
859
|
-
|
|
917
|
+
# Using make
|
|
918
|
+
make install
|
|
919
|
+
|
|
920
|
+
# Or directly with poetry
|
|
921
|
+
poetry install --all-extras
|
|
860
922
|
```
|
|
861
923
|
|
|
862
924
|
2. Set up pre-commit hooks:
|
|
@@ -79,14 +79,13 @@ The library supports different data types across database engines. All checkmark
|
|
|
79
79
|
| **Integer Array** | `List[int]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
80
80
|
| **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
81
81
|
| **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
82
|
-
| **Map/
|
|
83
|
-
| **Struct/Record** | `
|
|
82
|
+
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
|
83
|
+
| **Struct/Record** | `dataclass` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
84
84
|
| **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
85
|
-
| **JSON Objects** | `JSON` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
86
85
|
|
|
87
86
|
### Database-Specific Notes
|
|
88
87
|
|
|
89
|
-
- **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals
|
|
88
|
+
- **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings
|
|
90
89
|
- **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax
|
|
91
90
|
- **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit
|
|
92
91
|
- **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays and maps
|
|
@@ -786,20 +785,83 @@ The adapter_type parameter will use the configuration from the corresponding sec
|
|
|
786
785
|
|
|
787
786
|
## Development Setup
|
|
788
787
|
|
|
788
|
+
### Quick Start with Make
|
|
789
|
+
|
|
790
|
+
The project includes a Makefile for common development tasks:
|
|
791
|
+
|
|
792
|
+
```bash
|
|
793
|
+
# Install all dependencies
|
|
794
|
+
make install
|
|
795
|
+
|
|
796
|
+
# Run unit tests
|
|
797
|
+
make test
|
|
798
|
+
|
|
799
|
+
# Run linting and type checking
|
|
800
|
+
make lint
|
|
801
|
+
|
|
802
|
+
# Format code
|
|
803
|
+
make format
|
|
804
|
+
|
|
805
|
+
# Run all checks (lint + format check + tests)
|
|
806
|
+
make check
|
|
807
|
+
|
|
808
|
+
# See all available commands
|
|
809
|
+
make help
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### Available Make Commands
|
|
813
|
+
|
|
814
|
+
| Command | Description |
|
|
815
|
+
|---------|-------------|
|
|
816
|
+
| `make install` | Install all dependencies with poetry |
|
|
817
|
+
| `make test` | Run unit tests with coverage |
|
|
818
|
+
| `make test-unit` | Run unit tests (excludes integration tests) |
|
|
819
|
+
| `make test-integration` | Run integration tests (requires DB credentials) |
|
|
820
|
+
| `make test-all` | Run all tests (unit + integration) |
|
|
821
|
+
| `make test-tox` | Run tests across all Python versions (3.9-3.12) |
|
|
822
|
+
| `make lint` | Run ruff and mypy checks |
|
|
823
|
+
| `make format` | Format code with black and ruff |
|
|
824
|
+
| `make check` | Run all checks (lint + format + tests) |
|
|
825
|
+
| `make clean` | Remove build artifacts and cache files |
|
|
826
|
+
| `make build` | Build distribution packages |
|
|
827
|
+
| `make docs` | Build documentation |
|
|
828
|
+
|
|
829
|
+
### Testing Across Python Versions
|
|
830
|
+
|
|
831
|
+
The project supports Python 3.9-3.12. You can test across all versions using:
|
|
832
|
+
|
|
833
|
+
```bash
|
|
834
|
+
# Using tox (automatically tests all Python versions)
|
|
835
|
+
make test-tox
|
|
836
|
+
|
|
837
|
+
# Or directly with tox
|
|
838
|
+
tox
|
|
839
|
+
|
|
840
|
+
# Test specific Python version
|
|
841
|
+
tox -e py39 # Python 3.9
|
|
842
|
+
tox -e py310 # Python 3.10
|
|
843
|
+
tox -e py311 # Python 3.11
|
|
844
|
+
tox -e py312 # Python 3.12
|
|
845
|
+
```
|
|
846
|
+
|
|
789
847
|
### Code Quality
|
|
790
848
|
|
|
791
849
|
The project uses comprehensive tools to ensure code quality:
|
|
792
850
|
|
|
793
851
|
1. **Ruff** for linting and formatting
|
|
794
|
-
2. **
|
|
795
|
-
3. **
|
|
852
|
+
2. **Black** for code formatting
|
|
853
|
+
3. **Mypy** for static type checking
|
|
854
|
+
4. **Pre-commit hooks** for automated checks
|
|
796
855
|
|
|
797
856
|
To set up the development environment:
|
|
798
857
|
|
|
799
858
|
1. Install development dependencies:
|
|
800
859
|
```bash
|
|
801
|
-
#
|
|
802
|
-
|
|
860
|
+
# Using make
|
|
861
|
+
make install
|
|
862
|
+
|
|
863
|
+
# Or directly with poetry
|
|
864
|
+
poetry install --all-extras
|
|
803
865
|
```
|
|
804
866
|
|
|
805
867
|
2. Set up pre-commit hooks:
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "sql-testing-library"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.10.1"
|
|
8
8
|
description = "A powerful Python framework for unit testing SQL queries across BigQuery, Snowflake, Redshift, Athena, and Trino with mock data"
|
|
9
9
|
authors = ["Gurmeet Saran <gurmeetx@gmail.com>", "Kushal Thakkar <kushal.thakkar@gmail.com>"]
|
|
10
10
|
maintainers = ["Gurmeet Saran <gurmeetx@gmail.com>", "Kushal Thakkar <kushal.thakkar@gmail.com>"]
|
|
@@ -30,6 +30,32 @@ class BigQueryTypeConverter(BaseTypeConverter):
|
|
|
30
30
|
|
|
31
31
|
def convert(self, value: Any, target_type: Type) -> Any:
|
|
32
32
|
"""Convert BigQuery result value to target type."""
|
|
33
|
+
# Handle None/NULL values first
|
|
34
|
+
if value is None:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
# Handle Optional types
|
|
38
|
+
if self.is_optional_type(target_type):
|
|
39
|
+
if value is None:
|
|
40
|
+
return None
|
|
41
|
+
target_type = self.get_optional_inner_type(target_type)
|
|
42
|
+
|
|
43
|
+
# Handle dict/map types from BigQuery STRING columns containing JSON
|
|
44
|
+
if hasattr(target_type, "__origin__") and target_type.__origin__ is dict:
|
|
45
|
+
# BigQuery returns JSON stored as strings, so we need to parse them
|
|
46
|
+
if isinstance(value, str):
|
|
47
|
+
import json
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
return json.loads(value)
|
|
51
|
+
except json.JSONDecodeError:
|
|
52
|
+
return {}
|
|
53
|
+
elif isinstance(value, dict):
|
|
54
|
+
# Already a dict (shouldn't happen with STRING columns, but handle it)
|
|
55
|
+
return value
|
|
56
|
+
else:
|
|
57
|
+
return {}
|
|
58
|
+
|
|
33
59
|
# BigQuery typically returns proper Python types, so use base converter
|
|
34
60
|
return super().convert(value, target_type)
|
|
35
61
|
|
|
@@ -82,6 +108,9 @@ class BigQueryAdapter(DatabaseAdapter):
|
|
|
82
108
|
# Insert data
|
|
83
109
|
df = mock_table.to_dataframe()
|
|
84
110
|
if not df.empty:
|
|
111
|
+
# Convert dict columns to JSON strings for BigQuery
|
|
112
|
+
df = self._prepare_dataframe_for_bigquery(df, mock_table)
|
|
113
|
+
|
|
85
114
|
job_config = bigquery.LoadJobConfig()
|
|
86
115
|
job = self.client.load_table_from_dataframe(df, table, job_config=job_config)
|
|
87
116
|
job.result() # Wait for job to complete
|
|
@@ -130,6 +159,9 @@ class BigQueryAdapter(DatabaseAdapter):
|
|
|
130
159
|
|
|
131
160
|
# Insert data if any
|
|
132
161
|
if not df.empty:
|
|
162
|
+
# Convert dict columns to JSON strings for BigQuery
|
|
163
|
+
df = self._prepare_dataframe_for_bigquery(df, mock_table)
|
|
164
|
+
|
|
133
165
|
job_config = bigquery.LoadJobConfig()
|
|
134
166
|
job = self.client.load_table_from_dataframe(df, table, job_config=job_config)
|
|
135
167
|
job.result()
|
|
@@ -188,9 +220,51 @@ class BigQueryAdapter(DatabaseAdapter):
|
|
|
188
220
|
|
|
189
221
|
# Create field with mode=REPEATED for arrays
|
|
190
222
|
schema.append(bigquery.SchemaField(col_name, element_bq_type, mode="REPEATED"))
|
|
223
|
+
# Handle Dict/Map types
|
|
224
|
+
elif hasattr(col_type, "__origin__") and col_type.__origin__ is dict:
|
|
225
|
+
# BigQuery stores JSON data as STRING type
|
|
226
|
+
schema.append(bigquery.SchemaField(col_name, bigquery.enums.SqlTypeNames.STRING))
|
|
191
227
|
else:
|
|
192
228
|
# Handle scalar types
|
|
193
229
|
bq_type = type_mapping.get(col_type, bigquery.enums.SqlTypeNames.STRING)
|
|
194
230
|
schema.append(bigquery.SchemaField(col_name, bq_type))
|
|
195
231
|
|
|
196
232
|
return schema
|
|
233
|
+
|
|
234
|
+
def _prepare_dataframe_for_bigquery(
|
|
235
|
+
self, df: "pd.DataFrame", mock_table: BaseMockTable
|
|
236
|
+
) -> "pd.DataFrame":
|
|
237
|
+
"""Prepare DataFrame for BigQuery by converting dict columns to JSON strings."""
|
|
238
|
+
import json
|
|
239
|
+
|
|
240
|
+
import pandas as pd
|
|
241
|
+
|
|
242
|
+
from .._sql_utils import DecimalEncoder
|
|
243
|
+
|
|
244
|
+
# Create a copy to avoid modifying the original
|
|
245
|
+
df_copy = df.copy()
|
|
246
|
+
column_types = mock_table.get_column_types()
|
|
247
|
+
|
|
248
|
+
for col_name, col_type in column_types.items():
|
|
249
|
+
# Handle Optional types
|
|
250
|
+
if hasattr(col_type, "__origin__") and col_type.__origin__ is Union:
|
|
251
|
+
# Extract the non-None type from Optional[T]
|
|
252
|
+
non_none_types = [arg for arg in get_args(col_type) if arg is not type(None)]
|
|
253
|
+
if non_none_types:
|
|
254
|
+
col_type = non_none_types[0]
|
|
255
|
+
|
|
256
|
+
# Check if this is a dict type
|
|
257
|
+
if hasattr(col_type, "__origin__") and col_type.__origin__ is dict:
|
|
258
|
+
# Convert dict values to JSON strings
|
|
259
|
+
def convert_dict_to_json(val):
|
|
260
|
+
if pd.isna(val) or val is None:
|
|
261
|
+
return None
|
|
262
|
+
elif isinstance(val, dict):
|
|
263
|
+
# Use DecimalEncoder to handle Decimal values in dicts
|
|
264
|
+
return json.dumps(val, cls=DecimalEncoder)
|
|
265
|
+
else:
|
|
266
|
+
return val
|
|
267
|
+
|
|
268
|
+
df_copy[col_name] = df_copy[col_name].apply(convert_dict_to_json)
|
|
269
|
+
|
|
270
|
+
return df_copy
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_exceptions.py
RENAMED
|
@@ -50,6 +50,17 @@ class TypeConversionError(SQLTestingError):
|
|
|
50
50
|
self.value = value
|
|
51
51
|
self.target_type = target_type
|
|
52
52
|
self.column_name = column_name
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
|
|
54
|
+
# Handle type name extraction for various type forms
|
|
55
|
+
try:
|
|
56
|
+
type_name = target_type.__name__
|
|
57
|
+
except AttributeError:
|
|
58
|
+
# For types like Optional, Union, etc that don't have __name__
|
|
59
|
+
type_name = str(target_type)
|
|
60
|
+
|
|
61
|
+
if column_name:
|
|
62
|
+
message = f"Cannot convert '{value}' to {type_name} for column '{column_name}'"
|
|
63
|
+
else:
|
|
64
|
+
message = f"Cannot convert '{value}' to {type_name}"
|
|
65
|
+
|
|
66
|
+
super().__init__(message)
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_sql_utils.py
RENAMED
|
@@ -167,6 +167,9 @@ def format_sql_value(value: Any, column_type: Type, dialect: str = "standard") -
|
|
|
167
167
|
elif dialect == "redshift":
|
|
168
168
|
# Redshift SUPER type handles NULL maps
|
|
169
169
|
return "NULL::SUPER"
|
|
170
|
+
elif dialect == "bigquery":
|
|
171
|
+
# BigQuery JSON type handles NULL maps
|
|
172
|
+
return "NULL"
|
|
170
173
|
else:
|
|
171
174
|
return "NULL"
|
|
172
175
|
|
|
@@ -289,9 +292,14 @@ def format_sql_value(value: Any, column_type: Type, dialect: str = "standard") -
|
|
|
289
292
|
# Redshift uses SUPER type with JSON-like syntax for maps
|
|
290
293
|
json_str = json.dumps(value, cls=DecimalEncoder)
|
|
291
294
|
return f"JSON_PARSE('{json_str}')"
|
|
295
|
+
elif dialect == "bigquery":
|
|
296
|
+
# BigQuery stores JSON as strings
|
|
297
|
+
json_str = json.dumps(value, cls=DecimalEncoder)
|
|
298
|
+
# Escape single quotes in JSON string for SQL
|
|
299
|
+
json_str = json_str.replace("'", "''")
|
|
300
|
+
return f"'{json_str}'"
|
|
292
301
|
else:
|
|
293
302
|
# Other databases don't have native map support yet
|
|
294
|
-
# Could potentially use JSON for BigQuery, Snowflake
|
|
295
303
|
raise NotImplementedError(f"Map type not yet supported for dialect: {dialect}")
|
|
296
304
|
|
|
297
305
|
# Handle string types
|
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/athena.py
RENAMED
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/base.py
RENAMED
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/presto.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_adapters/trino.py
RENAMED
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_mock_table.py
RENAMED
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_pytest_plugin.py
RENAMED
|
File without changes
|
{sql_testing_library-0.9.0 → sql_testing_library-0.10.1}/src/sql_testing_library/_sql_logger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|