text2sql-engine 0.1.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.
text2sql/types.py ADDED
@@ -0,0 +1,138 @@
1
+ """Dataclasses returned by the pipeline.
2
+
3
+ Plain dataclasses, no external deps. Easy to inspect and serialize.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import time
9
+ from dataclasses import dataclass, field
10
+ from typing import Any
11
+
12
+
13
+ @dataclass
14
+ class TokenUsage:
15
+ """Token counts for one LLM call. Zero when the provider reports nothing."""
16
+
17
+ prompt_tokens: int = 0
18
+ completion_tokens: int = 0
19
+ total_tokens: int = 0
20
+
21
+ def __add__(self, other: "TokenUsage") -> "TokenUsage":
22
+ return TokenUsage(
23
+ prompt_tokens=self.prompt_tokens + other.prompt_tokens,
24
+ completion_tokens=self.completion_tokens + other.completion_tokens,
25
+ total_tokens=self.total_tokens + other.total_tokens,
26
+ )
27
+
28
+
29
+ @dataclass
30
+ class LLMResponse:
31
+ """One provider call, normalized.
32
+
33
+ Same shape for every provider, so the pipeline never touches an SDK type.
34
+ ``raw`` keeps the native response for advanced callers.
35
+ """
36
+
37
+ text: str
38
+ usage: TokenUsage = field(default_factory=TokenUsage)
39
+ model: str = ""
40
+ raw: Any = None
41
+
42
+
43
+ @dataclass
44
+ class LinkedColumn:
45
+ """A column picked by Stage 1."""
46
+
47
+ table: str
48
+ column: str
49
+ reason: str = ""
50
+
51
+
52
+ @dataclass
53
+ class LinkedJoin:
54
+ """A candidate join between two tables, found during linking."""
55
+
56
+ left_table: str
57
+ left_column: str
58
+ right_table: str
59
+ right_column: str
60
+
61
+
62
+ @dataclass
63
+ class LinkedSchema:
64
+ """Stage 1 output: the reduced schema.
65
+
66
+ This is what Stage 2 receives. It is also returned on the final result so
67
+ callers can see what the pipeline picked as relevant.
68
+ """
69
+
70
+ tables: list[str] = field(default_factory=list)
71
+ columns: list[LinkedColumn] = field(default_factory=list)
72
+ joins: list[LinkedJoin] = field(default_factory=list)
73
+ entities: list[str] = field(default_factory=list)
74
+ filters: list[str] = field(default_factory=list)
75
+ rationale: str = ""
76
+
77
+ def is_empty(self) -> bool:
78
+ """True when linking found no usable table or column."""
79
+ return not self.tables and not self.columns
80
+
81
+
82
+ @dataclass
83
+ class StageMetadata:
84
+ """Metadata for one stage: which model, how many tokens, how long."""
85
+
86
+ provider: str
87
+ model: str
88
+ usage: TokenUsage = field(default_factory=TokenUsage)
89
+ latency_seconds: float = 0.0
90
+ attempts: int = 1
91
+
92
+
93
+ @dataclass
94
+ class RunMetadata:
95
+ """Metadata for a full run (both stages)."""
96
+
97
+ linking: StageMetadata
98
+ generation: StageMetadata
99
+ total_latency_seconds: float = 0.0
100
+
101
+ @property
102
+ def total_usage(self) -> TokenUsage:
103
+ """Token usage of both stages combined."""
104
+ return self.linking.usage + self.generation.usage
105
+
106
+
107
+ @dataclass
108
+ class Text2SQLResult:
109
+ """Final result of :meth:`text2sql.Text2SQL.run`.
110
+
111
+ Attributes:
112
+ sql: The generated SQL string. This is the deliverable.
113
+ explanation: Optional short explanation from Stage 2.
114
+ linked_schema: Stage 1 output (the reduced schema).
115
+ metadata: Models, tokens, and latency for the run.
116
+ request: The original request.
117
+ """
118
+
119
+ sql: str
120
+ linked_schema: LinkedSchema
121
+ metadata: RunMetadata
122
+ request: str
123
+ explanation: str = ""
124
+
125
+
126
+ class _Timer:
127
+ """Small monotonic timer for stage latency. Internal only."""
128
+
129
+ def __init__(self) -> None:
130
+ self._start = 0.0
131
+ self.elapsed = 0.0
132
+
133
+ def __enter__(self) -> "_Timer":
134
+ self._start = time.perf_counter()
135
+ return self
136
+
137
+ def __exit__(self, *exc: object) -> None:
138
+ self.elapsed = time.perf_counter() - self._start
@@ -0,0 +1,304 @@
1
+ Metadata-Version: 2.4
2
+ Name: text2sql-engine
3
+ Version: 0.1.0
4
+ Summary: Schema-agnostic, config-driven Text-to-SQL library (2-stage LLM pipeline). Produces a SQL string; never connects to or executes against a database.
5
+ Author: stajyer14
6
+ License: MIT
7
+ Keywords: text-to-sql,nl2sql,llm,sql-generation,schema-linking
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Database
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: python-dotenv>=1.0
23
+ Requires-Dist: PyYAML>=6.0
24
+ Provides-Extra: openai
25
+ Requires-Dist: openai>=1.0; extra == "openai"
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.34; extra == "anthropic"
28
+ Provides-Extra: all
29
+ Requires-Dist: openai>=1.0; extra == "all"
30
+ Requires-Dist: anthropic>=0.34; extra == "all"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.4; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # text2sql
36
+
37
+ A **schema-agnostic, config-driven Text-to-SQL library**. Give it a
38
+ natural-language request and metadata for any relational schema, and it returns
39
+ a SQL string.
40
+
41
+ It is a **library**, not an app. No UI, no web server, no CLI. It **never
42
+ connects to or runs against a database**. Generating the SQL is the last step.
43
+ Running it is the caller's job.
44
+
45
+ ## How it works — a 2-stage LLM pipeline
46
+
47
+ ```
48
+ user request
49
+
50
+
51
+ ┌─────────────────────────────┐ full schema metadata
52
+ │ Stage 1: Schema Linking LLM │◄──────────────────────
53
+ │ reduce schema → subset │
54
+ └─────────────────────────────┘
55
+ │ linked schema (tables, columns, joins, entities, filters, rationale)
56
+
57
+ ┌─────────────────────────────┐
58
+ │ Stage 2: SQL Generation LLM │
59
+ │ produce SQL in dialect │
60
+ └─────────────────────────────┘
61
+
62
+
63
+ Text2SQLResult(sql, linked_schema, metadata, explanation)
64
+ ```
65
+
66
+ - **Stage 1 (linking)** takes the request and the *full* schema metadata. It
67
+ reduces the schema to the relevant part and returns structured JSON. Output is
68
+ forced via `response_format` (OpenAI) or tool-calling (Anthropic), with
69
+ strict-JSON parsing and retry as a fallback.
70
+ - **Stage 2 (generation)** takes the request and that reduced subset. It writes
71
+ SQL in the target dialect, plus a short explanation.
72
+ - The two stages can use **different providers and models**. For example a cheap
73
+ general model for linking, a stronger SQL model for generation.
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ pip install text2sql-engine # from PyPI (import name: text2sql)
79
+ pip install "text2sql-engine[all]" # + openai and anthropic SDKs
80
+ ```
81
+
82
+ The PyPI name is `text2sql-engine`. The import name is `text2sql`
83
+ (`import text2sql`). Different names on purpose, since `text2sql` was taken.
84
+
85
+ From a checkout of this repo:
86
+
87
+ ```bash
88
+ pip install -e . # core library
89
+ pip install -e ".[all]" # + openai and anthropic SDKs
90
+ pip install -e ".[dev]" # + pytest
91
+ ```
92
+
93
+ The provider SDKs (`openai`, `anthropic`) are imported lazily. So the library
94
+ imports, and the tests run, without them installed.
95
+
96
+ ## Quick start
97
+
98
+ ```python
99
+ from text2sql import Text2SQL
100
+
101
+ engine = Text2SQL.from_config() # reads .env + config.toml
102
+ result = engine.run("get me the top 5 best-selling products last month")
103
+
104
+ print(result.sql) # the generated SQL string
105
+ print(result.linked_schema) # Stage 1 output (reduced schema)
106
+ print(result.metadata) # models, tokens, latency, attempts
107
+ ```
108
+
109
+ 1. Copy `.env.example` to `.env`. Fill in provider selection and API keys.
110
+ 2. Adjust `config.toml` for behavior (dialect, sampling, retries).
111
+ 3. Point `SCHEMA_PATH` at your metadata file. See `examples/schema.yaml`.
112
+
113
+ ## Configuration — two separate layers
114
+
115
+ Config is split by concern. **Secrets, paths, and provider/model *selection* go
116
+ in `.env`. Everything tunable about *behavior* goes in `config.toml`.** One typed
117
+ layer (`text2sql.config.Settings`) loads both. It fails fast with a clear error
118
+ if a required `.env` variable is missing.
119
+
120
+ ### `.env` — secrets, paths, provider & model selection
121
+
122
+ | Variable | Required | Description |
123
+ |----------|----------|-------------|
124
+ | `SCHEMA_PATH` | yes | Path to the schema file (`.json`, `.yaml`, `.yml`). |
125
+ | `PROMPT_DIR` | no | Directory with prompt templates (`linking.txt`, `generation.txt`). If unset, the templates **packaged inside the library** are used. So it works after pip install, from any working directory. |
126
+ | `CONFIG_PATH` | no | Override the `config.toml` location. Defaults to `./config.toml`. |
127
+ | `LINKING_PROVIDER` | yes | Provider for Stage 1. One of the registered names: `openai`, `anthropic`. |
128
+ | `LINKING_MODEL` | yes | Model id for Stage 1 (schema linking). |
129
+ | `LINKING_BASE_URL` | no | Endpoint override for Stage 1 (for OpenAI-compatible gateways). |
130
+ | `SQL_PROVIDER` | yes | Provider for Stage 2. |
131
+ | `SQL_MODEL` | yes | Model id for Stage 2 (SQL generation). |
132
+ | `SQL_BASE_URL` | no | Endpoint override for Stage 2. |
133
+ | `OPENAI_API_KEY` | if used | API key. Needed only if a stage uses provider `openai`. |
134
+ | `ANTHROPIC_API_KEY` | if used | API key. Needed only if a stage uses provider `anthropic`. |
135
+
136
+ Provider, model, and `base_url` are picked **per stage**, independently.
137
+
138
+ ### `config.toml` — behavior
139
+
140
+ No magic numbers in code. Every tunable is here.
141
+
142
+ #### `[general]`
143
+
144
+ | Key | Type | Default | Description |
145
+ |-----|------|---------|-------------|
146
+ | `sql_dialect` | string | `postgres` | Target dialect (e.g. `postgres`, `mysql`, `sqlite`). Passed to the prompts. |
147
+ | `log_level` | string | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR`. |
148
+ | `strict_json` | bool | `true` | `true`: parse LLM JSON strictly. `false`: tolerate fences / extra prose. |
149
+
150
+ #### `[linking]` — Stage 1
151
+
152
+ | Key | Type | Default | Description |
153
+ |-----|------|---------|-------------|
154
+ | `temperature` | float | `0.0` | Sampling temperature. |
155
+ | `top_p` | float | `1.0` | Nucleus-sampling cutoff. |
156
+ | `max_tokens` | int | `1024` | Max tokens for the linking response. |
157
+ | `prompt_template` | string | `linking.txt` | Template file, looked up in `PROMPT_DIR`. |
158
+ | `max_tables` | int | `8` | Max tables linking may return. |
159
+ | `timeout_seconds` | float | `60` | Per-request timeout. |
160
+
161
+ #### `[generation]` — Stage 2
162
+
163
+ | Key | Type | Default | Description |
164
+ |-----|------|---------|-------------|
165
+ | `temperature` | float | `0.0` | Sampling temperature. |
166
+ | `top_p` | float | `1.0` | Nucleus-sampling cutoff. |
167
+ | `max_tokens` | int | `1024` | Max tokens for the SQL response. |
168
+ | `prompt_template` | string | `generation.txt` | Template file, looked up in `PROMPT_DIR`. |
169
+ | `timeout_seconds` | float | `60` | Per-request timeout. |
170
+
171
+ #### `[retry]` — shared by both stages
172
+
173
+ | Key | Type | Default | Description |
174
+ |-----|------|---------|-------------|
175
+ | `max_attempts` | int | `3` | Attempts per LLM call before failing. Retries on JSON-parse and transient provider errors. |
176
+ | `backoff_seconds` | float | `1.0` | First delay between retries. |
177
+ | `backoff_factor` | float | `2.0` | Delay is multiplied by this each retry. |
178
+
179
+ ## Schema metadata format
180
+
181
+ The schema is **never hardcoded**. It is loaded from an external file through a
182
+ `SchemaProvider`. `examples/schema.yaml` (and the same `examples/schema.json`)
183
+ show the full format: a small e-commerce database with `customers`,
184
+ `categories`, `products`, `orders`, and `order_items`. Each table has a
185
+ description. Each column has a name, type, description, primary-key flag, and
186
+ sample values. Foreign keys are listed. Both JSON and YAML work, picked by
187
+ extension.
188
+
189
+ The example runs out of the box. The tests exercise the pipeline against it with
190
+ mocked LLM calls.
191
+
192
+ ## Extending
193
+
194
+ Everything is swappable via **config + dependency injection**:
195
+
196
+ ```python
197
+ from text2sql import Text2SQL, SchemaProvider, PromptTemplates
198
+ from text2sql.schema import Schema
199
+
200
+ # 1. Custom schema source, e.g. live DB introspection instead of a file.
201
+ class MyIntrospectionProvider(SchemaProvider):
202
+ def load(self) -> Schema:
203
+ ... # build and return a Schema
204
+
205
+ # 2. Inject any part. Anything left None is built from config.
206
+ engine = Text2SQL.from_config(
207
+ schema_provider=MyIntrospectionProvider(),
208
+ prompts=PromptTemplates("/path/to/my/templates"),
209
+ # linking_provider=..., generation_provider=...,
210
+ )
211
+ ```
212
+
213
+ ### Adding a new LLM provider
214
+
215
+ Subclass `LLMProvider`, implement `complete` (and optionally `complete_json` for
216
+ native structured output), and register it. One class, one decorator:
217
+
218
+ ```python
219
+ from text2sql import LLMProvider, register_provider
220
+ from text2sql.types import LLMResponse
221
+
222
+ @register_provider("myprovider")
223
+ class MyProvider(LLMProvider):
224
+ def complete(self, *, system, user, temperature, top_p, max_tokens) -> LLMResponse:
225
+ ...
226
+ ```
227
+
228
+ Then set `LINKING_PROVIDER=myprovider` (or `SQL_PROVIDER`) in `.env`.
229
+
230
+ ### Prompts
231
+
232
+ Prompt templates are plain, editable text files in `PROMPT_DIR`. Each has a
233
+ `SYSTEM:` and a `USER:` section with `{placeholder}` substitution. Edit them
234
+ without touching code.
235
+
236
+ ## Result object
237
+
238
+ `engine.run(...)` returns a `Text2SQLResult`:
239
+
240
+ | Field | Description |
241
+ |-------|-------------|
242
+ | `sql` | The generated SQL string. The deliverable. |
243
+ | `explanation` | Short explanation from Stage 2. |
244
+ | `linked_schema` | Stage 1 output: `tables`, `columns`, `joins`, `entities`, `filters`, `rationale`. |
245
+ | `metadata` | `RunMetadata`: per-stage provider/model, token usage, latency, attempts. Plus `total_usage` and `total_latency_seconds`. |
246
+ | `request` | The original request. |
247
+
248
+ ## Error handling
249
+
250
+ Every error subclasses `Text2SQLError`:
251
+
252
+ - `ConfigError` — missing/invalid `.env` var or `config.toml`.
253
+ - `SchemaError` — schema file missing or invalid.
254
+ - `ProviderError` — provider build or API call failed.
255
+ - `StructuredOutputError` — output not parseable as JSON after all retries.
256
+ - `EmptyLinkingError` — Stage 1 matched no table/column.
257
+
258
+ Uses stdlib `logging` throughout, never `print`. Secrets are never logged.
259
+
260
+ ## Try it end to end
261
+
262
+ With a real provider and key set in `.env`:
263
+
264
+ ```bash
265
+ python examples/run_example.py "top 5 best-selling products last month"
266
+ ```
267
+
268
+ Makes real LLM calls for both stages. Prints the linked schema, the SQL, and the
269
+ metadata. Never connects to a database.
270
+
271
+ ## Development
272
+
273
+ ```bash
274
+ pip install -e ".[dev]"
275
+ pytest
276
+ ```
277
+
278
+ Tests mock all LLM calls (no network) and run on `examples/schema.yaml`.
279
+
280
+ ## Project layout
281
+
282
+ ```
283
+ text2sql/
284
+ config.py .env + config.toml loading, typed settings
285
+ types.py result dataclasses
286
+ errors.py exceptions
287
+ logging_utils.py logging setup
288
+ schema/ SchemaProvider, file loader, models, serializer
289
+ providers/ base + registry + openai + anthropic
290
+ prompts/ editable linking.txt / generation.txt templates
291
+ pipeline/ linking (Stage 1), generation (Stage 2), orchestrator
292
+ examples/
293
+ schema.yaml / schema.json sample metadata "spec"
294
+ run_example.py runnable end-to-end example (real LLM call)
295
+ config.toml behavioral parameters
296
+ .env.example secrets / paths / model selection template
297
+ tests/ pipeline, schema, config, and prompt tests
298
+ .github/workflows/ci.yml GitHub Actions: pytest on 3.11 and 3.12
299
+ LICENSE MIT
300
+ ```
301
+
302
+ ## License
303
+
304
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,29 @@
1
+ text2sql/__init__.py,sha256=EUP3cVW8vLecps3wqmPqqr6Apaht2tD9QsfdjP5-CQM,1442
2
+ text2sql/config.py,sha256=jCpdUogpzRmkL5kN6CPqYXhUNhRA7EdaCFlCY65QnLA,7709
3
+ text2sql/errors.py,sha256=Y5ORy7g_UsFvDJ2KorB2JFvTyOBqmrPv9MWc8Cl9MI8,1052
4
+ text2sql/logging_utils.py,sha256=hiEH1SDqP16kctUj4uPP0tbXdrCO9AlRcdS-mHYDg5s,1633
5
+ text2sql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ text2sql/types.py,sha256=MxcdHP7Gnftk1yKdcBQKaVVyeqRnBu5kxbhSZ2xJJ80,3532
7
+ text2sql/pipeline/__init__.py,sha256=rjEOi4U9C-SKP15cyKPdvG_EZBOW0VW01LouS3PJVdY,245
8
+ text2sql/pipeline/generation.py,sha256=LpnsKmSgu4Gfg-nHCCk6akg7ToI-G9Vk0LaVRn9WK5Y,3635
9
+ text2sql/pipeline/json_utils.py,sha256=92viA3xyw_GMF_nKdjSPgAyQ8iBUZgnyNRAoyWC5ZlE,3145
10
+ text2sql/pipeline/linking.py,sha256=U28LOcWJn3cItwAsv2fG4fYv9KcJ80XmP1Fi8nNx4qc,6966
11
+ text2sql/pipeline/pipeline.py,sha256=TE0cHSEJyeY43P89HsQDbnPGSfgRQmtw7KZAq-Yjj1U,5675
12
+ text2sql/prompts/__init__.py,sha256=HfeflfAGsZl3xHnNrmklTP6K_8EKxX6vWJrayq6QuEQ,3315
13
+ text2sql/prompts/generation.txt,sha256=r4125WCr7gsJIzTa5wZTAmbTyn5WvP3QrfGf4CWNP_w,849
14
+ text2sql/prompts/linking.txt,sha256=nLPSkaq3PiWiJ7wXLeD0BvK_-rR3hhc_tLhZ-daPnGY,889
15
+ text2sql/providers/__init__.py,sha256=R5a-YKtyaUFpkVJGWrmhDGyRHeh84gA3F7nEH57dSGo,345
16
+ text2sql/providers/anthropic_provider.py,sha256=Zhh8zM6EfHqkjTgNmhYKdZLHQ69b0Pu2-5WbCW2rD6s,4342
17
+ text2sql/providers/base.py,sha256=lqy_-Z923EfuKvOY247lyifdE5HjN0o52tyi9M2Ufns,3655
18
+ text2sql/providers/openai_provider.py,sha256=EoIkCB-RnFFHzyBMAY2eglzu7WLrVF5i9q8MhcqEyG0,4370
19
+ text2sql/providers/registry.py,sha256=epe7OLm07_jhsspItpauupTy3UEyuUheZ20VYQcq1Ec,1147
20
+ text2sql/schema/__init__.py,sha256=AvXHTwCDiOolg-_btcLReFDWupztDswEsFkz_1EGOmo,395
21
+ text2sql/schema/file_provider.py,sha256=Nv9x2-Eh9mXISk5XvUQaLfagth2s3LbX5F7jWp-oZqw,4918
22
+ text2sql/schema/models.py,sha256=yX5zdKbTuy-g-nkwT0v-0HUTK81jBRoabV-OC-kD-JI,2263
23
+ text2sql/schema/provider.py,sha256=JPMRsjRgEB4RdQR_pFwbP2LwLIXZhQVWSQPoYzaXC7s,798
24
+ text2sql/schema/serialize.py,sha256=_2MeA1IwDJ51-69PXyqXBSFZSyzovbqJkRIMpekkfJA,1833
25
+ text2sql_engine-0.1.0.dist-info/licenses/LICENSE,sha256=dzrVwSmgUgCDYwDn21Job7Yb4huyHjC74evyzsHXas8,1078
26
+ text2sql_engine-0.1.0.dist-info/METADATA,sha256=Cni4NycxDnoS3HgP5eYTRiUXgOmnLhSYBI27LTBm08U,12302
27
+ text2sql_engine-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
28
+ text2sql_engine-0.1.0.dist-info/top_level.txt,sha256=ZONWO1r8wsWpyHhF5qPzAjnsNoCEhwZ2Z-M_V8nKALc,9
29
+ text2sql_engine-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 text2sql contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ text2sql