sql-testing-library 0.12.0__tar.gz → 0.14.0__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.
Files changed (23) hide show
  1. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/CHANGELOG.md +23 -0
  2. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/PKG-INFO +88 -11
  3. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/README.md +87 -10
  4. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/pyproject.toml +2 -1
  5. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/base.py +16 -0
  6. sql_testing_library-0.14.0/src/sql_testing_library/_adapters/bigquery.py +479 -0
  7. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/presto.py +2 -5
  8. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/redshift.py +18 -25
  9. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/snowflake.py +49 -52
  10. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_core.py +204 -6
  11. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_pytest_plugin.py +25 -1
  12. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_sql_logger.py +45 -7
  13. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_sql_utils.py +86 -4
  14. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_types.py +23 -4
  15. sql_testing_library-0.12.0/src/sql_testing_library/_adapters/bigquery.py +0 -270
  16. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/LICENSE +0 -0
  17. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/__init__.py +0 -0
  18. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/__init__.py +0 -0
  19. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/athena.py +0 -0
  20. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_adapters/trino.py +0 -0
  21. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_exceptions.py +0 -0
  22. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/_mock_table.py +0 -0
  23. {sql_testing_library-0.12.0 → sql_testing_library-0.14.0}/src/sql_testing_library/py.typed +0 -0
@@ -5,6 +5,29 @@ 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.14.0 (2025-06-30)
9
+
10
+ ### Feat
11
+
12
+ - **bigquery**: add struct support with list fields (#109)
13
+ - **bigquery**: add struct support for big query (#108)
14
+ - add parallel table cleanup for improved performance (#107)
15
+ - add parallel table creation for physical tables mode (#106)
16
+
17
+ ### Fix
18
+
19
+ - **athena**: handle mixed format structs with lists and maps (#111)
20
+
21
+ ## 0.13.0 (2025-06-27)
22
+
23
+ ### Feat
24
+
25
+ - add pytest-xdist support for parallel test execution (#105)
26
+
27
+ ### Fix
28
+
29
+ - **snowflake**: fix issue related to physical view for snowflake (#104)
30
+
8
31
  ## 0.12.0 (2025-06-25)
9
32
 
10
33
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sql-testing-library
3
- Version: 0.12.0
3
+ Version: 0.14.0
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
@@ -137,12 +137,12 @@ The library supports different data types across database engines. All checkmark
137
137
  | **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
138
138
  | **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
139
139
  | **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ✅ |
140
- | **Struct/Record** | `dataclass` | | ✅ | ❌ | ✅ | ❌ |
140
+ | **Struct/Record** | `dataclass` | | ✅ | ❌ | ✅ | ❌ |
141
141
  | **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
142
142
 
143
143
  ### Database-Specific Notes
144
144
 
145
- - **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings; struct types not yet supported
145
+ - **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings; struct types supported using `STRUCT` syntax with named fields (dataclasses and Pydantic models)
146
146
  - **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax; supports struct types using `ROW` with named fields (dataclasses and Pydantic models)
147
147
  - **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit; struct types not yet supported
148
148
  - **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays, maps, and struct types using `ROW` with named fields (dataclasses and Pydantic models)
@@ -155,7 +155,7 @@ The library supports two execution modes for mock data injection. **CTE Mode is
155
155
  | Execution Mode | Description | BigQuery | Athena | Redshift | Trino | Snowflake |
156
156
  |----------------|-------------|----------|--------|----------|-------|-----------|
157
157
  | **CTE Mode** | Mock data injected as Common Table Expressions | ✅ | ✅ | ✅ | ✅ | ✅ |
158
- | **Physical Tables** | Mock data created as temporary tables | ✅ | ✅ | ✅ | ✅ | ⚠️* |
158
+ | **Physical Tables** | Mock data created as temporary tables | ✅ | ✅ | ✅ | ✅ | |
159
159
 
160
160
  ### Execution Mode Details
161
161
 
@@ -301,12 +301,84 @@ def test_physical_tables():
301
301
  query="SELECT * FROM table",
302
302
  use_physical_tables=True # Force physical tables
303
303
  )
304
+
305
+ # Physical Tables with Custom Parallel Settings
306
+ @sql_test(
307
+ mock_tables=[...],
308
+ result_class=ResultClass,
309
+ use_physical_tables=True,
310
+ max_workers=4 # Customize parallel execution
311
+ )
312
+ def test_with_custom_parallelism():
313
+ return TestCase(query="SELECT * FROM table")
304
314
  ```
305
315
 
306
316
  **Notes:**
307
317
  - **CTE Mode**: Default mode, works with all database engines, suitable for most use cases
308
318
  - **Physical Tables**: Used automatically when CTE queries exceed database size limits or when explicitly requested
309
- - **⚠️ Snowflake Physical Tables**: Currently disabled in test environment due to temporary table visibility limitations. CTE mode works perfectly for all use cases.
319
+ - **Parallel Table Creation**: When using physical tables with multiple mock tables, they are created in parallel by default for better performance
320
+ - **Snowflake**: Full support for both CTE and physical table modes
321
+
322
+ ### Performance Optimization: Parallel Table Operations
323
+
324
+ When using `use_physical_tables=True` with multiple mock tables, the library can create and cleanup tables in parallel for better performance.
325
+
326
+ #### Parallel Table Creation
327
+
328
+ **Default Behavior:**
329
+ - Parallel creation is **enabled by default** when using physical tables
330
+ - Smart worker allocation based on table count:
331
+ - 1-2 tables: Same number of workers as tables
332
+ - 3-5 tables: 3 workers
333
+ - 6-10 tables: 5 workers
334
+ - 11+ tables: 8 workers (capped)
335
+
336
+ **Customization:**
337
+ ```python
338
+ # Disable parallel creation
339
+ @sql_test(use_physical_tables=True, parallel_table_creation=False)
340
+
341
+ # Custom worker count
342
+ @sql_test(use_physical_tables=True, max_workers=2)
343
+
344
+ # In SQLTestCase directly
345
+ TestCase(
346
+ query="...",
347
+ use_physical_tables=True,
348
+ parallel_table_creation=True, # Default
349
+ max_workers=4 # Custom worker limit
350
+ )
351
+ ```
352
+
353
+ #### Parallel Table Cleanup
354
+
355
+ **Default Behavior:**
356
+ - Parallel cleanup is **enabled by default** when using physical tables
357
+ - Uses the same smart worker allocation as table creation
358
+ - Cleanup errors are logged as warnings (best-effort cleanup)
359
+
360
+ **Customization:**
361
+ ```python
362
+ # Disable parallel cleanup
363
+ @sql_test(use_physical_tables=True, parallel_table_cleanup=False)
364
+
365
+ # Custom worker count for both creation and cleanup
366
+ @sql_test(use_physical_tables=True, max_workers=2)
367
+
368
+ # In SQLTestCase directly
369
+ TestCase(
370
+ query="...",
371
+ use_physical_tables=True,
372
+ parallel_table_creation=True, # Default
373
+ parallel_table_cleanup=True, # Default
374
+ max_workers=4 # Custom worker limit for both operations
375
+ )
376
+ ```
377
+
378
+ **Performance Benefits:**
379
+ - Both table creation and cleanup operations are parallelized when multiple tables are involved
380
+ - Significantly reduces test execution time for tests with many mock tables
381
+ - Particularly beneficial for cloud databases where network latency is a factor
310
382
 
311
383
  ## Installation
312
384
 
@@ -572,9 +644,9 @@ def test_pattern_3():
572
644
  )
573
645
  ```
574
646
 
575
- ### Working with Struct Types (Athena and Trino)
647
+ ### Working with Struct Types (Athena, Trino, and BigQuery)
576
648
 
577
- The library supports struct/record types using Python dataclasses or Pydantic models for Athena and Trino:
649
+ The library supports struct/record types using Python dataclasses or Pydantic models for Athena, Trino, and BigQuery:
578
650
 
579
651
  ```python
580
652
  from dataclasses import dataclass
@@ -621,7 +693,7 @@ class EmployeesMockTable(BaseMockTable):
621
693
 
622
694
  # Test with struct types
623
695
  @sql_test(
624
- adapter_type="athena", # or "trino"
696
+ adapter_type="athena", # or "trino" or "bigquery"
625
697
  mock_tables=[
626
698
  EmployeesMockTable([
627
699
  Employee(
@@ -667,7 +739,7 @@ def test_struct_with_dot_notation():
667
739
 
668
740
  # You can also query entire structs
669
741
  @sql_test(
670
- adapter_type="trino",
742
+ adapter_type="trino", # or "athena" or "bigquery"
671
743
  mock_tables=[EmployeesMockTable([...])],
672
744
  result_class=dict # Returns full struct as dict
673
745
  )
@@ -1172,8 +1244,13 @@ For detailed usage and configuration options, see the example files included.
1172
1244
 
1173
1245
  The library has a few known limitations that are planned to be addressed in future updates:
1174
1246
 
1175
- ### Snowflake Support
1176
- - Physical table tests for Snowflake are currently skipped due to complex mocking requirements
1247
+ ### Struct Type Support
1248
+ - **Redshift**: Struct types are not supported due to lack of native struct/record types (uses SUPER type for JSON)
1249
+ - **Snowflake**: Struct types are not supported due to lack of native struct/record types (uses VARIANT type for JSON)
1250
+
1251
+
1252
+ ### Database-Specific Limitations
1253
+ - **BigQuery**: Does not support nested arrays (arrays of arrays). This is a BigQuery database limitation, not a library limitation. (See TODO in `test_struct_types_integration.py:test_nested_lists`)
1177
1254
 
1178
1255
  ### General Improvements
1179
1256
  - Add support for more SQL dialects
@@ -80,12 +80,12 @@ The library supports different data types across database engines. All checkmark
80
80
  | **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
81
81
  | **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
82
82
  | **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ✅ |
83
- | **Struct/Record** | `dataclass` | | ✅ | ❌ | ✅ | ❌ |
83
+ | **Struct/Record** | `dataclass` | | ✅ | ❌ | ✅ | ❌ |
84
84
  | **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
85
85
 
86
86
  ### Database-Specific Notes
87
87
 
88
- - **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings; struct types not yet supported
88
+ - **BigQuery**: NULL arrays become empty arrays `[]`; uses scientific notation for large decimals; dict/map types stored as JSON strings; struct types supported using `STRUCT` syntax with named fields (dataclasses and Pydantic models)
89
89
  - **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax; supports struct types using `ROW` with named fields (dataclasses and Pydantic models)
90
90
  - **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit; struct types not yet supported
91
91
  - **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays, maps, and struct types using `ROW` with named fields (dataclasses and Pydantic models)
@@ -98,7 +98,7 @@ The library supports two execution modes for mock data injection. **CTE Mode is
98
98
  | Execution Mode | Description | BigQuery | Athena | Redshift | Trino | Snowflake |
99
99
  |----------------|-------------|----------|--------|----------|-------|-----------|
100
100
  | **CTE Mode** | Mock data injected as Common Table Expressions | ✅ | ✅ | ✅ | ✅ | ✅ |
101
- | **Physical Tables** | Mock data created as temporary tables | ✅ | ✅ | ✅ | ✅ | ⚠️* |
101
+ | **Physical Tables** | Mock data created as temporary tables | ✅ | ✅ | ✅ | ✅ | |
102
102
 
103
103
  ### Execution Mode Details
104
104
 
@@ -244,12 +244,84 @@ def test_physical_tables():
244
244
  query="SELECT * FROM table",
245
245
  use_physical_tables=True # Force physical tables
246
246
  )
247
+
248
+ # Physical Tables with Custom Parallel Settings
249
+ @sql_test(
250
+ mock_tables=[...],
251
+ result_class=ResultClass,
252
+ use_physical_tables=True,
253
+ max_workers=4 # Customize parallel execution
254
+ )
255
+ def test_with_custom_parallelism():
256
+ return TestCase(query="SELECT * FROM table")
247
257
  ```
248
258
 
249
259
  **Notes:**
250
260
  - **CTE Mode**: Default mode, works with all database engines, suitable for most use cases
251
261
  - **Physical Tables**: Used automatically when CTE queries exceed database size limits or when explicitly requested
252
- - **⚠️ Snowflake Physical Tables**: Currently disabled in test environment due to temporary table visibility limitations. CTE mode works perfectly for all use cases.
262
+ - **Parallel Table Creation**: When using physical tables with multiple mock tables, they are created in parallel by default for better performance
263
+ - **Snowflake**: Full support for both CTE and physical table modes
264
+
265
+ ### Performance Optimization: Parallel Table Operations
266
+
267
+ When using `use_physical_tables=True` with multiple mock tables, the library can create and cleanup tables in parallel for better performance.
268
+
269
+ #### Parallel Table Creation
270
+
271
+ **Default Behavior:**
272
+ - Parallel creation is **enabled by default** when using physical tables
273
+ - Smart worker allocation based on table count:
274
+ - 1-2 tables: Same number of workers as tables
275
+ - 3-5 tables: 3 workers
276
+ - 6-10 tables: 5 workers
277
+ - 11+ tables: 8 workers (capped)
278
+
279
+ **Customization:**
280
+ ```python
281
+ # Disable parallel creation
282
+ @sql_test(use_physical_tables=True, parallel_table_creation=False)
283
+
284
+ # Custom worker count
285
+ @sql_test(use_physical_tables=True, max_workers=2)
286
+
287
+ # In SQLTestCase directly
288
+ TestCase(
289
+ query="...",
290
+ use_physical_tables=True,
291
+ parallel_table_creation=True, # Default
292
+ max_workers=4 # Custom worker limit
293
+ )
294
+ ```
295
+
296
+ #### Parallel Table Cleanup
297
+
298
+ **Default Behavior:**
299
+ - Parallel cleanup is **enabled by default** when using physical tables
300
+ - Uses the same smart worker allocation as table creation
301
+ - Cleanup errors are logged as warnings (best-effort cleanup)
302
+
303
+ **Customization:**
304
+ ```python
305
+ # Disable parallel cleanup
306
+ @sql_test(use_physical_tables=True, parallel_table_cleanup=False)
307
+
308
+ # Custom worker count for both creation and cleanup
309
+ @sql_test(use_physical_tables=True, max_workers=2)
310
+
311
+ # In SQLTestCase directly
312
+ TestCase(
313
+ query="...",
314
+ use_physical_tables=True,
315
+ parallel_table_creation=True, # Default
316
+ parallel_table_cleanup=True, # Default
317
+ max_workers=4 # Custom worker limit for both operations
318
+ )
319
+ ```
320
+
321
+ **Performance Benefits:**
322
+ - Both table creation and cleanup operations are parallelized when multiple tables are involved
323
+ - Significantly reduces test execution time for tests with many mock tables
324
+ - Particularly beneficial for cloud databases where network latency is a factor
253
325
 
254
326
  ## Installation
255
327
 
@@ -515,9 +587,9 @@ def test_pattern_3():
515
587
  )
516
588
  ```
517
589
 
518
- ### Working with Struct Types (Athena and Trino)
590
+ ### Working with Struct Types (Athena, Trino, and BigQuery)
519
591
 
520
- The library supports struct/record types using Python dataclasses or Pydantic models for Athena and Trino:
592
+ The library supports struct/record types using Python dataclasses or Pydantic models for Athena, Trino, and BigQuery:
521
593
 
522
594
  ```python
523
595
  from dataclasses import dataclass
@@ -564,7 +636,7 @@ class EmployeesMockTable(BaseMockTable):
564
636
 
565
637
  # Test with struct types
566
638
  @sql_test(
567
- adapter_type="athena", # or "trino"
639
+ adapter_type="athena", # or "trino" or "bigquery"
568
640
  mock_tables=[
569
641
  EmployeesMockTable([
570
642
  Employee(
@@ -610,7 +682,7 @@ def test_struct_with_dot_notation():
610
682
 
611
683
  # You can also query entire structs
612
684
  @sql_test(
613
- adapter_type="trino",
685
+ adapter_type="trino", # or "athena" or "bigquery"
614
686
  mock_tables=[EmployeesMockTable([...])],
615
687
  result_class=dict # Returns full struct as dict
616
688
  )
@@ -1115,8 +1187,13 @@ For detailed usage and configuration options, see the example files included.
1115
1187
 
1116
1188
  The library has a few known limitations that are planned to be addressed in future updates:
1117
1189
 
1118
- ### Snowflake Support
1119
- - Physical table tests for Snowflake are currently skipped due to complex mocking requirements
1190
+ ### Struct Type Support
1191
+ - **Redshift**: Struct types are not supported due to lack of native struct/record types (uses SUPER type for JSON)
1192
+ - **Snowflake**: Struct types are not supported due to lack of native struct/record types (uses VARIANT type for JSON)
1193
+
1194
+
1195
+ ### Database-Specific Limitations
1196
+ - **BigQuery**: Does not support nested arrays (arrays of arrays). This is a BigQuery database limitation, not a library limitation. (See TODO in `test_struct_types_integration.py:test_nested_lists`)
1120
1197
 
1121
1198
  ### General Improvements
1122
1199
  - Add support for more SQL dialects
@@ -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.12.0"
7
+ version = "0.14.0"
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>"]
@@ -104,6 +104,7 @@ pytest = ">=7.0.0"
104
104
  pytest-asyncio = ">=0.21.0"
105
105
  pytest-mock = ">=3.10.0"
106
106
  pytest-cov = ">=4.1.0"
107
+ pytest-xdist = ">=3.0.0"
107
108
  pytest-rerunfailures = ">=12.0.0"
108
109
  black = ">=22.0.0"
109
110
  flake8 = ">=4.0.0"
@@ -1,5 +1,7 @@
1
1
  """Base database adapter interface."""
2
2
 
3
+ import time
4
+ import uuid
3
5
  from abc import ABC, abstractmethod
4
6
  from typing import TYPE_CHECKING, Any, List, Optional, Tuple
5
7
 
@@ -56,3 +58,17 @@ class DatabaseAdapter(ABC):
56
58
  def get_query_size_limit(self) -> Optional[int]:
57
59
  """Return query size limit in bytes, or None if no limit."""
58
60
  return None
61
+
62
+ def get_temp_table_name(self, mock_table: BaseMockTable, prefix: str = "temp") -> str:
63
+ """Generate a unique temporary table name.
64
+
65
+ Args:
66
+ mock_table: The mock table to generate a name for
67
+ prefix: The prefix to use (default "temp", Snowflake uses "TEMP")
68
+
69
+ Returns:
70
+ A unique table name with timestamp and UUID
71
+ """
72
+ timestamp = int(time.time() * 1000)
73
+ unique_id = str(uuid.uuid4()).replace("-", "")[:8]
74
+ return f"{prefix}_{mock_table.get_table_name()}_{timestamp}_{unique_id}"