Skip to content

Commit 2c4e146

Browse files
committed
fix(audits): accept RFC 9562 UUID versions 6-8 in valid_uuid
The valid_uuid audit only allowed version digits 1-5, so well-formed UUIDv6, UUIDv7 and UUIDv8 values (RFC 9562) were reported as invalid. Widen the version digit to 1-8 and update the documented pattern. Signed-off-by: Dhruv Gupta <todhruvg@gmail.com>
1 parent f6527ff commit 2c4e146

3 files changed

Lines changed: 40 additions & 2 deletions

File tree

‎docs/concepts/audits.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ MODEL (
477477
#### valid_uuid, valid_uuid_non_blocking
478478
Ensures that all non-NULL rows of a column contain a string with the UUID structure.
479479

480-
UUID structure determined by matching regular expression `'^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'`.
480+
UUID structure determined by matching regular expression `'^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'`.
481481

482482
This example asserts that all `uuid` values have the UUID structure:
483483

‎sqlmesh/core/audit/builtin.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def create_non_blocking_copy(audit: Audit) -> Audit:
297297
SELECT *
298298
FROM @this_model
299299
WHERE @AND(
300-
NOT REGEXP_LIKE(LOWER(@column), '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
300+
NOT REGEXP_LIKE(LOWER(@column), '^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'),
301301
@condition,
302302
)
303303

‎tests/core/test_audit.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,44 @@ def test_not_constant_audit(model: Model):
852852
)
853853

854854

855+
def test_valid_uuid_audit(model: Model):
856+
import duckdb
857+
858+
rendered_query = model.render_audit_query(builtin.valid_uuid_audit, column=exp.column("a"))
859+
assert (
860+
rendered_query.sql()
861+
== """SELECT * FROM (SELECT * FROM "db"."test_model" AS "test_model" WHERE "ds" BETWEEN '1970-01-01' AND '1970-01-01') AS "_0" WHERE NOT REGEXP_LIKE(LOWER("a"), '^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') AND TRUE"""
862+
)
863+
864+
valid = [
865+
"6ba7b810-9dad-11d1-80b4-00c04fd430c8", # v1
866+
"000003e8-2363-21ef-b200-325096b39f47", # v2
867+
"5df41881-3aed-3515-88a7-2f4a814cf09e", # v3
868+
"919108F7-52D1-4320-9BAC-F847DB4148A8", # v4, upper case
869+
"2ed6657d-e927-568b-95e1-2665a8aea6a2", # v5
870+
"1ec9414c-232a-6b00-b3c8-9f6bdeced846", # v6
871+
"017f22e2-79b0-7cc3-98c4-dc0c0c07398f", # v7
872+
"2489e9ad-2ee2-8e00-8ec9-32d5f69181c0", # v8
873+
]
874+
invalid = [
875+
"017f22e2-79b0-9cc3-98c4-dc0c0c07398f", # unknown version
876+
"017f22e2-79b0-7cc3-c8c4-dc0c0c07398f", # non-RFC variant
877+
"017f22e279b07cc398c4dc0c0c07398f", # no hyphens
878+
"not-a-uuid",
879+
]
880+
881+
connection = duckdb.connect()
882+
connection.execute("CREATE SCHEMA db")
883+
connection.execute("CREATE TABLE db.test_model (a TEXT, b INT, ds TEXT)")
884+
connection.executemany(
885+
"INSERT INTO db.test_model VALUES (?, 1, '1970-01-01')",
886+
[[value] for value in valid + invalid + [None]],
887+
)
888+
889+
failing_rows = connection.execute(rendered_query.sql(dialect="duckdb")).fetchall()
890+
assert sorted(row[0] for row in failing_rows) == sorted(invalid)
891+
892+
855893
def test_condition_with_macro_var(model: Model):
856894
rendered_query = model.render_audit_query(
857895
builtin.not_null_audit,

0 commit comments

Comments
 (0)