You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/custom_materializations.md
+97Lines changed: 97 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -157,6 +157,103 @@ class CustomFullMaterialization(CustomMaterialization):
157
157
# Example existing materialization for look and feel: https://github.com/TobikoData/sqlmesh/blob/main/sqlmesh/core/snapshot/evaluator.py
158
158
```
159
159
160
+
## Extending `CustomKind`
161
+
162
+
!!! warning
163
+
This is even lower level usage that contains a bunch of extra complexity and relies on knowledge of the SQLMesh internals.
164
+
If you dont need this level of complexity, stick with the method described above.
165
+
166
+
In many cases, the above usage of a custom materialization will suffice.
167
+
168
+
However, you may still want tighter integration with SQLMesh's internals:
169
+
170
+
- You may want more control over what is considered a metadata change vs a data change
171
+
- You may want to validate custom properties are correct before any database connections are made
172
+
- You may want to leverage existing functionality of SQLMesh that relies on specific properties being present
173
+
174
+
In this case, you can provide a subclass of `CustomKind` for SQLMesh to use instead of `CustomKind` itself.
175
+
During project load, SQLMesh will instantiate your *subclass* instead of `CustomKind`.
176
+
177
+
This allows you to run custom validators at load time rather than having to perform extra validation when `insert()` is invoked on your `CustomMaterialization`.
178
+
179
+
This approach also allows you set "top-level" properties directly in the `kind (...)` block rather than nesting them under `materialization_properties`.
180
+
181
+
To extend `CustomKind`, first you define a subclass like so:
182
+
183
+
```python linenums="1" hl_lines="7"
184
+
from sqlmesh import CustomKind
185
+
from pydantic import field_validator, ValidationInfo
186
+
from sqlmesh.utils.pydantic import list_of_fields_validator
In this example, we define a field called `primary_key` that takes a list of fields. Notice that the field validation is just a simple Pydantic `@field_validator` with the [exact same usage](https://github.com/TobikoData/sqlmesh/blob/ade5f7245950822f3cfe5a68a0c243f91ceca600/sqlmesh/core/model/kind.py#L470) as the standard SQLMesh model kinds.
200
+
201
+
To use it within a model, we can do something like:
202
+
203
+
```sql linenums="1" hl_lines="5"
204
+
MODEL (
205
+
name my_db.my_model,
206
+
kind CUSTOM (
207
+
materialization 'my_custom_full',
208
+
primary_key (col1, col2)
209
+
)
210
+
);
211
+
```
212
+
213
+
Notice that the `primary_key` field we declared is top-level within the `kind` block instead of being nested under `materialization_properties`.
214
+
215
+
To indicate to SQLMesh that it should use this subclass, specify it as a generic type parameter on your custom materialization class like so:
When SQLMesh loads your custom materialization, it will inspect the Python type signature for generic parameters that are subclasses of `CustomKind`. If it finds one, it will instantiate your subclass when building `model.kind` instead of using the default `CustomKind` class.
238
+
239
+
In this example, this means that:
240
+
241
+
- Validation for `primary_key` happens at load time instead of evaluation time.
242
+
- When your custom materialization is called to load data into tables, `model.kind` will resolve to your custom kind object so you can access the extra properties you defined without first needing to validate them / coerce them to a usable type.
243
+
244
+
### Data vs Metadata changes
245
+
246
+
Subclasses of `CustomKind` that add extra properties can also decide if they are data properties (changes may trigger the creation of new snapshots) or metadata properties (changes just update metadata about the model).
247
+
248
+
They can also decide if they are relevant for text diffing when SQLMesh detects changes to a model.
249
+
250
+
You can opt in to SQLMesh's change tracking by overriding the following methods:
251
+
252
+
- If changing the property should change the data fingerprint, add it to [data_hash_values()](https://github.com/TobikoData/sqlmesh/blob/ade5f7245950822f3cfe5a68a0c243f91ceca600/sqlmesh/core/model/kind.py#L858)
253
+
- If changing the property should change the metadata fingerprint, add it to [metadata_hash_values()](https://github.com/TobikoData/sqlmesh/blob/ade5f7245950822f3cfe5a68a0c243f91ceca600/sqlmesh/core/model/kind.py#L867)
254
+
- If the property should show up in context diffs, add it to [to_expression()](https://github.com/TobikoData/sqlmesh/blob/ade5f7245950822f3cfe5a68a0c243f91ceca600/sqlmesh/core/model/kind.py#L880)
0 commit comments