e6data-spark-compatibility 1.0.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.
Files changed (112) hide show
  1. e6_spark_compat/__init__.py +50 -0
  2. e6_spark_compat/_vendor/__init__.py +35 -0
  3. e6_spark_compat/_vendor/sqlglot/__init__.py +180 -0
  4. e6_spark_compat/_vendor/sqlglot/__main__.py +96 -0
  5. e6_spark_compat/_vendor/sqlglot/_typing.py +17 -0
  6. e6_spark_compat/_vendor/sqlglot/_version.py +34 -0
  7. e6_spark_compat/_vendor/sqlglot/dialects/__init__.py +126 -0
  8. e6_spark_compat/_vendor/sqlglot/dialects/athena.py +288 -0
  9. e6_spark_compat/_vendor/sqlglot/dialects/bigquery.py +1443 -0
  10. e6_spark_compat/_vendor/sqlglot/dialects/clickhouse.py +1417 -0
  11. e6_spark_compat/_vendor/sqlglot/dialects/databricks.py +290 -0
  12. e6_spark_compat/_vendor/sqlglot/dialects/dialect.py +2004 -0
  13. e6_spark_compat/_vendor/sqlglot/dialects/doris.py +687 -0
  14. e6_spark_compat/_vendor/sqlglot/dialects/dremio.py +124 -0
  15. e6_spark_compat/_vendor/sqlglot/dialects/drill.py +160 -0
  16. e6_spark_compat/_vendor/sqlglot/dialects/druid.py +20 -0
  17. e6_spark_compat/_vendor/sqlglot/dialects/duckdb.py +1263 -0
  18. e6_spark_compat/_vendor/sqlglot/dialects/dune.py +16 -0
  19. e6_spark_compat/_vendor/sqlglot/dialects/e6.py +3153 -0
  20. e6_spark_compat/_vendor/sqlglot/dialects/exasol.py +251 -0
  21. e6_spark_compat/_vendor/sqlglot/dialects/fabric.py +213 -0
  22. e6_spark_compat/_vendor/sqlglot/dialects/hive.py +813 -0
  23. e6_spark_compat/_vendor/sqlglot/dialects/materialize.py +96 -0
  24. e6_spark_compat/_vendor/sqlglot/dialects/mysql.py +1329 -0
  25. e6_spark_compat/_vendor/sqlglot/dialects/oracle.py +395 -0
  26. e6_spark_compat/_vendor/sqlglot/dialects/postgres.py +849 -0
  27. e6_spark_compat/_vendor/sqlglot/dialects/presto.py +857 -0
  28. e6_spark_compat/_vendor/sqlglot/dialects/prql.py +209 -0
  29. e6_spark_compat/_vendor/sqlglot/dialects/redshift.py +464 -0
  30. e6_spark_compat/_vendor/sqlglot/dialects/risingwave.py +85 -0
  31. e6_spark_compat/_vendor/sqlglot/dialects/singlestore.py +1146 -0
  32. e6_spark_compat/_vendor/sqlglot/dialects/snowflake.py +1796 -0
  33. e6_spark_compat/_vendor/sqlglot/dialects/spark.py +261 -0
  34. e6_spark_compat/_vendor/sqlglot/dialects/spark2.py +456 -0
  35. e6_spark_compat/_vendor/sqlglot/dialects/sqlite.py +344 -0
  36. e6_spark_compat/_vendor/sqlglot/dialects/starrocks.py +356 -0
  37. e6_spark_compat/_vendor/sqlglot/dialects/tableau.py +61 -0
  38. e6_spark_compat/_vendor/sqlglot/dialects/teradata.py +398 -0
  39. e6_spark_compat/_vendor/sqlglot/dialects/trino.py +116 -0
  40. e6_spark_compat/_vendor/sqlglot/dialects/tsql.py +1420 -0
  41. e6_spark_compat/_vendor/sqlglot/diff.py +468 -0
  42. e6_spark_compat/_vendor/sqlglot/errors.py +93 -0
  43. e6_spark_compat/_vendor/sqlglot/executor/__init__.py +95 -0
  44. e6_spark_compat/_vendor/sqlglot/executor/context.py +101 -0
  45. e6_spark_compat/_vendor/sqlglot/executor/env.py +246 -0
  46. e6_spark_compat/_vendor/sqlglot/executor/python.py +460 -0
  47. e6_spark_compat/_vendor/sqlglot/executor/table.py +155 -0
  48. e6_spark_compat/_vendor/sqlglot/expressions.py +9186 -0
  49. e6_spark_compat/_vendor/sqlglot/generator.py +5147 -0
  50. e6_spark_compat/_vendor/sqlglot/helper.py +582 -0
  51. e6_spark_compat/_vendor/sqlglot/jsonpath.py +227 -0
  52. e6_spark_compat/_vendor/sqlglot/lineage.py +433 -0
  53. e6_spark_compat/_vendor/sqlglot/optimizer/__init__.py +11 -0
  54. e6_spark_compat/_vendor/sqlglot/optimizer/annotate_types.py +665 -0
  55. e6_spark_compat/_vendor/sqlglot/optimizer/canonicalize.py +222 -0
  56. e6_spark_compat/_vendor/sqlglot/optimizer/eliminate_ctes.py +43 -0
  57. e6_spark_compat/_vendor/sqlglot/optimizer/eliminate_joins.py +181 -0
  58. e6_spark_compat/_vendor/sqlglot/optimizer/eliminate_subqueries.py +189 -0
  59. e6_spark_compat/_vendor/sqlglot/optimizer/isolate_table_selects.py +50 -0
  60. e6_spark_compat/_vendor/sqlglot/optimizer/merge_subqueries.py +418 -0
  61. e6_spark_compat/_vendor/sqlglot/optimizer/normalize.py +200 -0
  62. e6_spark_compat/_vendor/sqlglot/optimizer/normalize_identifiers.py +64 -0
  63. e6_spark_compat/_vendor/sqlglot/optimizer/optimize_joins.py +92 -0
  64. e6_spark_compat/_vendor/sqlglot/optimizer/optimizer.py +94 -0
  65. e6_spark_compat/_vendor/sqlglot/optimizer/pushdown_predicates.py +223 -0
  66. e6_spark_compat/_vendor/sqlglot/optimizer/pushdown_projections.py +176 -0
  67. e6_spark_compat/_vendor/sqlglot/optimizer/qualify.py +104 -0
  68. e6_spark_compat/_vendor/sqlglot/optimizer/qualify_columns.py +1111 -0
  69. e6_spark_compat/_vendor/sqlglot/optimizer/qualify_tables.py +171 -0
  70. e6_spark_compat/_vendor/sqlglot/optimizer/scope.py +933 -0
  71. e6_spark_compat/_vendor/sqlglot/optimizer/simplify.py +1603 -0
  72. e6_spark_compat/_vendor/sqlglot/optimizer/unnest_subqueries.py +302 -0
  73. e6_spark_compat/_vendor/sqlglot/parser.py +8817 -0
  74. e6_spark_compat/_vendor/sqlglot/planner.py +463 -0
  75. e6_spark_compat/_vendor/sqlglot/py.typed +0 -0
  76. e6_spark_compat/_vendor/sqlglot/schema.py +604 -0
  77. e6_spark_compat/_vendor/sqlglot/serde.py +68 -0
  78. e6_spark_compat/_vendor/sqlglot/time.py +687 -0
  79. e6_spark_compat/_vendor/sqlglot/tokens.py +1559 -0
  80. e6_spark_compat/_vendor/sqlglot/transforms.py +1044 -0
  81. e6_spark_compat/_vendor/sqlglot/trie.py +81 -0
  82. e6_spark_compat/core/__init__.py +1 -0
  83. e6_spark_compat/core/connection.py +185 -0
  84. e6_spark_compat/core/e6_executor.py +81 -0
  85. e6_spark_compat/core/logging_config.py +201 -0
  86. e6_spark_compat/core/query_plan.py +850 -0
  87. e6_spark_compat/core/schema_cache.py +73 -0
  88. e6_spark_compat/core/session.py +303 -0
  89. e6_spark_compat/core/sql_generator.py +2880 -0
  90. e6_spark_compat/core/types.py +75 -0
  91. e6_spark_compat/pyspark_compat.py +14 -0
  92. e6_spark_compat/sedona/__init__.py +85 -0
  93. e6_spark_compat/spatial/__init__.py +1 -0
  94. e6_spark_compat/spatial/functions.py +547 -0
  95. e6_spark_compat/spatial/sedona_registrator.py +13 -0
  96. e6_spark_compat/sql/__init__.py +8 -0
  97. e6_spark_compat/sql/column.py +780 -0
  98. e6_spark_compat/sql/dataframe.py +1275 -0
  99. e6_spark_compat/sql/functions.py +1172 -0
  100. e6_spark_compat/sql/group.py +117 -0
  101. e6_spark_compat/sql/mock_io.py +441 -0
  102. e6_spark_compat/sql/reader.py +369 -0
  103. e6_spark_compat/sql/row.py +65 -0
  104. e6_spark_compat/sql/types.py +298 -0
  105. e6_spark_compat/sql/udf_translator.py +1812 -0
  106. e6_spark_compat/sql/window.py +282 -0
  107. e6_spark_compat/sql/writer.py +545 -0
  108. e6data_spark_compatibility-1.0.0.dist-info/METADATA +424 -0
  109. e6data_spark_compatibility-1.0.0.dist-info/RECORD +112 -0
  110. e6data_spark_compatibility-1.0.0.dist-info/WHEEL +5 -0
  111. e6data_spark_compatibility-1.0.0.dist-info/licenses/LICENSE +69 -0
  112. e6data_spark_compatibility-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,50 @@
1
+ """
2
+ e6-spark-compat: PySpark and Sedona compatibility layer for e6data
3
+ """
4
+
5
+ # Fix multiprocessing issue on macOS/Windows before any imports
6
+ import platform
7
+ import multiprocessing
8
+ import os
9
+
10
+ # Only apply fix if:
11
+ # 1. We're on macOS (Darwin) or Windows
12
+ # 2. Not explicitly disabled via environment variable
13
+ # 3. The current method is 'spawn' (problematic)
14
+ if os.environ.get('E6_SPARK_COMPAT_NO_MP_FIX') != '1':
15
+ try:
16
+ current_method = multiprocessing.get_start_method(allow_none=True)
17
+ system = platform.system()
18
+
19
+ # macOS defaults to 'spawn' which causes re-imports
20
+ # current_method can be None initially, which defaults to 'spawn' on macOS
21
+ if system == 'Darwin' and (current_method == 'spawn' or current_method is None):
22
+ multiprocessing.set_start_method('fork', force=True)
23
+ # Windows only supports 'spawn', so we can't fix it this way
24
+ elif system == 'Windows' and current_method == 'spawn':
25
+ # Log a warning but continue
26
+ import warnings
27
+ warnings.warn(
28
+ "e6-spark-compat: Windows detected. Scripts may execute multiple times. "
29
+ "Use 'if __name__ == \"__main__\":' guard to prevent issues.",
30
+ RuntimeWarning
31
+ )
32
+ except (RuntimeError, ValueError):
33
+ # Already set or platform doesn't support the change
34
+ pass
35
+
36
+ # Initialize vendored dependencies first (patches sys.modules for sqlglot)
37
+ from . import _vendor
38
+
39
+ # Initialize logging configuration before importing other modules
40
+ from .core.logging_config import configure_logging
41
+ configure_logging()
42
+
43
+ from .core.session import SparkSession
44
+ from .sql.dataframe import DataFrame
45
+ from .sql.column import Column
46
+ from .sql.row import Row
47
+ from .core.sql_generator import set_use_cte
48
+
49
+ __version__ = "1.0.0"
50
+ __all__ = ["SparkSession", "DataFrame", "Column", "Row", "set_use_cte"]
@@ -0,0 +1,35 @@
1
+ """
2
+ Vendored dependencies for e6-spark-compat.
3
+
4
+ This directory contains vendored (bundled) copies of dependencies
5
+ to avoid external package requirements for PyPI publishing.
6
+ """
7
+ import sys
8
+ import os
9
+ import importlib.util
10
+
11
+ # Pre-register sqlglot in sys.modules BEFORE importing it
12
+ # This is necessary because the vendored sqlglot uses internal imports like 'from sqlglot import ...'
13
+ def _setup_vendored_sqlglot():
14
+ """Setup vendored sqlglot by pre-registering it in sys.modules."""
15
+ vendor_dir = os.path.dirname(__file__)
16
+ sqlglot_dir = os.path.join(vendor_dir, 'sqlglot')
17
+
18
+ # Create a module spec for the vendored sqlglot
19
+ spec = importlib.util.spec_from_file_location(
20
+ 'sqlglot',
21
+ os.path.join(sqlglot_dir, '__init__.py'),
22
+ submodule_search_locations=[sqlglot_dir]
23
+ )
24
+
25
+ # Create the module and add to sys.modules BEFORE executing it
26
+ sqlglot_module = importlib.util.module_from_spec(spec)
27
+ sys.modules['sqlglot'] = sqlglot_module
28
+
29
+ # Now execute the module (this allows internal imports to work)
30
+ spec.loader.exec_module(sqlglot_module)
31
+
32
+ # Also make it available as e6_spark_compat._vendor.sqlglot
33
+ sys.modules['e6_spark_compat._vendor.sqlglot'] = sqlglot_module
34
+
35
+ _setup_vendored_sqlglot()
@@ -0,0 +1,180 @@
1
+ # ruff: noqa: F401
2
+ """
3
+ .. include:: ../README.md
4
+
5
+ ----
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ import typing as t
12
+
13
+ from sqlglot import expressions as exp
14
+ from sqlglot.dialects.dialect import Dialect as Dialect, Dialects as Dialects
15
+ from sqlglot.diff import diff as diff
16
+ from sqlglot.errors import (
17
+ ErrorLevel as ErrorLevel,
18
+ ParseError as ParseError,
19
+ TokenError as TokenError,
20
+ UnsupportedError as UnsupportedError,
21
+ )
22
+ from sqlglot.expressions import (
23
+ Expression as Expression,
24
+ alias_ as alias,
25
+ and_ as and_,
26
+ case as case,
27
+ cast as cast,
28
+ column as column,
29
+ condition as condition,
30
+ delete as delete,
31
+ except_ as except_,
32
+ from_ as from_,
33
+ func as func,
34
+ insert as insert,
35
+ intersect as intersect,
36
+ maybe_parse as maybe_parse,
37
+ merge as merge,
38
+ not_ as not_,
39
+ or_ as or_,
40
+ select as select,
41
+ subquery as subquery,
42
+ table_ as table,
43
+ to_column as to_column,
44
+ to_identifier as to_identifier,
45
+ to_table as to_table,
46
+ union as union,
47
+ )
48
+ from sqlglot.generator import Generator as Generator
49
+ from sqlglot.parser import Parser as Parser
50
+ from sqlglot.schema import MappingSchema as MappingSchema, Schema as Schema
51
+ from sqlglot.tokens import (
52
+ Token as Token,
53
+ Tokenizer as Tokenizer,
54
+ TokenType as TokenType,
55
+ )
56
+
57
+ if t.TYPE_CHECKING:
58
+ from sqlglot._typing import E
59
+ from sqlglot.dialects.dialect import DialectType as DialectType
60
+
61
+ logger = logging.getLogger("sqlglot")
62
+
63
+
64
+ try:
65
+ from sqlglot._version import __version__, __version_tuple__
66
+ except ImportError:
67
+ logger.error(
68
+ "Unable to set __version__, run `pip install -e .` or `python setup.py develop` first."
69
+ )
70
+
71
+
72
+ pretty = False
73
+ """Whether to format generated SQL by default."""
74
+
75
+
76
+ def tokenize(sql: str, read: DialectType = None, dialect: DialectType = None) -> t.List[Token]:
77
+ """
78
+ Tokenizes the given SQL string.
79
+
80
+ Args:
81
+ sql: the SQL code string to tokenize.
82
+ read: the SQL dialect to apply during tokenizing (eg. "spark", "hive", "presto", "mysql").
83
+ dialect: the SQL dialect (alias for read).
84
+
85
+ Returns:
86
+ The resulting list of tokens.
87
+ """
88
+ return Dialect.get_or_raise(read or dialect).tokenize(sql)
89
+
90
+
91
+ def parse(
92
+ sql: str, read: DialectType = None, dialect: DialectType = None, **opts
93
+ ) -> t.List[t.Optional[Expression]]:
94
+ """
95
+ Parses the given SQL string into a collection of syntax trees, one per parsed SQL statement.
96
+
97
+ Args:
98
+ sql: the SQL code string to parse.
99
+ read: the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql").
100
+ dialect: the SQL dialect (alias for read).
101
+ **opts: other `sqlglot.parser.Parser` options.
102
+
103
+ Returns:
104
+ The resulting syntax tree collection.
105
+ """
106
+ return Dialect.get_or_raise(read or dialect).parse(sql, **opts)
107
+
108
+
109
+ @t.overload
110
+ def parse_one(sql: str, *, into: t.Type[E], **opts) -> E: ...
111
+
112
+
113
+ @t.overload
114
+ def parse_one(sql: str, **opts) -> Expression: ...
115
+
116
+
117
+ def parse_one(
118
+ sql: str,
119
+ read: DialectType = None,
120
+ dialect: DialectType = None,
121
+ into: t.Optional[exp.IntoType] = None,
122
+ **opts,
123
+ ) -> Expression:
124
+ """
125
+ Parses the given SQL string and returns a syntax tree for the first parsed SQL statement.
126
+
127
+ Args:
128
+ sql: the SQL code string to parse.
129
+ read: the SQL dialect to apply during parsing (eg. "spark", "hive", "presto", "mysql").
130
+ dialect: the SQL dialect (alias for read)
131
+ into: the SQLGlot Expression to parse into.
132
+ **opts: other `sqlglot.parser.Parser` options.
133
+
134
+ Returns:
135
+ The syntax tree for the first parsed statement.
136
+ """
137
+
138
+ dialect = Dialect.get_or_raise(read or dialect)
139
+ if into:
140
+ result = dialect.parse_into(into, sql, **opts)
141
+ else:
142
+ result = dialect.parse(sql, **opts)
143
+ for expression in result:
144
+ if not expression:
145
+ raise ParseError(f"No expression was parsed from '{sql}'")
146
+ return expression
147
+ else:
148
+ raise ParseError(f"No expression was parsed from '{sql}'")
149
+
150
+
151
+ def transpile(
152
+ sql: str,
153
+ read: DialectType = None,
154
+ write: DialectType = None,
155
+ identity: bool = True,
156
+ error_level: t.Optional[ErrorLevel] = None,
157
+ **opts,
158
+ ) -> t.List[str]:
159
+ """
160
+ Parses the given SQL string in accordance with the source dialect and returns a list of SQL strings transformed
161
+ to conform to the target dialect. Each string in the returned list represents a single transformed SQL statement.
162
+
163
+ Args:
164
+ sql: the SQL code string to transpile.
165
+ read: the source dialect used to parse the input string (eg. "spark", "hive", "presto", "mysql").
166
+ write: the target dialect into which the input should be transformed (eg. "spark", "hive", "presto", "mysql").
167
+ identity: if set to `True` and if the target dialect is not specified the source dialect will be used as both:
168
+ the source and the target dialect.
169
+ error_level: the desired error level of the parser.
170
+ **opts: other `sqlglot.generator.Generator` options.
171
+
172
+ Returns:
173
+ The list of transpiled SQL statements.
174
+ """
175
+ write = (read if write is None else write) if identity else write
176
+ write = Dialect.get_or_raise(write)
177
+ return [
178
+ write.generate(expression, copy=False, **opts) if expression else ""
179
+ for expression in parse(sql, read, error_level=error_level)
180
+ ]
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import sys
5
+ import typing as t
6
+
7
+ import sqlglot
8
+
9
+ parser = argparse.ArgumentParser(description="Transpile SQL")
10
+ parser.add_argument(
11
+ "sql",
12
+ metavar="sql",
13
+ type=str,
14
+ help="SQL statement(s) to transpile, or - to parse stdin.",
15
+ )
16
+ parser.add_argument(
17
+ "--read",
18
+ dest="read",
19
+ type=str,
20
+ default=None,
21
+ help="Dialect to read default is generic",
22
+ )
23
+ parser.add_argument(
24
+ "--write",
25
+ dest="write",
26
+ type=str,
27
+ default=None,
28
+ help="Dialect to write default is generic",
29
+ )
30
+ parser.add_argument(
31
+ "--no-identify",
32
+ dest="identify",
33
+ action="store_false",
34
+ help="Don't auto identify fields",
35
+ )
36
+ parser.add_argument(
37
+ "--no-pretty",
38
+ dest="pretty",
39
+ action="store_false",
40
+ help="Compress sql",
41
+ )
42
+ parser.add_argument(
43
+ "--parse",
44
+ dest="parse",
45
+ action="store_true",
46
+ help="Parse and return the expression tree",
47
+ )
48
+ parser.add_argument(
49
+ "--tokenize",
50
+ dest="tokenize",
51
+ action="store_true",
52
+ help="Tokenize and return the tokens list",
53
+ )
54
+ parser.add_argument(
55
+ "--error-level",
56
+ dest="error_level",
57
+ type=str,
58
+ default="IMMEDIATE",
59
+ help="IGNORE, WARN, RAISE, IMMEDIATE (default)",
60
+ )
61
+ parser.add_argument(
62
+ "--version",
63
+ action="version",
64
+ version=sqlglot.__version__,
65
+ help="Display the SQLGlot version",
66
+ )
67
+
68
+
69
+ args = parser.parse_args()
70
+ error_level = sqlglot.ErrorLevel[args.error_level.upper()]
71
+
72
+ sql = sys.stdin.read() if args.sql == "-" else args.sql
73
+
74
+ if args.parse:
75
+ objs: t.Union[t.List[str], t.List[sqlglot.tokens.Token]] = [
76
+ repr(expression)
77
+ for expression in sqlglot.parse(
78
+ sql,
79
+ read=args.read,
80
+ error_level=error_level,
81
+ )
82
+ ]
83
+ elif args.tokenize:
84
+ objs = sqlglot.Dialect.get_or_raise(args.read).tokenize(sql)
85
+ else:
86
+ objs = sqlglot.transpile(
87
+ sql,
88
+ read=args.read,
89
+ write=args.write,
90
+ identify=args.identify,
91
+ pretty=args.pretty,
92
+ error_level=error_level,
93
+ )
94
+
95
+ for obj in objs:
96
+ print(obj)
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ import sqlglot
6
+
7
+ if t.TYPE_CHECKING:
8
+ from typing_extensions import Literal as Lit # noqa
9
+
10
+ # A little hack for backwards compatibility with Python 3.7.
11
+ # For example, we might want a TypeVar for objects that support comparison e.g. SupportsRichComparisonT from typeshed.
12
+ # But Python 3.7 doesn't support Protocols, so we'd also need typing_extensions, which we don't want as a dependency.
13
+ A = t.TypeVar("A", bound=t.Any)
14
+ B = t.TypeVar("B", bound="sqlglot.exp.Binary")
15
+ E = t.TypeVar("E", bound="sqlglot.exp.Expression")
16
+ F = t.TypeVar("F", bound="sqlglot.exp.Func")
17
+ T = t.TypeVar("T")
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.0.1.dev6817'
32
+ __version_tuple__ = version_tuple = (0, 0, 1, 'dev6817')
33
+
34
+ __commit_id__ = commit_id = 'g8a0cb2080'
@@ -0,0 +1,126 @@
1
+ # ruff: noqa: F401
2
+ """
3
+ ## Dialects
4
+
5
+ While there is a SQL standard, most SQL engines support a variation of that standard. This makes it difficult
6
+ to write portable SQL code. SQLGlot bridges all the different variations, called "dialects", with an extensible
7
+ SQL transpilation framework.
8
+
9
+ The base `sqlglot.dialects.dialect.Dialect` class implements a generic dialect that aims to be as universal as possible.
10
+
11
+ Each SQL variation has its own `Dialect` subclass, extending the corresponding `Tokenizer`, `Parser` and `Generator`
12
+ classes as needed.
13
+
14
+ ### Implementing a custom Dialect
15
+
16
+ Creating a new SQL dialect may seem complicated at first, but it is actually quite simple in SQLGlot:
17
+
18
+ ```python
19
+ from sqlglot import exp
20
+ from sqlglot.dialects.dialect import Dialect
21
+ from sqlglot.generator import Generator
22
+ from sqlglot.tokens import Tokenizer, TokenType
23
+
24
+
25
+ class Custom(Dialect):
26
+ class Tokenizer(Tokenizer):
27
+ QUOTES = ["'", '"'] # Strings can be delimited by either single or double quotes
28
+ IDENTIFIERS = ["`"] # Identifiers can be delimited by backticks
29
+
30
+ # Associates certain meaningful words with tokens that capture their intent
31
+ KEYWORDS = {
32
+ **Tokenizer.KEYWORDS,
33
+ "INT64": TokenType.BIGINT,
34
+ "FLOAT64": TokenType.DOUBLE,
35
+ }
36
+
37
+ class Generator(Generator):
38
+ # Specifies how AST nodes, i.e. subclasses of exp.Expression, should be converted into SQL
39
+ TRANSFORMS = {
40
+ exp.Array: lambda self, e: f"[{self.expressions(e)}]",
41
+ }
42
+
43
+ # Specifies how AST nodes representing data types should be converted into SQL
44
+ TYPE_MAPPING = {
45
+ exp.DataType.Type.TINYINT: "INT64",
46
+ exp.DataType.Type.SMALLINT: "INT64",
47
+ exp.DataType.Type.INT: "INT64",
48
+ exp.DataType.Type.BIGINT: "INT64",
49
+ exp.DataType.Type.DECIMAL: "NUMERIC",
50
+ exp.DataType.Type.FLOAT: "FLOAT64",
51
+ exp.DataType.Type.DOUBLE: "FLOAT64",
52
+ exp.DataType.Type.BOOLEAN: "BOOL",
53
+ exp.DataType.Type.TEXT: "STRING",
54
+ }
55
+ ```
56
+
57
+ The above example demonstrates how certain parts of the base `Dialect` class can be overridden to match a different
58
+ specification. Even though it is a fairly realistic starting point, we strongly encourage the reader to study existing
59
+ dialect implementations in order to understand how their various components can be modified, depending on the use-case.
60
+
61
+ ----
62
+ """
63
+
64
+ import importlib
65
+ import threading
66
+
67
+ DIALECTS = [
68
+ "Athena",
69
+ "BigQuery",
70
+ "ClickHouse",
71
+ "Databricks",
72
+ "Doris",
73
+ "Dremio",
74
+ "Drill",
75
+ "Druid",
76
+ "DuckDB",
77
+ "Dune",
78
+ "Fabric",
79
+ "Hive",
80
+ "Materialize",
81
+ "MySQL",
82
+ "Oracle",
83
+ "Postgres",
84
+ "Presto",
85
+ "PRQL",
86
+ "Redshift",
87
+ "RisingWave",
88
+ "SingleStore",
89
+ "Snowflake",
90
+ "Spark",
91
+ "Spark2",
92
+ "SQLite",
93
+ "StarRocks",
94
+ "Tableau",
95
+ "Teradata",
96
+ "Trino",
97
+ "TSQL",
98
+ "Exasol",
99
+ "E6",
100
+ ]
101
+
102
+ MODULE_BY_DIALECT = {name: name.lower() for name in DIALECTS}
103
+ DIALECT_MODULE_NAMES = MODULE_BY_DIALECT.values()
104
+
105
+ MODULE_BY_ATTRIBUTE = {
106
+ **MODULE_BY_DIALECT,
107
+ "Dialect": "dialect",
108
+ "Dialects": "dialect",
109
+ }
110
+
111
+ __all__ = list(MODULE_BY_ATTRIBUTE)
112
+
113
+ # We use a reentrant lock because a dialect may depend on (i.e., import) other dialects.
114
+ # Without it, the first dialect import would never be completed, because subsequent
115
+ # imports would be blocked on the lock held by the first import.
116
+ _import_lock = threading.RLock()
117
+
118
+
119
+ def __getattr__(name):
120
+ module_name = MODULE_BY_ATTRIBUTE.get(name)
121
+ if module_name:
122
+ with _import_lock:
123
+ module = importlib.import_module(f"sqlglot.dialects.{module_name}")
124
+ return getattr(module, name)
125
+
126
+ raise AttributeError(f"module {__name__} has no attribute {name}")