GCC Code Coverage Report


Directory: src/
File: src/pg/rabitq_params_pg.c
Date: 2026-09-30 11:11:31
Exec Total Coverage
Lines: 34 35 97.1%
Functions: 10 10 100.0%
Branches: 2 6 33.3%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2026 Tiger Data, Inc.
3 * Licensed under the PostgreSQL License. See LICENSE for details.
4 *
5 * vs_pg_rabitq_params.c - PostgreSQL functions for the rabitq_params type
6 *
7 * Stores the orthogonal transform matrix P for RaBitQ encoding.
8 * Generated via rabitq_params_generate(dim, seed); text I/O outputs
9 * {dim:seed} since inspecting dim^2 floats isn't useful.
10 */
11
12 #include <postgres.h>
13
14 #include <fmgr.h>
15 #include <lib/stringinfo.h>
16 #include <utils/builtins.h>
17 #include <utils/memutils.h>
18
19 #include "index/posting_page.h"
20 #include "quant/matrix.h"
21 #include "support_pg.h"
22
23 /*
24 * The generator caps dim at PRISM_INDEX_MAX_DIM (see
25 * vs_pg_check_rabitq_params_dim_valid). Prove at compile time that a
26 * matrix that large still fits a single allocation, so raising the cap
27 * without revisiting VS_RABITQ_PARAMS_PG_SIZE breaks the build here
28 * rather than silently over-allocating (or, on 32-bit, overflowing the
29 * size computation) at run time.
30 */
31 StaticAssertDecl(
32 offsetof(RaBitQParamsPG, P) + (uint64_t)PRISM_INDEX_MAX_DIM *
33 PRISM_INDEX_MAX_DIM *
34 sizeof(float) <=
35 MaxAllocSize,
36 "rabitq_params matrix at PRISM_INDEX_MAX_DIM exceeds MaxAllocSize; "
37 "revisit VS_RABITQ_PARAMS_PG_SIZE and the dim cap together");
38
39 /* ----------------------------------------------------------------
40 * Type I/O
41 * ---------------------------------------------------------------- */
42
43 9 PG_FUNCTION_INFO_V1(vs_rabitq_params_in);
44
45 Datum
46 1 vs_rabitq_params_in(PG_FUNCTION_ARGS)
47 {
48
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
49 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
50 errmsg("cannot parse rabitq_params from text"),
51 errhint("Use rabitq_params_generate(dim, seed) "
52 "instead.")));
53 PG_RETURN_NULL();
54 }
55
56 9 PG_FUNCTION_INFO_V1(vs_rabitq_params_out);
57
58 Datum
59 1 vs_rabitq_params_out(PG_FUNCTION_ARGS)
60 {
61 1 RaBitQParamsPG *p = PG_GETARG_RABITQ_PARAMS_P(0);
62 1 StringInfoData buf;
63
64 1 initStringInfo(&buf);
65 1 appendStringInfo(
66 1 &buf, "{%d:%llu}", (int)p->dim, (unsigned long long)p->seed);
67
68 1 PG_RETURN_CSTRING(buf.data);
69 }
70
71 /* ----------------------------------------------------------------
72 * Generate function
73 * ---------------------------------------------------------------- */
74
75 9 PG_FUNCTION_INFO_V1(vs_rabitq_params_generate_pg);
76
77 Datum
78 9 vs_rabitq_params_generate_pg(PG_FUNCTION_ARGS)
79 {
80 9 int32 dim = PG_GETARG_INT32(0);
81 9 int64 seed = PG_GETARG_INT64(1);
82
83 9 vs_pg_check_rabitq_params_dim_valid(dim);
84
85 8 Size size = VS_RABITQ_PARAMS_PG_SIZE(dim);
86 8 RaBitQParamsPG *result = (RaBitQParamsPG *)palloc0(size);
87 8 SET_VARSIZE(result, size);
88 8 result->dim = (int16_t)dim;
89 8 result->unused = 0;
90 8 result->seed = (uint64_t)seed;
91
92 16 int ret = vs_random_orthogonal_matrix(
93 8 result->P, (Dimension)dim, (uint64_t)seed);
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret != 0)
95 ✗ ereport(ERROR,
96 (errcode(ERRCODE_INTERNAL_ERROR),
97 errmsg("failed to generate orthogonal matrix"
98 " for rabitq_params")));
99
100 8 PG_RETURN_POINTER(result);
101 }
102
103 /* ----------------------------------------------------------------
104 * Accessor functions
105 * ---------------------------------------------------------------- */
106
107 9 PG_FUNCTION_INFO_V1(vs_rabitq_params_dim);
108
109 Datum
110 1 vs_rabitq_params_dim(PG_FUNCTION_ARGS)
111 {
112 1 RaBitQParamsPG *p = PG_GETARG_RABITQ_PARAMS_P(0);
113 1 PG_RETURN_INT32((int32)p->dim);
114 }
115
116 9 PG_FUNCTION_INFO_V1(vs_rabitq_params_seed);
117
118 Datum
119 1 vs_rabitq_params_seed(PG_FUNCTION_ARGS)
120 {
121 1 RaBitQParamsPG *p = PG_GETARG_RABITQ_PARAMS_P(0);
122 1 PG_RETURN_INT64((int64)p->seed);
123 }
124