|
10 | 10 | import logging |
11 | 11 | import os |
12 | 12 | from collections.abc import Generator |
| 13 | +from pathlib import Path |
13 | 14 | from typing import Optional |
14 | 15 |
|
15 | 16 | import pytest |
16 | 17 | from flask import Flask |
17 | 18 | from flask.testing import FlaskClient |
| 19 | +from sqlalchemy import Engine, text |
18 | 20 | from sqlalchemy.orm import Session |
19 | 21 | from testcontainers.core.container import DockerContainer |
20 | 22 | from testcontainers.core.waiting_utils import wait_for_logs |
@@ -184,6 +186,57 @@ def stop_containers(self) -> None: |
184 | 186 | _container_manager = DifyTestContainers() |
185 | 187 |
|
186 | 188 |
|
| 189 | +def _get_migration_dir() -> Path: |
| 190 | + conftest_dir = Path(__file__).parent |
| 191 | + return conftest_dir.parent.parent / "migrations" |
| 192 | + |
| 193 | + |
| 194 | +def _get_engine_url(engine: Engine): |
| 195 | + try: |
| 196 | + return engine.url.render_as_string(hide_password=False).replace("%", "%%") |
| 197 | + except AttributeError: |
| 198 | + return str(engine.url).replace("%", "%%") |
| 199 | + |
| 200 | + |
| 201 | +_UUIDv7SQL = r""" |
| 202 | +/* Main function to generate a uuidv7 value with millisecond precision */ |
| 203 | +CREATE FUNCTION uuidv7() RETURNS uuid |
| 204 | +AS |
| 205 | +$$ |
| 206 | + -- Replace the first 48 bits of a uuidv4 with the current |
| 207 | + -- number of milliseconds since 1970-01-01 UTC |
| 208 | + -- and set the "ver" field to 7 by setting additional bits |
| 209 | +SELECT encode( |
| 210 | + set_bit( |
| 211 | + set_bit( |
| 212 | + overlay(uuid_send(gen_random_uuid()) placing |
| 213 | + substring(int8send((extract(epoch from clock_timestamp()) * 1000)::bigint) from |
| 214 | + 3) |
| 215 | + from 1 for 6), |
| 216 | + 52, 1), |
| 217 | + 53, 1), 'hex')::uuid; |
| 218 | +$$ LANGUAGE SQL VOLATILE PARALLEL SAFE; |
| 219 | +
|
| 220 | +COMMENT ON FUNCTION uuidv7 IS |
| 221 | + 'Generate a uuid-v7 value with a 48-bit timestamp (millisecond precision) and 74 bits of randomness'; |
| 222 | +
|
| 223 | +CREATE FUNCTION uuidv7_boundary(timestamptz) RETURNS uuid |
| 224 | +AS |
| 225 | +$$ |
| 226 | + /* uuid fields: version=0b0111, variant=0b10 */ |
| 227 | +SELECT encode( |
| 228 | + overlay('\x00000000000070008000000000000000'::bytea |
| 229 | + placing substring(int8send(floor(extract(epoch from $1) * 1000)::bigint) from 3) |
| 230 | + from 1 for 6), |
| 231 | + 'hex')::uuid; |
| 232 | +$$ LANGUAGE SQL STABLE STRICT PARALLEL SAFE; |
| 233 | +
|
| 234 | +COMMENT ON FUNCTION uuidv7_boundary(timestamptz) IS |
| 235 | + 'Generate a non-random uuidv7 with the given timestamp (first 48 bits) and all random bits to 0. |
| 236 | + As the smallest possible uuidv7 for that timestamp, it may be used as a boundary for partitions.'; |
| 237 | +""" |
| 238 | + |
| 239 | + |
187 | 240 | def _create_app_with_containers() -> Flask: |
188 | 241 | """ |
189 | 242 | Create Flask application configured to use test containers. |
@@ -211,7 +264,10 @@ def _create_app_with_containers() -> Flask: |
211 | 264 |
|
212 | 265 | # Initialize database schema |
213 | 266 | logger.info("Creating database schema...") |
| 267 | + |
214 | 268 | with app.app_context(): |
| 269 | + with db.engine.connect() as conn, conn.begin(): |
| 270 | + conn.execute(text(_UUIDv7SQL)) |
215 | 271 | db.create_all() |
216 | 272 | logger.info("Database schema created successfully") |
217 | 273 |
|
|
0 commit comments