pytrilogy 0.3.138__cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.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 (182) hide show
  1. LICENSE.md +19 -0
  2. _preql_import_resolver/__init__.py +5 -0
  3. _preql_import_resolver/_preql_import_resolver.cpython-311-x86_64-linux-gnu.so +0 -0
  4. pytrilogy-0.3.138.dist-info/METADATA +525 -0
  5. pytrilogy-0.3.138.dist-info/RECORD +182 -0
  6. pytrilogy-0.3.138.dist-info/WHEEL +5 -0
  7. pytrilogy-0.3.138.dist-info/entry_points.txt +2 -0
  8. pytrilogy-0.3.138.dist-info/licenses/LICENSE.md +19 -0
  9. trilogy/__init__.py +9 -0
  10. trilogy/ai/README.md +10 -0
  11. trilogy/ai/__init__.py +19 -0
  12. trilogy/ai/constants.py +92 -0
  13. trilogy/ai/conversation.py +107 -0
  14. trilogy/ai/enums.py +7 -0
  15. trilogy/ai/execute.py +50 -0
  16. trilogy/ai/models.py +34 -0
  17. trilogy/ai/prompts.py +87 -0
  18. trilogy/ai/providers/__init__.py +0 -0
  19. trilogy/ai/providers/anthropic.py +106 -0
  20. trilogy/ai/providers/base.py +24 -0
  21. trilogy/ai/providers/google.py +146 -0
  22. trilogy/ai/providers/openai.py +89 -0
  23. trilogy/ai/providers/utils.py +68 -0
  24. trilogy/authoring/README.md +3 -0
  25. trilogy/authoring/__init__.py +143 -0
  26. trilogy/constants.py +113 -0
  27. trilogy/core/README.md +52 -0
  28. trilogy/core/__init__.py +0 -0
  29. trilogy/core/constants.py +6 -0
  30. trilogy/core/enums.py +443 -0
  31. trilogy/core/env_processor.py +120 -0
  32. trilogy/core/environment_helpers.py +320 -0
  33. trilogy/core/ergonomics.py +193 -0
  34. trilogy/core/exceptions.py +123 -0
  35. trilogy/core/functions.py +1227 -0
  36. trilogy/core/graph_models.py +139 -0
  37. trilogy/core/internal.py +85 -0
  38. trilogy/core/models/__init__.py +0 -0
  39. trilogy/core/models/author.py +2672 -0
  40. trilogy/core/models/build.py +2521 -0
  41. trilogy/core/models/build_environment.py +180 -0
  42. trilogy/core/models/core.py +494 -0
  43. trilogy/core/models/datasource.py +322 -0
  44. trilogy/core/models/environment.py +748 -0
  45. trilogy/core/models/execute.py +1177 -0
  46. trilogy/core/optimization.py +251 -0
  47. trilogy/core/optimizations/__init__.py +12 -0
  48. trilogy/core/optimizations/base_optimization.py +17 -0
  49. trilogy/core/optimizations/hide_unused_concept.py +47 -0
  50. trilogy/core/optimizations/inline_datasource.py +102 -0
  51. trilogy/core/optimizations/predicate_pushdown.py +245 -0
  52. trilogy/core/processing/README.md +94 -0
  53. trilogy/core/processing/READMEv2.md +121 -0
  54. trilogy/core/processing/VIRTUAL_UNNEST.md +30 -0
  55. trilogy/core/processing/__init__.py +0 -0
  56. trilogy/core/processing/concept_strategies_v3.py +508 -0
  57. trilogy/core/processing/constants.py +15 -0
  58. trilogy/core/processing/discovery_node_factory.py +451 -0
  59. trilogy/core/processing/discovery_utility.py +517 -0
  60. trilogy/core/processing/discovery_validation.py +167 -0
  61. trilogy/core/processing/graph_utils.py +43 -0
  62. trilogy/core/processing/node_generators/README.md +9 -0
  63. trilogy/core/processing/node_generators/__init__.py +31 -0
  64. trilogy/core/processing/node_generators/basic_node.py +160 -0
  65. trilogy/core/processing/node_generators/common.py +268 -0
  66. trilogy/core/processing/node_generators/constant_node.py +38 -0
  67. trilogy/core/processing/node_generators/filter_node.py +315 -0
  68. trilogy/core/processing/node_generators/group_node.py +213 -0
  69. trilogy/core/processing/node_generators/group_to_node.py +117 -0
  70. trilogy/core/processing/node_generators/multiselect_node.py +205 -0
  71. trilogy/core/processing/node_generators/node_merge_node.py +653 -0
  72. trilogy/core/processing/node_generators/recursive_node.py +88 -0
  73. trilogy/core/processing/node_generators/rowset_node.py +165 -0
  74. trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  75. trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +261 -0
  76. trilogy/core/processing/node_generators/select_merge_node.py +748 -0
  77. trilogy/core/processing/node_generators/select_node.py +95 -0
  78. trilogy/core/processing/node_generators/synonym_node.py +98 -0
  79. trilogy/core/processing/node_generators/union_node.py +91 -0
  80. trilogy/core/processing/node_generators/unnest_node.py +182 -0
  81. trilogy/core/processing/node_generators/window_node.py +201 -0
  82. trilogy/core/processing/nodes/README.md +28 -0
  83. trilogy/core/processing/nodes/__init__.py +179 -0
  84. trilogy/core/processing/nodes/base_node.py +519 -0
  85. trilogy/core/processing/nodes/filter_node.py +75 -0
  86. trilogy/core/processing/nodes/group_node.py +194 -0
  87. trilogy/core/processing/nodes/merge_node.py +420 -0
  88. trilogy/core/processing/nodes/recursive_node.py +46 -0
  89. trilogy/core/processing/nodes/select_node_v2.py +242 -0
  90. trilogy/core/processing/nodes/union_node.py +53 -0
  91. trilogy/core/processing/nodes/unnest_node.py +62 -0
  92. trilogy/core/processing/nodes/window_node.py +56 -0
  93. trilogy/core/processing/utility.py +823 -0
  94. trilogy/core/query_processor.py +596 -0
  95. trilogy/core/statements/README.md +35 -0
  96. trilogy/core/statements/__init__.py +0 -0
  97. trilogy/core/statements/author.py +536 -0
  98. trilogy/core/statements/build.py +0 -0
  99. trilogy/core/statements/common.py +20 -0
  100. trilogy/core/statements/execute.py +155 -0
  101. trilogy/core/table_processor.py +66 -0
  102. trilogy/core/utility.py +8 -0
  103. trilogy/core/validation/README.md +46 -0
  104. trilogy/core/validation/__init__.py +0 -0
  105. trilogy/core/validation/common.py +161 -0
  106. trilogy/core/validation/concept.py +146 -0
  107. trilogy/core/validation/datasource.py +227 -0
  108. trilogy/core/validation/environment.py +73 -0
  109. trilogy/core/validation/fix.py +106 -0
  110. trilogy/dialect/__init__.py +32 -0
  111. trilogy/dialect/base.py +1359 -0
  112. trilogy/dialect/bigquery.py +256 -0
  113. trilogy/dialect/common.py +147 -0
  114. trilogy/dialect/config.py +144 -0
  115. trilogy/dialect/dataframe.py +50 -0
  116. trilogy/dialect/duckdb.py +177 -0
  117. trilogy/dialect/enums.py +147 -0
  118. trilogy/dialect/metadata.py +173 -0
  119. trilogy/dialect/mock.py +190 -0
  120. trilogy/dialect/postgres.py +91 -0
  121. trilogy/dialect/presto.py +104 -0
  122. trilogy/dialect/results.py +89 -0
  123. trilogy/dialect/snowflake.py +90 -0
  124. trilogy/dialect/sql_server.py +92 -0
  125. trilogy/engine.py +48 -0
  126. trilogy/execution/config.py +75 -0
  127. trilogy/executor.py +568 -0
  128. trilogy/hooks/__init__.py +4 -0
  129. trilogy/hooks/base_hook.py +40 -0
  130. trilogy/hooks/graph_hook.py +139 -0
  131. trilogy/hooks/query_debugger.py +166 -0
  132. trilogy/metadata/__init__.py +0 -0
  133. trilogy/parser.py +10 -0
  134. trilogy/parsing/README.md +21 -0
  135. trilogy/parsing/__init__.py +0 -0
  136. trilogy/parsing/common.py +1069 -0
  137. trilogy/parsing/config.py +5 -0
  138. trilogy/parsing/exceptions.py +8 -0
  139. trilogy/parsing/helpers.py +1 -0
  140. trilogy/parsing/parse_engine.py +2813 -0
  141. trilogy/parsing/render.py +750 -0
  142. trilogy/parsing/trilogy.lark +540 -0
  143. trilogy/py.typed +0 -0
  144. trilogy/render.py +42 -0
  145. trilogy/scripts/README.md +7 -0
  146. trilogy/scripts/__init__.py +0 -0
  147. trilogy/scripts/dependency/Cargo.lock +617 -0
  148. trilogy/scripts/dependency/Cargo.toml +39 -0
  149. trilogy/scripts/dependency/README.md +131 -0
  150. trilogy/scripts/dependency/build.sh +25 -0
  151. trilogy/scripts/dependency/src/directory_resolver.rs +162 -0
  152. trilogy/scripts/dependency/src/lib.rs +16 -0
  153. trilogy/scripts/dependency/src/main.rs +770 -0
  154. trilogy/scripts/dependency/src/parser.rs +435 -0
  155. trilogy/scripts/dependency/src/preql.pest +208 -0
  156. trilogy/scripts/dependency/src/python_bindings.rs +289 -0
  157. trilogy/scripts/dependency/src/resolver.rs +716 -0
  158. trilogy/scripts/dependency/tests/base.preql +3 -0
  159. trilogy/scripts/dependency/tests/cli_integration.rs +377 -0
  160. trilogy/scripts/dependency/tests/customer.preql +6 -0
  161. trilogy/scripts/dependency/tests/main.preql +9 -0
  162. trilogy/scripts/dependency/tests/orders.preql +7 -0
  163. trilogy/scripts/dependency/tests/test_data/base.preql +9 -0
  164. trilogy/scripts/dependency/tests/test_data/consumer.preql +1 -0
  165. trilogy/scripts/dependency.py +323 -0
  166. trilogy/scripts/display.py +460 -0
  167. trilogy/scripts/environment.py +46 -0
  168. trilogy/scripts/parallel_execution.py +483 -0
  169. trilogy/scripts/single_execution.py +131 -0
  170. trilogy/scripts/trilogy.py +772 -0
  171. trilogy/std/__init__.py +0 -0
  172. trilogy/std/color.preql +3 -0
  173. trilogy/std/date.preql +13 -0
  174. trilogy/std/display.preql +18 -0
  175. trilogy/std/geography.preql +22 -0
  176. trilogy/std/metric.preql +15 -0
  177. trilogy/std/money.preql +67 -0
  178. trilogy/std/net.preql +14 -0
  179. trilogy/std/ranking.preql +7 -0
  180. trilogy/std/report.preql +5 -0
  181. trilogy/std/semantic.preql +6 -0
  182. trilogy/utility.py +34 -0
LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2023
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ from ._preql_import_resolver import *
2
+
3
+ __doc__ = _preql_import_resolver.__doc__
4
+ if hasattr(_preql_import_resolver, "__all__"):
5
+ __all__ = _preql_import_resolver.__all__
@@ -0,0 +1,525 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytrilogy
3
+ Version: 0.3.138
4
+ Classifier: Programming Language :: Python
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3.9
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Requires-Dist: pyodbc ; extra == 'odbc'
12
+ Requires-Dist: psycopg2-binary ; extra == 'postgres'
13
+ Requires-Dist: sqlalchemy-bigquery ; extra == 'bigquery'
14
+ Requires-Dist: snowflake-sqlalchemy ; extra == 'snowflake'
15
+ Requires-Dist: httpx ; extra == 'ai'
16
+ Requires-Dist: rich ; extra == 'cli'
17
+ Provides-Extra: odbc
18
+ Provides-Extra: postgres
19
+ Provides-Extra: bigquery
20
+ Provides-Extra: snowflake
21
+ Provides-Extra: ai
22
+ Provides-Extra: cli
23
+ License-File: LICENSE.md
24
+ Summary: Declarative, typed query language that compiles to SQL.
25
+ Description-Content-Type: text/markdown
26
+ Requires-Dist: lark
27
+ Requires-Dist: jinja2
28
+ Requires-Dist: sqlalchemy<2.0.0
29
+ Requires-Dist: networkx
30
+ Requires-Dist: pydantic
31
+ Requires-Dist: duckdb<1.4.0
32
+ Requires-Dist: pyarrow
33
+ Requires-Dist: duckdb-engine
34
+ Requires-Dist: click
35
+
36
+ # Trilogy
37
+ **SQL with superpowers for analytics**
38
+
39
+ [![Website](https://img.shields.io/badge/INTRO-WEB-orange?)](https://trilogydata.dev/)
40
+ [![Discord](https://img.shields.io/badge/DISCORD-CHAT-red?logo=discord)](https://discord.gg/Z4QSSuqGEd)
41
+ [![PyPI version](https://badge.fury.io/py/pytrilogy.svg)](https://badge.fury.io/py/pytrilogy)
42
+
43
+ The Trilogy language is an experiment in better SQL for analytics - a streamlined SQL that replaces tables/joins with a lightweight semantic binding layer and provides easy reuse and composability. It compiles to SQL - making it easy to debug or integrate into existing workflows - and can be run against any supported SQL backend.
44
+
45
+ [pytrilogy](https://github.com/trilogy-data/pytrilogy) is the reference implementation, written in Python.
46
+
47
+ ## What Trilogy Gives You
48
+
49
+ - **Speed** - write faster, with concise, powerful syntax
50
+ - **Efficiency** - write less SQL, and reuse what you do
51
+ - **Fearless refactoring** - change models without breaking queries
52
+ - **Testability** - built-in testing patterns with query fixtures
53
+ - **Easy to use** - for humans and LLMs alike
54
+
55
+ Trilogy is especially powerful for data consumption, providing a rich metadata layer that makes creating, interpreting, and visualizing queries easy and expressive.
56
+
57
+
58
+ We recommend starting with the studio to explore Trilogy. For integration, `pytrilogy` can be run locally to parse and execute trilogy model [.preql] files using the `trilogy` CLI tool, or can be run in python by importing the `trilogy` package.
59
+
60
+
61
+ ## Quick Start
62
+
63
+ > [!TIP]
64
+ > **Try it now:** [Open-source studio](https://trilogydata.dev/trilogy-studio-core/) | [Interactive demo](https://trilogydata.dev/demo/) | [Documentation](https://trilogydata.dev/)
65
+
66
+ **Install**
67
+ ```bash
68
+ pip install pytrilogy
69
+ ```
70
+
71
+ **Save in hello.preql**
72
+ ```sql
73
+ const prime <- unnest([2, 3, 5, 7, 11, 13, 17, 19, 23, 29]);
74
+
75
+ def cube_plus_one(x) -> (x * x * x + 1);
76
+
77
+ WHERE
78
+ prime_cubed_plus_one % 7 = 0
79
+ SELECT
80
+ prime,
81
+ @cube_plus_one(prime) as prime_cubed_plus_one
82
+ ORDER BY
83
+ prime asc
84
+ LIMIT 10;
85
+ ```
86
+
87
+ **Run it in DuckDB**
88
+ ```bash
89
+ trilogy run hello.preql duckdb
90
+ ```
91
+
92
+ ## Trilogy is Easy to Write
93
+ For humans *and* AI. Enjoy flexible, one-shot query generation without any DB access or security risks.
94
+
95
+ (full code in the python API section.)
96
+
97
+ ```python
98
+ query = text_to_query(
99
+ executor.environment,
100
+ "number of flights by month in 2005",
101
+ Provider.OPENAI,
102
+ "gpt-5-chat-latest",
103
+ api_key,
104
+ )
105
+
106
+ # get a ready to run query
107
+ print(query)
108
+ # typical output
109
+ '''where local.dep_time.year = 2020
110
+ select
111
+ local.dep_time.month,
112
+ count(local.id2) as number_of_flights
113
+ order by
114
+ local.dep_time.month asc;'''
115
+ ```
116
+
117
+ ## Goals
118
+
119
+ Versus SQL, Trilogy aims to:
120
+
121
+ **Keep:**
122
+ - Correctness
123
+ - Accessibility
124
+
125
+ **Improve:**
126
+ - Simplicity
127
+ - Refactoring/maintainability
128
+ - Reusability/composability
129
+ - Expressivness
130
+
131
+ **Maintain:**
132
+ - Acceptable performance
133
+
134
+ ## Backend Support
135
+
136
+ | Backend | Status | Notes |
137
+ |---------|--------|-------|
138
+ | **BigQuery** | Core | Full support |
139
+ | **DuckDB** | Core | Full support |
140
+ | **Snowflake** | Core | Full support |
141
+ | **SQL Server** | Experimental | Limited testing |
142
+ | **Presto** | Experimental | Limited testing |
143
+
144
+ ## Examples
145
+
146
+ ### Hello World
147
+
148
+ Save the following code in a file named `hello.preql`
149
+
150
+ ```python
151
+ # semantic model is abstract from data
152
+
153
+ type word string; # types can be used to provide expressive metadata tags that propagate through dataflow
154
+
155
+ key sentence_id int;
156
+ property sentence_id.word_one string::word; # comments after a definition
157
+ property sentence_id.word_two string::word; # are syntactic sugar for adding
158
+ property sentence_id.word_three string::word; # a description to it
159
+
160
+ # comments in other places are just comments
161
+
162
+ # define our datasource to bind the model to data
163
+ # for most work, you can import something already defined
164
+ # testing using query fixtures is a common pattern
165
+ datasource word_one(
166
+ sentence: sentence_id,
167
+ word:word_one
168
+ )
169
+ grain(sentence_id)
170
+ query '''
171
+ select 1 as sentence, 'Hello' as word
172
+ union all
173
+ select 2, 'Bonjour'
174
+ ''';
175
+
176
+ datasource word_two(
177
+ sentence: sentence_id,
178
+ word:word_two
179
+ )
180
+ grain(sentence_id)
181
+ query '''
182
+ select 1 as sentence, 'World' as word
183
+ union all
184
+ select 2 as sentence, 'World'
185
+ ''';
186
+
187
+ datasource word_three(
188
+ sentence: sentence_id,
189
+ word:word_three
190
+ )
191
+ grain(sentence_id)
192
+ query '''
193
+ select 1 as sentence, '!' as word
194
+ union all
195
+ select 2 as sentence, '!'
196
+ ''';
197
+
198
+ def concat_with_space(x,y) -> x || ' ' || y;
199
+
200
+ # an actual select statement
201
+ # joins are automatically resolved between the 3 sources
202
+ with sentences as
203
+ select sentence_id, @concat_with_space(word_one, word_two) || word_three as text;
204
+
205
+ WHERE
206
+ sentences.sentence_id in (1,2)
207
+ SELECT
208
+ sentences.text
209
+ ;
210
+ ```
211
+
212
+ **Run it:**
213
+ ```bash
214
+ trilogy run hello.preql duckdb
215
+ ```
216
+
217
+ ![UI Preview](hello-world.png)
218
+
219
+ ### Python SDK Usage
220
+
221
+ Trilogy can be run directly in python through the core SDK. Trilogy code can be defined and parsed inline or parsed out of files.
222
+
223
+ A BigQuery example, similar to the [BigQuery quickstart](https://cloud.google.com/bigquery/docs/quickstarts/query-public-dataset-console):
224
+
225
+ ```python
226
+ from trilogy import Dialects, Environment
227
+
228
+ environment = Environment()
229
+
230
+ environment.parse('''
231
+ key name string;
232
+ key gender string;
233
+ key state string;
234
+ key year int;
235
+ key yearly_name_count int; int;
236
+
237
+ datasource usa_names(
238
+ name:name,
239
+ number:yearly_name_count,
240
+ year:year,
241
+ gender:gender,
242
+ state:state
243
+ )
244
+ address `bigquery-public-data.usa_names.usa_1910_2013`;
245
+ ''')
246
+
247
+ executor = Dialects.BIGQUERY.default_executor(environment=environment)
248
+
249
+ results = executor.execute_text('''
250
+ WHERE
251
+ name = 'Elvis'
252
+ SELECT
253
+ name,
254
+ sum(yearly_name_count) -> name_count
255
+ ORDER BY
256
+ name_count desc
257
+ LIMIT 10;
258
+ ''')
259
+
260
+ # multiple queries can result from one text batch
261
+ for row in results:
262
+ # get results for first query
263
+ answers = row.fetchall()
264
+ for x in answers:
265
+ print(x)
266
+ ```
267
+
268
+ ### LLM Usage
269
+
270
+ Connect to your favorite provider and generate queries with confidence and high accuracy.
271
+
272
+ ```python
273
+ from trilogy import Environment, Dialects
274
+ from trilogy.ai import Provider, text_to_query
275
+ import os
276
+
277
+ executor = Dialects.DUCK_DB.default_executor(
278
+ environment=Environment(working_path=Path(__file__).parent)
279
+ )
280
+
281
+ api_key = os.environ.get(OPENAI_API_KEY)
282
+ if not api_key:
283
+ raise ValueError("OPENAI_API_KEY required for gpt generation")
284
+ # load a model
285
+ executor.parse_file("flight.preql")
286
+ # create tables in the DB if needed
287
+ executor.execute_file("setup.sql")
288
+ # generate a query
289
+ query = text_to_query(
290
+ executor.environment,
291
+ "number of flights by month in 2005",
292
+ Provider.OPENAI,
293
+ "gpt-5-chat-latest",
294
+ api_key,
295
+ )
296
+
297
+ # print the generated trilogy query
298
+ print(query)
299
+ # run it
300
+ results = executor.execute_text(query)[-1].fetchall()
301
+ assert len(results) == 12
302
+
303
+ for row in results:
304
+ # all monthly flights are between 5000 and 7000
305
+ assert row[1] > 5000 and row[1] < 7000, row
306
+
307
+ ```
308
+
309
+ ### CLI Usage
310
+
311
+ Trilogy can be run through a CLI tool, also named 'trilogy'.
312
+
313
+ **Basic syntax:**
314
+ ```bash
315
+ trilogy run <cmd or path to trilogy file> <dialect>
316
+ ```
317
+
318
+ **With backend options:**
319
+ ```bash
320
+ trilogy run "key x int; datasource test_source(i:x) grain(x) address test; select x;" duckdb --path <path/to/database>
321
+ ```
322
+
323
+ **Format code:**
324
+ ```bash
325
+ trilogy fmt <path to trilogy file>
326
+ ```
327
+
328
+ #### Backend Configuration
329
+
330
+ **BigQuery:**
331
+ - Uses applicationdefault authentication (TODO: support arbitrary credential paths)
332
+ - In Python, you can pass a custom client
333
+
334
+ **DuckDB:**
335
+ - `--path` - Optional database file path
336
+
337
+ **Postgres:**
338
+ - `--host` - Database host
339
+ - `--port` - Database port
340
+ - `--username` - Username
341
+ - `--password` - Password
342
+ - `--database` - Database name
343
+
344
+ **Snowflake:**
345
+ - `--account` - Snowflake account
346
+ - `--username` - Username
347
+ - `--password` - Password
348
+
349
+ ## More Resources
350
+
351
+ - [Interactive demo](https://trilogydata.dev/demo/)
352
+ - [Public model repository](https://github.com/trilogydata/trilogy-public-models) - Great place for modeling examples
353
+ - [Full documentation](https://trilogydata.dev/)
354
+
355
+ ## Python API Integration
356
+
357
+ ### Root Imports
358
+
359
+ Are stable and should be sufficient for executing code from Trilogy as text.
360
+
361
+ ```python
362
+ from pytrilogy import Executor, Dialect
363
+ ```
364
+
365
+ ### Authoring Imports
366
+
367
+ Are also stable, and should be used for cases which programatically generate Trilogy statements without text inputs
368
+ or need to process/transform parsed code in more complicated ways.
369
+
370
+ ```python
371
+ from pytrilogy.authoring import Concept, Function, ...
372
+ ```
373
+
374
+ ### Other Imports
375
+
376
+ Are likely to be unstable. Open an issue if you need to take dependencies on other modules outside those two paths.
377
+
378
+ ## MCP/Server
379
+
380
+ Trilogy is straightforward to run as a server/MCP server; the former to generate SQL on demand and integrate into other tools, and MCP
381
+ for full interactive query loops.
382
+
383
+ This makes it easy to integrate Trilogy into existing tools or workflows.
384
+
385
+ You can see examples of both use cases in the trilogy-studio codebase [here](https://github.com/trilogy-data/trilogy-studio-core)
386
+ and install and run an MCP server directly with that codebase.
387
+
388
+ If you're interested in a more fleshed out standalone server or MCP server, please open an issue and we'll prioritize it!
389
+
390
+ ## Trilogy Syntax Reference
391
+
392
+ Not exhaustive - see [documentation](https://trilogydata.dev/) for more details.
393
+
394
+ ### Import
395
+ ```sql
396
+ import [path] as [alias];
397
+ ```
398
+
399
+ ### Concepts
400
+
401
+ **Types:**
402
+ `string | int | float | bool | date | datetime | time | numeric(scale, precision) | timestamp | interval | array<[type]> | map<[type], [type]> | struct<name:[type], name:[type]>`
403
+
404
+ **Key:**
405
+ ```sql
406
+ key [name] [type];
407
+ ```
408
+
409
+ **Property:**
410
+ ```sql
411
+ property [key].[name] [type];
412
+ property x.y int;
413
+
414
+ # or multi-key
415
+ property <[key],[key]>.[name] [type];
416
+ property <x,y>.z int;
417
+ ```
418
+
419
+ **Transformation:**
420
+ ```sql
421
+ auto [name] <- [expression];
422
+ auto x <- y + 1;
423
+ ```
424
+
425
+ ### Datasource
426
+ ```sql
427
+ datasource <name>(
428
+ <column_and_concept_with_same_name>,
429
+ # or a mapping from column to concept
430
+ <column>:<concept>,
431
+ <column>:<concept>,
432
+ )
433
+ grain(<concept>, <concept>)
434
+ address <table>;
435
+
436
+ datasource orders(
437
+ order_id,
438
+ order_date,
439
+ total_rev: point_of_sale_rev,
440
+ customomer_id: customer.id
441
+ )
442
+ grain orders
443
+ address orders;
444
+
445
+ ```
446
+
447
+ ### Queries
448
+
449
+ **Basic SELECT:**
450
+ ```sql
451
+ WHERE
452
+ <concept> = <value>
453
+ SELECT
454
+ <concept>,
455
+ <concept>+1 -> <alias>,
456
+ ...
457
+ HAVING
458
+ <alias> = <value2>
459
+ ORDER BY
460
+ <concept> asc|desc
461
+ ;
462
+ ```
463
+
464
+ **CTEs/Rowsets:**
465
+ ```sql
466
+ with <alias> as
467
+ WHERE
468
+ <concept> = <value>
469
+ select
470
+ <concept>,
471
+ <concept>+1 -> <alias>,
472
+ ...
473
+
474
+ select <alias>.<concept>;
475
+ ```
476
+
477
+ ### Data Operations
478
+
479
+ **Persist to table:**
480
+ ```sql
481
+ persist <alias> as <table_name> from
482
+ <select>;
483
+ ```
484
+
485
+ **Export to file:**
486
+ ```sql
487
+ COPY INTO <TARGET_TYPE> '<target_path>' FROM SELECT
488
+ <concept>, ...
489
+ ORDER BY
490
+ <concept>, ...
491
+ ;
492
+ ```
493
+
494
+ **Show generated SQL:**
495
+ ```sql
496
+ show <select>;
497
+ ```
498
+
499
+ **Validate Model**
500
+ ```sql
501
+ validate all
502
+ validate concepts abc,def...
503
+ validate datasources abc,def...
504
+ ```
505
+
506
+
507
+ ## Contributing
508
+
509
+ Clone repository and install requirements.txt and requirements-test.txt.
510
+
511
+ Please open an issue first to discuss what you would like to change, and then create a PR against that issue.
512
+
513
+ ## Similar Projects
514
+
515
+ Trilogy combines two aspects: a semantic layer and a query language. Examples of both are linked below:
516
+
517
+ **Semantic layers** - tools for defining a metadata layer above SQL/warehouse to enable higher level abstractions:
518
+ - [MetricFlow](https://github.com/dbt-labs/metricflow)
519
+ - [Cube](https://github.com/cube-js/cube)
520
+ - [Zillion](https://github.com/totalhack/zillion)
521
+
522
+ **Better SQL** has been a popular space. We believe Trilogy takes a different approach than the following, but all are worth checking out. Please open PRs/comment for anything missed!
523
+ - [Malloy](https://github.com/malloydata/malloy)
524
+ - [Preql](https://github.com/erezsh/Preql)
525
+ - [PRQL](https://github.com/PRQL/prql)