| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2026 Tiger Data, Inc. | ||
| 3 | * Licensed under the PostgreSQL License. See LICENSE for details. | ||
| 4 | * | ||
| 5 | * meta.h - Metadata page layout for prism index | ||
| 6 | * | ||
| 7 | * Block 0 of every prism index stores a PrismMetaPage in the | ||
| 8 | * page special area. It records index parameters (dimension, tree | ||
| 9 | * depth, centroid format, distance metric, RaBitQ seed) and the | ||
| 10 | * global mean vector used for RaBitQ query preparation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef PRISM_META_H | ||
| 14 | #define PRISM_META_H | ||
| 15 | |||
| 16 | #include <postgres.h> | ||
| 17 | |||
| 18 | #pragma GCC diagnostic push | ||
| 19 | #pragma GCC diagnostic ignored "-Wunused-parameter" | ||
| 20 | #include <storage/bufpage.h> | ||
| 21 | #pragma GCC diagnostic pop | ||
| 22 | |||
| 23 | #include "core/types.h" | ||
| 24 | |||
| 25 | /* | ||
| 26 | * "PRI" + a format-version byte. Bump the low byte on any incompatible | ||
| 27 | * metapage/layout change so an index built by an older format is rejected at | ||
| 28 | * open rather than silently misread. v2 added PrismMetaPage.first_posting, | ||
| 29 | * which shifted the struct layout; v3 removed the unused indexed-row count, | ||
| 30 | * which shifted it again. | ||
| 31 | */ | ||
| 32 | #define PRISM_META_MAGIC ((uint32_t)0x50524905) /* "PRI\x05" */ | ||
| 33 | |||
| 34 | /* Metadata flags */ | ||
| 35 | #define PRISM_META_FLAG_FASTSCAN 0x01 | ||
| 36 | |||
| 37 | typedef struct PrismMetaPage | ||
| 38 | { | ||
| 39 | uint32_t magic; /* PRISM_META_MAGIC */ | ||
| 40 | Dimension dim; /* vector dimension */ | ||
| 41 | uint8_t nlevels; /* centroid tree depth */ | ||
| 42 | uint8_t centroid_format; /* PrismCentroidFormat */ | ||
| 43 | BlockNumber first_centroid; /* root centroid page */ | ||
| 44 | BlockNumber first_posting; /* first posting page (one past the last | ||
| 45 | * centroid page); lets VACUUM skip the whole | ||
| 46 | * centroid region without scanning it */ | ||
| 47 | uint32_t nlist; /* number of leaf centroids */ | ||
| 48 | /* | ||
| 49 | * Centroid pages reachable from first_centroid. Maintained rather than | ||
| 50 | * derived: the region a build reserves is [PRISM_FIRST_CENTROID_BLKNO, | ||
| 51 | * first_posting), but a split with no room on a level-0 page extends the | ||
| 52 | * relation and chains the new page past the posting region, so a block | ||
| 53 | * range stops measuring it. prism_rebalance folds each split's additions | ||
| 54 | * back in here. | ||
| 55 | */ | ||
| 56 | uint32_t ncentroid_pages; | ||
| 57 | uint8_t metric; /* DistanceMetric */ | ||
| 58 | uint8_t fan_out; /* children per tree node */ | ||
| 59 | uint8_t flags; /* PRISM_META_FLAG_* */ | ||
| 60 | uint8_t reserved; | ||
| 61 | uint64_t rabitq_seed; /* seed for RaBitQ params */ | ||
| 62 | /* Global mean vector stored inline after struct */ | ||
| 63 | } PrismMetaPage; | ||
| 64 | |||
| 65 | /* Total special-area size including inline global mean */ | ||
| 66 | #define PRISM_META_SIZE(dim) \ | ||
| 67 | (MAXALIGN( \ | ||
| 68 | offsetof(PrismMetaPage, rabitq_seed) + sizeof(uint64_t) + \ | ||
| 69 | (size_t)(dim) * sizeof(float))) | ||
| 70 | |||
| 71 | /* Access the inline global mean vector after the struct */ | ||
| 72 | static inline float * | ||
| 73 | 194 | prism_meta_global_mean(PrismMetaPage *meta) | |
| 74 | { | ||
| 75 | 194 | return (float *)((char *)meta + offsetof(PrismMetaPage, rabitq_seed) + | |
| 76 | sizeof(uint64_t)); | ||
| 77 | } | ||
| 78 | |||
| 79 | static inline const float * | ||
| 80 | 243 | prism_meta_global_mean_const(const PrismMetaPage *meta) | |
| 81 | { | ||
| 82 | 243 | return (const float *)((const char *)meta + | |
| 83 | offsetof(PrismMetaPage, rabitq_seed) + | ||
| 84 | sizeof(uint64_t)); | ||
| 85 | } | ||
| 86 | |||
| 87 | #endif /* PRISM_META_H */ | ||
| 88 |