david8-duckdb 0.2.0b1__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.
- david8_duckdb-0.2.0b1/PKG-INFO +29 -0
- david8_duckdb-0.2.0b1/README.md +5 -0
- david8_duckdb-0.2.0b1/david8_duckdb/__init__.py +10 -0
- david8_duckdb-0.2.0b1/david8_duckdb/core/__init__.py +0 -0
- david8_duckdb-0.2.0b1/david8_duckdb/core/copy_to_query.py +29 -0
- david8_duckdb-0.2.0b1/david8_duckdb/core/query_builder.py +15 -0
- david8_duckdb-0.2.0b1/david8_duckdb/core/select_query.py +50 -0
- david8_duckdb-0.2.0b1/david8_duckdb/protocols/__init__.py +0 -0
- david8_duckdb-0.2.0b1/david8_duckdb/protocols/query_builder.py +19 -0
- david8_duckdb-0.2.0b1/david8_duckdb/protocols/sql.py +38 -0
- david8_duckdb-0.2.0b1/david8_duckdb.egg-info/PKG-INFO +29 -0
- david8_duckdb-0.2.0b1/david8_duckdb.egg-info/SOURCES.txt +17 -0
- david8_duckdb-0.2.0b1/david8_duckdb.egg-info/dependency_links.txt +1 -0
- david8_duckdb-0.2.0b1/david8_duckdb.egg-info/requires.txt +1 -0
- david8_duckdb-0.2.0b1/david8_duckdb.egg-info/top_level.txt +1 -0
- david8_duckdb-0.2.0b1/pyproject.toml +83 -0
- david8_duckdb-0.2.0b1/setup.cfg +4 -0
- david8_duckdb-0.2.0b1/tests/test_copy_to.py +35 -0
- david8_duckdb-0.2.0b1/tests/test_select.py +93 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: david8_duckdb
|
|
3
|
+
Version: 0.2.0b1
|
|
4
|
+
Summary: SQL query builder. david8 duckdb dielect
|
|
5
|
+
Author-email: Danila Ganchar <danila.ganchar@gmail.com>
|
|
6
|
+
Maintainer-email: Danila Ganchar <danila.ganchar@gmail.com>
|
|
7
|
+
Project-URL: Homepage, https://github.com/d-ganchar/david8_duckdb
|
|
8
|
+
Project-URL: Changelog, https://github.com/d-ganchar/david8_duckdb/releases
|
|
9
|
+
Project-URL: Issues, https://github.com/d-ganchar/david8_duckdb/issues
|
|
10
|
+
Project-URL: CI, https://github.com/d-ganchar/david8_duckdb/actions
|
|
11
|
+
Project-URL: Documentation, https://github.com/d-ganchar/david8_duckdb/wiki
|
|
12
|
+
Project-URL: Source, https://github.com/d-ganchar/david8_duckdb
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: <3.14,>=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: david8<2.0.0b1,>=1.0.0b1
|
|
24
|
+
|
|
25
|
+
# david8_duckdb
|
|
26
|
+
|
|
27
|
+
`david8_duckdb` is [DuckDb](https://duckdb.org/) dialect for [david8](https://github.com/d-ganchar/david8)
|
|
28
|
+
|
|
29
|
+
See [Wiki](https://github.com/d-ganchar/david8_duckdb/wiki)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from david8.core.base_dialect import BaseDialect as _BaseDialect
|
|
2
|
+
from david8.param_styles import QMarkParamStyle
|
|
3
|
+
|
|
4
|
+
from .core.query_builder import DuckDbQueryBuilder as _QueryBuilder
|
|
5
|
+
from .protocols.query_builder import QueryBuilderProtocol
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_qb(is_quote_mode: bool = False) -> QueryBuilderProtocol:
|
|
9
|
+
dialect = _BaseDialect(QMarkParamStyle(), is_quote_mode)
|
|
10
|
+
return _QueryBuilder(dialect)
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
|
|
3
|
+
from david8.core.base_query import BaseQuery
|
|
4
|
+
from david8.protocols.dialect import DialectProtocol
|
|
5
|
+
|
|
6
|
+
from david8_duckdb.protocols.sql import SelectProtocol
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclasses.dataclass(slots=True)
|
|
10
|
+
class CopyToQuery(BaseQuery):
|
|
11
|
+
source: str | SelectProtocol
|
|
12
|
+
target: str
|
|
13
|
+
copy_options: dict = None
|
|
14
|
+
|
|
15
|
+
def _render_sql(self, dialect: DialectProtocol) -> str:
|
|
16
|
+
source = f'({self.source.get_sql(dialect)})' if isinstance(self.source, SelectProtocol) else self.source
|
|
17
|
+
return f"COPY {source} TO '{self.target}'"
|
|
18
|
+
|
|
19
|
+
def _render_sql_postfix(self, dialect: DialectProtocol) -> str:
|
|
20
|
+
if not self.copy_options:
|
|
21
|
+
return ''
|
|
22
|
+
|
|
23
|
+
option_items = []
|
|
24
|
+
for key, value in self.copy_options.items():
|
|
25
|
+
if value is not None:
|
|
26
|
+
fixed_value = str(value).lower() if isinstance(value, bool) else value
|
|
27
|
+
option_items.append(f'{key} {fixed_value}')
|
|
28
|
+
|
|
29
|
+
return f' ({", ".join(option_items)})'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from david8.core.base_query_builder import BaseQueryBuilder as _BaseQueryBuilder
|
|
2
|
+
from david8.protocols.sql import AliasedProtocol, ExprProtocol, FunctionProtocol, QueryProtocol
|
|
3
|
+
|
|
4
|
+
from ..protocols.query_builder import QueryBuilderProtocol
|
|
5
|
+
from ..protocols.sql import SelectProtocol
|
|
6
|
+
from .copy_to_query import CopyToQuery
|
|
7
|
+
from .select_query import DuckDbSelect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DuckDbQueryBuilder(QueryBuilderProtocol, _BaseQueryBuilder):
|
|
11
|
+
def select(self, *args: str | AliasedProtocol | ExprProtocol | FunctionProtocol) -> SelectProtocol:
|
|
12
|
+
return DuckDbSelect(select_columns=args, dialect=self._dialect)
|
|
13
|
+
|
|
14
|
+
def copy_to(self, source: str | SelectProtocol, target: str, copy_options: dict = None) -> QueryProtocol:
|
|
15
|
+
return CopyToQuery(dialect=self._dialect, source=source, target=target, copy_options=copy_options)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
|
|
3
|
+
from david8.core.base_dql import BaseSelect as _BaseSelect
|
|
4
|
+
from david8.protocols.dialect import DialectProtocol
|
|
5
|
+
|
|
6
|
+
from ..protocols.sql import SelectProtocol
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclasses.dataclass(slots=True)
|
|
10
|
+
class DuckDbSelect(_BaseSelect, SelectProtocol):
|
|
11
|
+
from_files: tuple[str, tuple[str, ...]] = dataclasses.field(default_factory=tuple)
|
|
12
|
+
|
|
13
|
+
def from_csv(self, *file_names: str) -> 'SelectProtocol':
|
|
14
|
+
self.from_files = ('read_csv', file_names)
|
|
15
|
+
return self
|
|
16
|
+
|
|
17
|
+
def from_json(self, *file_names: str) -> 'SelectProtocol':
|
|
18
|
+
self.from_files = ('read_json', file_names)
|
|
19
|
+
return self
|
|
20
|
+
|
|
21
|
+
def from_json_objects(self, *file_names: str) -> 'SelectProtocol':
|
|
22
|
+
self.from_files = ('read_json_objects', file_names)
|
|
23
|
+
return self
|
|
24
|
+
|
|
25
|
+
def from_ndjson_objects(self, *file_names: str) -> 'SelectProtocol':
|
|
26
|
+
self.from_files = ('read_ndjson_objects', file_names)
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
def from_json_objects_auto(self, *file_names: str) -> 'SelectProtocol':
|
|
30
|
+
self.from_files = ('read_json_objects_auto', file_names)
|
|
31
|
+
return self
|
|
32
|
+
|
|
33
|
+
def from_parquet(self, *file_names: str) -> 'SelectProtocol':
|
|
34
|
+
self.from_files = ('read_parquet', file_names)
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def from_xlsx(self, file_name: str) -> 'SelectProtocol':
|
|
38
|
+
self.from_files = ('read_xlsx', (file_name,))
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
def _from_to_sql(self, dialect: DialectProtocol) -> str:
|
|
42
|
+
if not self.from_files:
|
|
43
|
+
return _BaseSelect._from_to_sql(self, dialect)
|
|
44
|
+
|
|
45
|
+
if len(self.from_files[1]) > 1:
|
|
46
|
+
files = str(list(self.from_files[1]))
|
|
47
|
+
else:
|
|
48
|
+
files = f"'{self.from_files[1][0]}'"
|
|
49
|
+
|
|
50
|
+
return f' FROM {self.from_files[0]}({files})'
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from david8.protocols.query_builder import QueryBuilderProtocol as _QueryBuilderProtocol
|
|
2
|
+
from david8.protocols.sql import AliasedProtocol, ExprProtocol, FunctionProtocol, QueryProtocol
|
|
3
|
+
|
|
4
|
+
from ..protocols.sql import SelectProtocol
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class QueryBuilderProtocol(_QueryBuilderProtocol):
|
|
8
|
+
def select(self, *args: str | AliasedProtocol | ExprProtocol | FunctionProtocol) -> SelectProtocol:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
def copy_to(self, source: str | SelectProtocol, target: str, copy_options: dict = None) -> QueryProtocol:
|
|
12
|
+
"""
|
|
13
|
+
:param source: query or table
|
|
14
|
+
:param target: file name
|
|
15
|
+
:param copy_options: https://duckdb.org/docs/stable/sql/statements/copy#copy--to-options
|
|
16
|
+
|
|
17
|
+
example:
|
|
18
|
+
qb.copy_to('events', 'events.parquet', {'FORMAT': 'parquet', 'DELIMITER': "','", 'APPEND': True})
|
|
19
|
+
"""
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from david8.protocols.sql import SelectProtocol as _SelectProtocol
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SelectProtocol(_SelectProtocol):
|
|
5
|
+
def from_csv(self, *file_names: str) -> 'SelectProtocol':
|
|
6
|
+
"""
|
|
7
|
+
https://duckdb.org/docs/stable/data/csv/reading_faulty_csv_files
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def from_json(self, *file_names: str) -> 'SelectProtocol':
|
|
11
|
+
"""
|
|
12
|
+
https://duckdb.org/docs/stable/data/json/loading_json#the-read_json-function
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def from_json_objects(self, *file_names: str) -> 'SelectProtocol':
|
|
16
|
+
"""
|
|
17
|
+
https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def from_ndjson_objects(self, *file_names: str) -> 'SelectProtocol':
|
|
21
|
+
"""
|
|
22
|
+
https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def from_json_objects_auto(self, *file_names: str) -> 'SelectProtocol':
|
|
26
|
+
"""
|
|
27
|
+
https://duckdb.org/docs/stable/data/json/loading_json#functions-for-reading-json-objects
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def from_parquet(self, *file_names: str) -> 'SelectProtocol':
|
|
31
|
+
"""
|
|
32
|
+
read_parquet(): https://duckdb.org/docs/stable/data/parquet/overview
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def from_xlsx(self, file_name: str) -> 'SelectProtocol':
|
|
36
|
+
"""
|
|
37
|
+
read_xlsx(): https://duckdb.org/docs/stable/core_extensions/excel
|
|
38
|
+
"""
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: david8_duckdb
|
|
3
|
+
Version: 0.2.0b1
|
|
4
|
+
Summary: SQL query builder. david8 duckdb dielect
|
|
5
|
+
Author-email: Danila Ganchar <danila.ganchar@gmail.com>
|
|
6
|
+
Maintainer-email: Danila Ganchar <danila.ganchar@gmail.com>
|
|
7
|
+
Project-URL: Homepage, https://github.com/d-ganchar/david8_duckdb
|
|
8
|
+
Project-URL: Changelog, https://github.com/d-ganchar/david8_duckdb/releases
|
|
9
|
+
Project-URL: Issues, https://github.com/d-ganchar/david8_duckdb/issues
|
|
10
|
+
Project-URL: CI, https://github.com/d-ganchar/david8_duckdb/actions
|
|
11
|
+
Project-URL: Documentation, https://github.com/d-ganchar/david8_duckdb/wiki
|
|
12
|
+
Project-URL: Source, https://github.com/d-ganchar/david8_duckdb
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: <3.14,>=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: david8<2.0.0b1,>=1.0.0b1
|
|
24
|
+
|
|
25
|
+
# david8_duckdb
|
|
26
|
+
|
|
27
|
+
`david8_duckdb` is [DuckDb](https://duckdb.org/) dialect for [david8](https://github.com/d-ganchar/david8)
|
|
28
|
+
|
|
29
|
+
See [Wiki](https://github.com/d-ganchar/david8_duckdb/wiki)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
david8_duckdb/__init__.py
|
|
4
|
+
david8_duckdb.egg-info/PKG-INFO
|
|
5
|
+
david8_duckdb.egg-info/SOURCES.txt
|
|
6
|
+
david8_duckdb.egg-info/dependency_links.txt
|
|
7
|
+
david8_duckdb.egg-info/requires.txt
|
|
8
|
+
david8_duckdb.egg-info/top_level.txt
|
|
9
|
+
david8_duckdb/core/__init__.py
|
|
10
|
+
david8_duckdb/core/copy_to_query.py
|
|
11
|
+
david8_duckdb/core/query_builder.py
|
|
12
|
+
david8_duckdb/core/select_query.py
|
|
13
|
+
david8_duckdb/protocols/__init__.py
|
|
14
|
+
david8_duckdb/protocols/query_builder.py
|
|
15
|
+
david8_duckdb/protocols/sql.py
|
|
16
|
+
tests/test_copy_to.py
|
|
17
|
+
tests/test_select.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
david8<2.0.0b1,>=1.0.0b1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
david8_duckdb
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "david8_duckdb"
|
|
3
|
+
version = "0.2.0b1"
|
|
4
|
+
description = "SQL query builder. david8 duckdb dielect"
|
|
5
|
+
authors = [{name = "Danila Ganchar", email = "danila.ganchar@gmail.com"}]
|
|
6
|
+
maintainers = [{name = "Danila Ganchar", email = "danila.ganchar@gmail.com"}]
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.11, < 3.14"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"david8>=1.0.0b1,<2.0.0b1"
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Topic :: Software Development :: Libraries",
|
|
18
|
+
"Topic :: Database",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/d-ganchar/david8_duckdb"
|
|
28
|
+
Changelog = "https://github.com/d-ganchar/david8_duckdb/releases"
|
|
29
|
+
Issues = "https://github.com/d-ganchar/david8_duckdb/issues"
|
|
30
|
+
CI = "https://github.com/d-ganchar/david8_duckdb/actions"
|
|
31
|
+
Documentation = "https://github.com/d-ganchar/david8_duckdb/wiki"
|
|
32
|
+
Source = "https://github.com/d-ganchar/david8_duckdb"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["setuptools>=77.0.0"]
|
|
37
|
+
build-backend = "setuptools.build_meta"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages]
|
|
41
|
+
find = { include = ["david8_duckdb", "david8_duckdb.*"] }
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
[dependency-groups]
|
|
45
|
+
dev = [
|
|
46
|
+
"ruff",
|
|
47
|
+
"parameterized",
|
|
48
|
+
"pytest",
|
|
49
|
+
"pytest-cov>=7.0.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[lint.select]
|
|
53
|
+
|
|
54
|
+
[lint.isort]
|
|
55
|
+
known-third-party = ["pytest"]
|
|
56
|
+
lines-after-imports = 2
|
|
57
|
+
lines-between-types = 1
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
[tool.ruff]
|
|
61
|
+
line-length = 120
|
|
62
|
+
exclude = [
|
|
63
|
+
".bzr",
|
|
64
|
+
".direnv",
|
|
65
|
+
".eggs",
|
|
66
|
+
"**/.git",
|
|
67
|
+
"__pycache__",
|
|
68
|
+
"tests/fixtures/",
|
|
69
|
+
"benchmarks/"
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = ["E", "F", "I", "UP", "N", "B", "W"]
|
|
74
|
+
|
|
75
|
+
[tool.pytest.ini_options]
|
|
76
|
+
testpaths = [
|
|
77
|
+
"tests",
|
|
78
|
+
"--color=yes",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
addopts = [
|
|
82
|
+
|
|
83
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from david8.protocols.sql import QueryProtocol
|
|
2
|
+
from parameterized import parameterized
|
|
3
|
+
|
|
4
|
+
from tests.base_test import BaseTest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestCopyTo(BaseTest):
|
|
8
|
+
@parameterized.expand([
|
|
9
|
+
(
|
|
10
|
+
BaseTest.qb.copy_to('events', 'events.csv'),
|
|
11
|
+
"COPY events TO 'events.csv'",
|
|
12
|
+
),
|
|
13
|
+
(
|
|
14
|
+
BaseTest.qb.copy_to('events', 'events.csv', {'DELIMITER': "','", 'APPEND': True}),
|
|
15
|
+
"COPY events TO 'events.csv' (DELIMITER ',', APPEND true)",
|
|
16
|
+
),
|
|
17
|
+
# query
|
|
18
|
+
(
|
|
19
|
+
BaseTest.qb.copy_to(
|
|
20
|
+
BaseTest.qb.select('name', 'value').from_table('events'),
|
|
21
|
+
'events.csv'
|
|
22
|
+
),
|
|
23
|
+
"COPY (SELECT name, value FROM events) TO 'events.csv'"
|
|
24
|
+
),
|
|
25
|
+
(
|
|
26
|
+
BaseTest.qb.copy_to(
|
|
27
|
+
BaseTest.qb.select('name', 'value').from_table('events'),
|
|
28
|
+
'events.csv',
|
|
29
|
+
{'DELIMITER': "','", 'APPEND': True},
|
|
30
|
+
),
|
|
31
|
+
"COPY (SELECT name, value FROM events) TO 'events.csv' (DELIMITER ',', APPEND true)",
|
|
32
|
+
),
|
|
33
|
+
])
|
|
34
|
+
def test_copy_to(self, query: QueryProtocol, exp_sql: str):
|
|
35
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from parameterized import parameterized
|
|
2
|
+
|
|
3
|
+
from david8_duckdb.protocols.sql import SelectProtocol
|
|
4
|
+
from tests.base_test import BaseTest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestSelect(BaseTest):
|
|
8
|
+
@parameterized.expand([
|
|
9
|
+
(
|
|
10
|
+
BaseTest.qb.select('*').from_csv('faulty.csv'),
|
|
11
|
+
"SELECT * FROM read_csv('faulty.csv')",
|
|
12
|
+
),
|
|
13
|
+
(
|
|
14
|
+
BaseTest.qb.select('*').from_csv('flights1.csv', 'flights2.csv'),
|
|
15
|
+
"SELECT * FROM read_csv(['flights1.csv', 'flights2.csv'])",
|
|
16
|
+
),
|
|
17
|
+
])
|
|
18
|
+
def test_from_csv(self, query: SelectProtocol, exp_sql: str):
|
|
19
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
20
|
+
|
|
21
|
+
@parameterized.expand([
|
|
22
|
+
(
|
|
23
|
+
BaseTest.qb.select('*').from_json('todos.json'),
|
|
24
|
+
"SELECT * FROM read_json('todos.json')",
|
|
25
|
+
),
|
|
26
|
+
(
|
|
27
|
+
BaseTest.qb.select('*').from_json('todos1.json', 'todos2.json'),
|
|
28
|
+
"SELECT * FROM read_json(['todos1.json', 'todos2.json'])",
|
|
29
|
+
),
|
|
30
|
+
])
|
|
31
|
+
def test_from_json(self, query: SelectProtocol, exp_sql: str):
|
|
32
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
33
|
+
|
|
34
|
+
@parameterized.expand([
|
|
35
|
+
(
|
|
36
|
+
BaseTest.qb.select('*').from_json_objects('todos.json'),
|
|
37
|
+
"SELECT * FROM read_json_objects('todos.json')",
|
|
38
|
+
),
|
|
39
|
+
(
|
|
40
|
+
BaseTest.qb.select('*').from_json_objects('todos1.json', 'todos2.json'),
|
|
41
|
+
"SELECT * FROM read_json_objects(['todos1.json', 'todos2.json'])",
|
|
42
|
+
),
|
|
43
|
+
])
|
|
44
|
+
def test_from_json_objects(self, query: SelectProtocol, exp_sql: str):
|
|
45
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
46
|
+
|
|
47
|
+
@parameterized.expand([
|
|
48
|
+
(
|
|
49
|
+
BaseTest.qb.select('*').from_ndjson_objects('todos.json'),
|
|
50
|
+
"SELECT * FROM read_ndjson_objects('todos.json')",
|
|
51
|
+
),
|
|
52
|
+
(
|
|
53
|
+
BaseTest.qb.select('*').from_ndjson_objects('todos1.json', 'todos2.json'),
|
|
54
|
+
"SELECT * FROM read_ndjson_objects(['todos1.json', 'todos2.json'])",
|
|
55
|
+
),
|
|
56
|
+
])
|
|
57
|
+
def test_from_ndjson_objects(self, query: SelectProtocol, exp_sql: str):
|
|
58
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
59
|
+
|
|
60
|
+
@parameterized.expand([
|
|
61
|
+
(
|
|
62
|
+
BaseTest.qb.select('*').from_json_objects_auto('todos.json'),
|
|
63
|
+
"SELECT * FROM read_json_objects_auto('todos.json')",
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
BaseTest.qb.select('*').from_json_objects_auto('todos1.json', 'todos2.json'),
|
|
67
|
+
"SELECT * FROM read_json_objects_auto(['todos1.json', 'todos2.json'])",
|
|
68
|
+
),
|
|
69
|
+
])
|
|
70
|
+
def test_from_json_objects_auto(self, query: SelectProtocol, exp_sql: str):
|
|
71
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
72
|
+
|
|
73
|
+
@parameterized.expand([
|
|
74
|
+
(
|
|
75
|
+
BaseTest.qb.select('*').from_parquet('file.parquet'),
|
|
76
|
+
"SELECT * FROM read_parquet('file.parquet')",
|
|
77
|
+
),
|
|
78
|
+
(
|
|
79
|
+
BaseTest.qb.select('*').from_parquet('file1.parquet', 'file2.parquet'),
|
|
80
|
+
"SELECT * FROM read_parquet(['file1.parquet', 'file2.parquet'])",
|
|
81
|
+
),
|
|
82
|
+
])
|
|
83
|
+
def test_from_parquet(self, query: SelectProtocol, exp_sql: str):
|
|
84
|
+
self.assertEqual(query.get_sql(), exp_sql)
|
|
85
|
+
|
|
86
|
+
@parameterized.expand([
|
|
87
|
+
(
|
|
88
|
+
BaseTest.qb.select('*').from_xlsx('test.xlsx'),
|
|
89
|
+
"SELECT * FROM read_xlsx('test.xlsx')",
|
|
90
|
+
),
|
|
91
|
+
])
|
|
92
|
+
def test_from_xlsx(self, query: SelectProtocol, exp_sql: str):
|
|
93
|
+
self.assertEqual(query.get_sql(), exp_sql)
|