multi_compress 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/GET_STARTED.md +19 -0
- data/README.md +14 -1
- data/db_core/include/mcdb_format.h +67 -9
- data/db_core/src/mcdb_format.c +392 -139
- data/db_deployment/mysql/README.md +19 -0
- data/db_deployment/mysql/bin/common +70 -18
- data/db_deployment/mysql/bin/enable +5 -1
- data/db_deployment/mysql/bin/status +2 -0
- data/db_deployment/mysql/bin/upgrade +17 -5
- data/db_deployment/postgres/README.md +24 -0
- data/db_deployment/postgres/bin/enable +2 -0
- data/db_deployment/postgres/bin/install +4 -2
- data/docs/database-envelope-v2.md +147 -0
- data/docs/rfcs/0002-mcdb2-dictionaries.md +75 -0
- data/ext/multi_compress/multi_compress.c +32 -0
- data/lib/multi_compress/database.rb +255 -49
- data/lib/multi_compress/db_deployment.rb +423 -11
- data/lib/multi_compress/version.rb +1 -1
- data/mysql_udf/README.md +45 -0
- data/mysql_udf/sql/examples.sql +5 -0
- data/mysql_udf/sql/install.sql +25 -1
- data/mysql_udf/sql/uninstall.sql +7 -1
- data/mysql_udf/sql/views.sql +16 -4
- data/mysql_udf/src/multi_compress_mysql.c +383 -44
- data/mysql_udf/test/run_e2e.sh +119 -1
- data/postgres_extension/Makefile +2 -2
- data/postgres_extension/README.md +48 -0
- data/postgres_extension/multi_compress.control +2 -2
- data/postgres_extension/multi_compress_pg.exports +12 -0
- data/postgres_extension/sql/examples.sql +11 -0
- data/postgres_extension/sql/multi_compress--0.5.0--0.6.0.sql +59 -0
- data/postgres_extension/sql/multi_compress--0.6.0.sql +85 -0
- data/postgres_extension/src/multi_compress_pg.c +301 -16
- data/postgres_extension/test/run_e2e.sh +90 -2
- metadata +6 -2
data/db_core/src/mcdb_format.c
CHANGED
|
@@ -1,63 +1,29 @@
|
|
|
1
1
|
#include "mcdb_format.h"
|
|
2
2
|
|
|
3
|
+
#include <stdio.h>
|
|
3
4
|
#include <stdlib.h>
|
|
4
5
|
#include <string.h>
|
|
5
|
-
#include <stdio.h>
|
|
6
6
|
|
|
7
7
|
#include <zstd.h>
|
|
8
8
|
|
|
9
|
-
typedef char
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
0x9E6495A3U, 0x0EDB8832U, 0x79DCB8A4U, 0xE0D5E91EU, 0x97D2D988U, 0x09B64C2BU, 0x7EB17CBDU,
|
|
18
|
-
0xE7B82D07U, 0x90BF1D91U, 0x1DB71064U, 0x6AB020F2U, 0xF3B97148U, 0x84BE41DEU, 0x1ADAD47DU,
|
|
19
|
-
0x6DDDE4EBU, 0xF4D4B551U, 0x83D385C7U, 0x136C9856U, 0x646BA8C0U, 0xFD62F97AU, 0x8A65C9ECU,
|
|
20
|
-
0x14015C4FU, 0x63066CD9U, 0xFA0F3D63U, 0x8D080DF5U, 0x3B6E20C8U, 0x4C69105EU, 0xD56041E4U,
|
|
21
|
-
0xA2677172U, 0x3C03E4D1U, 0x4B04D447U, 0xD20D85FDU, 0xA50AB56BU, 0x35B5A8FAU, 0x42B2986CU,
|
|
22
|
-
0xDBBBC9D6U, 0xACBCF940U, 0x32D86CE3U, 0x45DF5C75U, 0xDCD60DCFU, 0xABD13D59U, 0x26D930ACU,
|
|
23
|
-
0x51DE003AU, 0xC8D75180U, 0xBFD06116U, 0x21B4F4B5U, 0x56B3C423U, 0xCFBA9599U, 0xB8BDA50FU,
|
|
24
|
-
0x2802B89EU, 0x5F058808U, 0xC60CD9B2U, 0xB10BE924U, 0x2F6F7C87U, 0x58684C11U, 0xC1611DABU,
|
|
25
|
-
0xB6662D3DU, 0x76DC4190U, 0x01DB7106U, 0x98D220BCU, 0xEFD5102AU, 0x71B18589U, 0x06B6B51FU,
|
|
26
|
-
0x9FBFE4A5U, 0xE8B8D433U, 0x7807C9A2U, 0x0F00F934U, 0x9609A88EU, 0xE10E9818U, 0x7F6A0DBBU,
|
|
27
|
-
0x086D3D2DU, 0x91646C97U, 0xE6635C01U, 0x6B6B51F4U, 0x1C6C6162U, 0x856530D8U, 0xF262004EU,
|
|
28
|
-
0x6C0695EDU, 0x1B01A57BU, 0x8208F4C1U, 0xF50FC457U, 0x65B0D9C6U, 0x12B7E950U, 0x8BBEB8EAU,
|
|
29
|
-
0xFCB9887CU, 0x62DD1DDFU, 0x15DA2D49U, 0x8CD37CF3U, 0xFBD44C65U, 0x4DB26158U, 0x3AB551CEU,
|
|
30
|
-
0xA3BC0074U, 0xD4BB30E2U, 0x4ADFA541U, 0x3DD895D7U, 0xA4D1C46DU, 0xD3D6F4FBU, 0x4369E96AU,
|
|
31
|
-
0x346ED9FCU, 0xAD678846U, 0xDA60B8D0U, 0x44042D73U, 0x33031DE5U, 0xAA0A4C5FU, 0xDD0D7CC9U,
|
|
32
|
-
0x5005713CU, 0x270241AAU, 0xBE0B1010U, 0xC90C2086U, 0x5768B525U, 0x206F85B3U, 0xB966D409U,
|
|
33
|
-
0xCE61E49FU, 0x5EDEF90EU, 0x29D9C998U, 0xB0D09822U, 0xC7D7A8B4U, 0x59B33D17U, 0x2EB40D81U,
|
|
34
|
-
0xB7BD5C3BU, 0xC0BA6CADU, 0xEDB88320U, 0x9ABFB3B6U, 0x03B6E20CU, 0x74B1D29AU, 0xEAD54739U,
|
|
35
|
-
0x9DD277AFU, 0x04DB2615U, 0x73DC1683U, 0xE3630B12U, 0x94643B84U, 0x0D6D6A3EU, 0x7A6A5AA8U,
|
|
36
|
-
0xE40ECF0BU, 0x9309FF9DU, 0x0A00AE27U, 0x7D079EB1U, 0xF00F9344U, 0x8708A3D2U, 0x1E01F268U,
|
|
37
|
-
0x6906C2FEU, 0xF762575DU, 0x806567CBU, 0x196C3671U, 0x6E6B06E7U, 0xFED41B76U, 0x89D32BE0U,
|
|
38
|
-
0x10DA7A5AU, 0x67DD4ACCU, 0xF9B9DF6FU, 0x8EBEEFF9U, 0x17B7BE43U, 0x60B08ED5U, 0xD6D6A3E8U,
|
|
39
|
-
0xA1D1937EU, 0x38D8C2C4U, 0x4FDFF252U, 0xD1BB67F1U, 0xA6BC5767U, 0x3FB506DDU, 0x48B2364BU,
|
|
40
|
-
0xD80D2BDAU, 0xAF0A1B4CU, 0x36034AF6U, 0x41047A60U, 0xDF60EFC3U, 0xA867DF55U, 0x316E8EEFU,
|
|
41
|
-
0x4669BE79U, 0xCB61B38CU, 0xBC66831AU, 0x256FD2A0U, 0x5268E236U, 0xCC0C7795U, 0xBB0B4703U,
|
|
42
|
-
0x220216B9U, 0x5505262FU, 0xC5BA3BBEU, 0xB2BD0B28U, 0x2BB45A92U, 0x5CB36A04U, 0xC2D7FFA7U,
|
|
43
|
-
0xB5D0CF31U, 0x2CD99E8BU, 0x5BDEAE1DU, 0x9B64C2B0U, 0xEC63F226U, 0x756AA39CU, 0x026D930AU,
|
|
44
|
-
0x9C0906A9U, 0xEB0E363FU, 0x72076785U, 0x05005713U, 0x95BF4A82U, 0xE2B87A14U, 0x7BB12BAEU,
|
|
45
|
-
0x0CB61B38U, 0x92D28E9BU, 0xE5D5BE0DU, 0x7CDCEFB7U, 0x0BDBDF21U, 0x86D3D2D4U, 0xF1D4E242U,
|
|
46
|
-
0x68DDB3F8U, 0x1FDA836EU, 0x81BE16CDU, 0xF6B9265BU, 0x6FB077E1U, 0x18B74777U, 0x88085AE6U,
|
|
47
|
-
0xFF0F6A70U, 0x66063BCAU, 0x11010B5CU, 0x8F659EFFU, 0xF862AE69U, 0x616BFFD3U, 0x166CCF45U,
|
|
48
|
-
0xA00AE278U, 0xD70DD2EEU, 0x4E048354U, 0x3903B3C2U, 0xA7672661U, 0xD06016F7U, 0x4969474DU,
|
|
49
|
-
0x3E6E77DBU, 0xAED16A4AU, 0xD9D65ADCU, 0x40DF0B66U, 0x37D83BF0U, 0xA9BCAE53U, 0xDEBB9EC5U,
|
|
50
|
-
0x47B2CF7FU, 0x30B5FFE9U, 0xBDBDF21CU, 0xCABAC28AU, 0x53B39330U, 0x24B4A3A6U, 0xBAD03605U,
|
|
51
|
-
0xCDD70693U, 0x54DE5729U, 0x23D967BFU, 0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U,
|
|
52
|
-
0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU,
|
|
53
|
-
};
|
|
9
|
+
typedef char mcdb_v1_envelope_bound_check
|
|
10
|
+
[(MCDB_MAX_ENVELOPE_V1 == (unsigned)(MCDB_V1_HEADER_SIZE + ZSTD_COMPRESSBOUND(MCDB_MAX_OUTPUT)))
|
|
11
|
+
? 1
|
|
12
|
+
: -1];
|
|
13
|
+
typedef char mcdb_v2_envelope_bound_check
|
|
14
|
+
[(MCDB_MAX_ENVELOPE_V2 == (unsigned)(MCDB_V2_HEADER_SIZE + ZSTD_COMPRESSBOUND(MCDB_MAX_OUTPUT)))
|
|
15
|
+
? 1
|
|
16
|
+
: -1];
|
|
54
17
|
|
|
55
18
|
static uint32_t mcdb_crc32(const unsigned char *data, size_t len) {
|
|
56
19
|
uint32_t crc = 0xFFFFFFFFU;
|
|
57
20
|
size_t i;
|
|
21
|
+
int bit;
|
|
58
22
|
|
|
59
23
|
for (i = 0; i < len; i++) {
|
|
60
|
-
crc
|
|
24
|
+
crc ^= data[i];
|
|
25
|
+
for (bit = 0; bit < 8; bit++)
|
|
26
|
+
crc = (crc & 1U) ? ((crc >> 1) ^ 0xEDB88320U) : (crc >> 1);
|
|
61
27
|
}
|
|
62
28
|
return crc ^ 0xFFFFFFFFU;
|
|
63
29
|
}
|
|
@@ -65,7 +31,6 @@ static uint32_t mcdb_crc32(const unsigned char *data, size_t len) {
|
|
|
65
31
|
static uint64_t read_u64_le(const unsigned char *p) {
|
|
66
32
|
uint64_t v = 0;
|
|
67
33
|
int i;
|
|
68
|
-
|
|
69
34
|
for (i = 0; i < 8; i++)
|
|
70
35
|
v |= (uint64_t)p[i] << (8 * i);
|
|
71
36
|
return v;
|
|
@@ -77,122 +42,169 @@ static uint32_t read_u32_le(const unsigned char *p) {
|
|
|
77
42
|
|
|
78
43
|
static int mcdb_is_valid_utf8(const unsigned char *s, size_t len) {
|
|
79
44
|
size_t i = 0;
|
|
80
|
-
|
|
81
45
|
while (i < len) {
|
|
82
|
-
unsigned char c;
|
|
46
|
+
unsigned char c = s[i];
|
|
83
47
|
size_t n;
|
|
84
|
-
|
|
85
|
-
unsigned char
|
|
86
|
-
unsigned char hi2;
|
|
48
|
+
unsigned char lo2 = 0x80;
|
|
49
|
+
unsigned char hi2 = 0xBF;
|
|
87
50
|
size_t k;
|
|
88
51
|
|
|
89
|
-
c = s[i];
|
|
90
|
-
n = 0;
|
|
91
|
-
cp = 0;
|
|
92
|
-
lo2 = 0x80;
|
|
93
|
-
hi2 = 0xBF;
|
|
94
|
-
|
|
95
52
|
if (c < 0x80) {
|
|
96
53
|
if (c == 0)
|
|
97
54
|
return 0;
|
|
98
|
-
i
|
|
55
|
+
i++;
|
|
99
56
|
continue;
|
|
100
57
|
}
|
|
101
|
-
|
|
102
58
|
if ((c & 0xE0) == 0xC0) {
|
|
103
|
-
n = 2;
|
|
104
|
-
cp = c & 0x1F;
|
|
105
59
|
if (c < 0xC2)
|
|
106
60
|
return 0;
|
|
61
|
+
n = 2;
|
|
107
62
|
} else if ((c & 0xF0) == 0xE0) {
|
|
108
63
|
n = 3;
|
|
109
|
-
cp = c & 0x0F;
|
|
110
64
|
if (c == 0xE0)
|
|
111
|
-
lo2 = 0xA0;
|
|
65
|
+
lo2 = 0xA0;
|
|
112
66
|
if (c == 0xED)
|
|
113
|
-
hi2 = 0x9F;
|
|
67
|
+
hi2 = 0x9F;
|
|
114
68
|
} else if ((c & 0xF8) == 0xF0) {
|
|
115
|
-
|
|
116
|
-
cp = c & 0x07;
|
|
117
|
-
if (c < 0xF0 || c > 0xF4)
|
|
69
|
+
if (c > 0xF4)
|
|
118
70
|
return 0;
|
|
71
|
+
n = 4;
|
|
119
72
|
if (c == 0xF0)
|
|
120
|
-
lo2 = 0x90;
|
|
73
|
+
lo2 = 0x90;
|
|
121
74
|
if (c == 0xF4)
|
|
122
|
-
hi2 = 0x8F;
|
|
75
|
+
hi2 = 0x8F;
|
|
123
76
|
} else {
|
|
124
77
|
return 0;
|
|
125
78
|
}
|
|
126
|
-
|
|
127
79
|
if (i + n > len)
|
|
128
80
|
return 0;
|
|
129
81
|
for (k = 1; k < n; k++) {
|
|
130
|
-
unsigned char cc;
|
|
131
|
-
unsigned char lo;
|
|
132
|
-
unsigned char hi;
|
|
133
|
-
|
|
134
|
-
cc = s[i + k];
|
|
135
|
-
lo = (k == 1) ? lo2 : 0x80;
|
|
136
|
-
hi = (k == 1) ? hi2 : 0xBF;
|
|
82
|
+
unsigned char cc = s[i + k];
|
|
83
|
+
unsigned char lo = k == 1 ? lo2 : 0x80;
|
|
84
|
+
unsigned char hi = k == 1 ? hi2 : 0xBF;
|
|
137
85
|
if (cc < lo || cc > hi)
|
|
138
86
|
return 0;
|
|
139
|
-
cp = (cp << 6) | (cc & 0x3F);
|
|
140
87
|
}
|
|
141
|
-
(void)cp;
|
|
142
88
|
i += n;
|
|
143
89
|
}
|
|
144
90
|
return 1;
|
|
145
91
|
}
|
|
146
92
|
|
|
147
|
-
mcdb_status
|
|
148
|
-
|
|
149
|
-
|
|
93
|
+
mcdb_status mcdb_parse_header(const unsigned char *in, size_t in_len, mcdb_header *out_header) {
|
|
94
|
+
mcdb_header header;
|
|
95
|
+
size_t max_envelope;
|
|
150
96
|
|
|
151
|
-
if (in == NULL || in_len <
|
|
97
|
+
if (in == NULL || in_len < MCDB_V1_HEADER_SIZE)
|
|
152
98
|
return MCDB_ERR_TRUNCATED;
|
|
153
|
-
if (in_len > MCDB_MAX_ENVELOPE)
|
|
154
|
-
return MCDB_ERR_ENVELOPE_SIZE;
|
|
155
99
|
if (in[0] != MCDB_MAGIC0 || in[1] != MCDB_MAGIC1 || in[2] != MCDB_MAGIC2 ||
|
|
156
100
|
in[3] != MCDB_MAGIC3)
|
|
157
101
|
return MCDB_ERR_MAGIC;
|
|
158
|
-
if (in[4] !=
|
|
102
|
+
if (in[4] != MCDB_VERSION_V1 && in[4] != MCDB_VERSION_V2)
|
|
159
103
|
return MCDB_ERR_VERSION;
|
|
104
|
+
|
|
105
|
+
memset(&header, 0, sizeof(header));
|
|
106
|
+
header.version = in[4];
|
|
107
|
+
header.header_size =
|
|
108
|
+
header.version == MCDB_VERSION_V2 ? MCDB_V2_HEADER_SIZE : MCDB_V1_HEADER_SIZE;
|
|
109
|
+
max_envelope = header.version == MCDB_VERSION_V2 ? MCDB_MAX_ENVELOPE_V2 : MCDB_MAX_ENVELOPE_V1;
|
|
110
|
+
|
|
111
|
+
if (in_len < header.header_size)
|
|
112
|
+
return MCDB_ERR_TRUNCATED;
|
|
113
|
+
if (in_len > max_envelope)
|
|
114
|
+
return MCDB_ERR_ENVELOPE_SIZE;
|
|
160
115
|
if (in[5] != MCDB_CODEC_ZSTD)
|
|
161
116
|
return MCDB_ERR_CODEC;
|
|
162
|
-
if (in[6] !=
|
|
117
|
+
if (in[6] != MCDB_FLAGS_NONE)
|
|
163
118
|
return MCDB_ERR_FLAGS;
|
|
164
119
|
|
|
165
|
-
original_size = read_u64_le(in +
|
|
166
|
-
if (original_size > MCDB_MAX_OUTPUT)
|
|
120
|
+
header.original_size = read_u64_le(in + MCDB_ORIGINAL_SIZE_OFFSET);
|
|
121
|
+
if (header.original_size > MCDB_MAX_OUTPUT)
|
|
167
122
|
return MCDB_ERR_SIZE_LIMIT;
|
|
168
123
|
|
|
124
|
+
if (header.version == MCDB_VERSION_V2) {
|
|
125
|
+
header.dictionary_ref = read_u64_le(in + MCDB_DICTIONARY_REF_OFFSET);
|
|
126
|
+
if (header.dictionary_ref == 0 || header.dictionary_ref > MCDB_MAX_DICTIONARY_REF)
|
|
127
|
+
return MCDB_ERR_DICTIONARY_REF;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (out_header)
|
|
131
|
+
*out_header = header;
|
|
132
|
+
return MCDB_OK;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
mcdb_status mcdb_validate_header(const unsigned char *in, size_t in_len,
|
|
136
|
+
uint64_t *out_original_size) {
|
|
137
|
+
mcdb_header header;
|
|
138
|
+
mcdb_status st = mcdb_parse_header(in, in_len, &header);
|
|
139
|
+
if (st != MCDB_OK)
|
|
140
|
+
return st;
|
|
141
|
+
if (header.version != MCDB_VERSION_V1)
|
|
142
|
+
return MCDB_ERR_VERSION;
|
|
169
143
|
if (out_original_size)
|
|
170
|
-
*out_original_size = original_size;
|
|
144
|
+
*out_original_size = header.original_size;
|
|
171
145
|
return MCDB_OK;
|
|
172
146
|
}
|
|
173
147
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
148
|
+
mcdb_status mcdb_validate_v2_header(const unsigned char *in, size_t in_len,
|
|
149
|
+
uint64_t *out_original_size, uint64_t *out_dictionary_ref) {
|
|
150
|
+
mcdb_header header;
|
|
151
|
+
mcdb_status st = mcdb_parse_header(in, in_len, &header);
|
|
152
|
+
if (st != MCDB_OK)
|
|
153
|
+
return st;
|
|
154
|
+
if (header.version != MCDB_VERSION_V2)
|
|
155
|
+
return MCDB_ERR_VERSION;
|
|
156
|
+
if (out_original_size)
|
|
157
|
+
*out_original_size = header.original_size;
|
|
158
|
+
if (out_dictionary_ref)
|
|
159
|
+
*out_dictionary_ref = header.dictionary_ref;
|
|
160
|
+
return MCDB_OK;
|
|
161
|
+
}
|
|
184
162
|
|
|
185
|
-
|
|
186
|
-
|
|
163
|
+
mcdb_status mcdb_validate_dictionary(const unsigned char *dictionary, size_t dictionary_len,
|
|
164
|
+
uint32_t *out_zstd_dictionary_id) {
|
|
165
|
+
uint32_t dict_id;
|
|
166
|
+
if (dictionary == NULL || dictionary_len == 0 || dictionary_len > MCDB_MAX_DICTIONARY_BYTES)
|
|
167
|
+
return MCDB_ERR_DICTIONARY_SIZE;
|
|
168
|
+
dict_id = ZSTD_getDictID_fromDict(dictionary, dictionary_len);
|
|
169
|
+
if (dict_id == 0)
|
|
170
|
+
return MCDB_ERR_DICTIONARY_ID;
|
|
171
|
+
if (out_zstd_dictionary_id)
|
|
172
|
+
*out_zstd_dictionary_id = dict_id;
|
|
173
|
+
return MCDB_OK;
|
|
174
|
+
}
|
|
187
175
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
176
|
+
uint32_t mcdb_zstd_frame_dictionary_id(const unsigned char *frame, size_t frame_len) {
|
|
177
|
+
if (frame == NULL || frame_len == 0)
|
|
178
|
+
return 0;
|
|
179
|
+
return ZSTD_getDictID_fromFrame(frame, frame_len);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
uint64_t mcdb_dictionary_ref(const unsigned char *in, size_t in_len, mcdb_status *out_status) {
|
|
183
|
+
mcdb_header header;
|
|
184
|
+
mcdb_status st = mcdb_parse_header(in, in_len, &header);
|
|
185
|
+
if (out_status)
|
|
186
|
+
*out_status = st;
|
|
187
|
+
if (st != MCDB_OK || header.version != MCDB_VERSION_V2) {
|
|
188
|
+
if (out_status && st == MCDB_OK)
|
|
189
|
+
*out_status = MCDB_ERR_VERSION;
|
|
190
|
+
return 0;
|
|
192
191
|
}
|
|
192
|
+
return header.dictionary_ref;
|
|
193
|
+
}
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
static mcdb_status mcdb_validate_frame(const unsigned char *in, size_t in_len,
|
|
196
|
+
const mcdb_header *header, const unsigned char **out_frame,
|
|
197
|
+
size_t *out_frame_len, char *errbuf) {
|
|
198
|
+
const unsigned char *frame = in + header->header_size;
|
|
199
|
+
size_t frame_len = in_len - header->header_size;
|
|
200
|
+
size_t frame_size;
|
|
201
|
+
unsigned long long content_size;
|
|
202
|
+
|
|
203
|
+
if (frame_len == 0) {
|
|
204
|
+
if (errbuf)
|
|
205
|
+
snprintf(errbuf, MCDB_ERRLEN, "MCDB: missing zstd frame");
|
|
206
|
+
return MCDB_ERR_DECOMPRESS;
|
|
207
|
+
}
|
|
196
208
|
frame_size = ZSTD_findFrameCompressedSize(frame, frame_len);
|
|
197
209
|
if (ZSTD_isError(frame_size)) {
|
|
198
210
|
if (errbuf)
|
|
@@ -206,28 +218,31 @@ static mcdb_status mcdb_decode_payload(const unsigned char *in, size_t in_len,
|
|
|
206
218
|
"MCDB: zstd frame has trailing bytes or concatenated frames");
|
|
207
219
|
return MCDB_ERR_TRAILING_DATA;
|
|
208
220
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
frame_content_size == ZSTD_CONTENTSIZE_UNKNOWN || frame_content_size != original_size) {
|
|
221
|
+
content_size = ZSTD_getFrameContentSize(frame, frame_len);
|
|
222
|
+
if (content_size == ZSTD_CONTENTSIZE_ERROR || content_size == ZSTD_CONTENTSIZE_UNKNOWN ||
|
|
223
|
+
content_size != header->original_size) {
|
|
213
224
|
if (errbuf)
|
|
214
225
|
snprintf(errbuf, MCDB_ERRLEN, "MCDB: zstd frame content size does not match header");
|
|
215
226
|
return MCDB_ERR_FRAME_CONTENT_SIZE;
|
|
216
227
|
}
|
|
228
|
+
if (out_frame)
|
|
229
|
+
*out_frame = frame;
|
|
230
|
+
if (out_frame_len)
|
|
231
|
+
*out_frame_len = frame_len;
|
|
232
|
+
return MCDB_OK;
|
|
233
|
+
}
|
|
217
234
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (produced != original_size) {
|
|
235
|
+
static mcdb_status mcdb_finish_decoded(const unsigned char *in, const mcdb_header *header,
|
|
236
|
+
unsigned char *out, size_t produced, size_t *out_len,
|
|
237
|
+
char *errbuf) {
|
|
238
|
+
uint32_t expected_crc;
|
|
239
|
+
uint32_t actual_crc;
|
|
240
|
+
if (produced != header->original_size) {
|
|
225
241
|
if (errbuf)
|
|
226
242
|
snprintf(errbuf, MCDB_ERRLEN, "MCDB: size mismatch (header %llu, got %zu)",
|
|
227
|
-
(unsigned long long)original_size, produced);
|
|
243
|
+
(unsigned long long)header->original_size, produced);
|
|
228
244
|
return MCDB_ERR_SIZE_MISMATCH;
|
|
229
245
|
}
|
|
230
|
-
|
|
231
246
|
expected_crc = read_u32_le(in + MCDB_CRC_OFFSET);
|
|
232
247
|
actual_crc = mcdb_crc32(out, produced);
|
|
233
248
|
if (actual_crc != expected_crc) {
|
|
@@ -236,14 +251,12 @@ static mcdb_status mcdb_decode_payload(const unsigned char *in, size_t in_len,
|
|
|
236
251
|
expected_crc, actual_crc);
|
|
237
252
|
return MCDB_ERR_CRC;
|
|
238
253
|
}
|
|
239
|
-
|
|
240
254
|
if (!mcdb_is_valid_utf8(out, produced)) {
|
|
241
255
|
if (errbuf)
|
|
242
256
|
snprintf(errbuf, MCDB_ERRLEN,
|
|
243
257
|
"MCDB: payload is not valid UTF-8 text or contains a NUL byte");
|
|
244
258
|
return MCDB_ERR_UTF8;
|
|
245
259
|
}
|
|
246
|
-
|
|
247
260
|
if (out_len)
|
|
248
261
|
*out_len = produced;
|
|
249
262
|
return MCDB_OK;
|
|
@@ -251,51 +264,159 @@ static mcdb_status mcdb_decode_payload(const unsigned char *in, size_t in_len,
|
|
|
251
264
|
|
|
252
265
|
mcdb_status mcdb_decode_into(const unsigned char *in, size_t in_len, unsigned char *out,
|
|
253
266
|
size_t out_capacity, size_t *out_len, char *errbuf) {
|
|
254
|
-
|
|
267
|
+
mcdb_header header;
|
|
268
|
+
const unsigned char *frame;
|
|
269
|
+
size_t frame_len;
|
|
270
|
+
size_t produced;
|
|
271
|
+
mcdb_status st;
|
|
255
272
|
|
|
256
273
|
if (out_len)
|
|
257
274
|
*out_len = 0;
|
|
258
275
|
if (errbuf)
|
|
259
276
|
errbuf[0] = '\0';
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
277
|
+
st = mcdb_parse_header(in, in_len, &header);
|
|
278
|
+
if (st != MCDB_OK)
|
|
279
|
+
return st;
|
|
280
|
+
if (header.version != MCDB_VERSION_V1)
|
|
281
|
+
return MCDB_ERR_VERSION;
|
|
282
|
+
if (out == NULL || out_capacity < header.original_size)
|
|
283
|
+
return MCDB_ERR_SIZE_MISMATCH;
|
|
284
|
+
st = mcdb_validate_frame(in, in_len, &header, &frame, &frame_len, errbuf);
|
|
285
|
+
if (st != MCDB_OK)
|
|
286
|
+
return st;
|
|
287
|
+
produced = ZSTD_decompress(out, (size_t)header.original_size, frame, frame_len);
|
|
288
|
+
if (ZSTD_isError(produced)) {
|
|
289
|
+
if (errbuf)
|
|
290
|
+
snprintf(errbuf, MCDB_ERRLEN, "MCDB: zstd error: %s", ZSTD_getErrorName(produced));
|
|
291
|
+
return MCDB_ERR_DECOMPRESS;
|
|
292
|
+
}
|
|
293
|
+
return mcdb_finish_decoded(in, &header, out, produced, out_len, errbuf);
|
|
263
294
|
}
|
|
264
295
|
|
|
265
296
|
mcdb_status mcdb_decode(const unsigned char *in, size_t in_len, unsigned char **out,
|
|
266
297
|
size_t *out_len, char *errbuf) {
|
|
267
|
-
|
|
268
|
-
mcdb_status st;
|
|
298
|
+
mcdb_header header;
|
|
269
299
|
unsigned char *buf;
|
|
270
|
-
|
|
300
|
+
mcdb_status st;
|
|
271
301
|
if (out)
|
|
272
302
|
*out = NULL;
|
|
273
303
|
if (out_len)
|
|
274
304
|
*out_len = 0;
|
|
275
305
|
if (errbuf)
|
|
276
306
|
errbuf[0] = '\0';
|
|
277
|
-
|
|
278
|
-
st = mcdb_validate_header(in, in_len, &original_size);
|
|
307
|
+
st = mcdb_validate_header(in, in_len, &header.original_size);
|
|
279
308
|
if (st != MCDB_OK) {
|
|
280
309
|
if (errbuf)
|
|
281
310
|
snprintf(errbuf, MCDB_ERRLEN, "MCDB: %s", mcdb_status_str(st));
|
|
282
311
|
return st;
|
|
283
312
|
}
|
|
284
|
-
|
|
285
|
-
buf = (unsigned char *)malloc(original_size ? original_size : 1);
|
|
313
|
+
buf = (unsigned char *)malloc(header.original_size ? (size_t)header.original_size : 1);
|
|
286
314
|
if (buf == NULL) {
|
|
287
315
|
if (errbuf)
|
|
288
316
|
snprintf(errbuf, MCDB_ERRLEN, "MCDB: out of memory");
|
|
289
317
|
return MCDB_ERR_ALLOC;
|
|
290
318
|
}
|
|
291
|
-
|
|
292
|
-
st =
|
|
293
|
-
mcdb_decode_payload(in, in_len, original_size, buf, (size_t)original_size, out_len, errbuf);
|
|
319
|
+
st = mcdb_decode_into(in, in_len, buf, (size_t)header.original_size, out_len, errbuf);
|
|
294
320
|
if (st != MCDB_OK) {
|
|
295
321
|
free(buf);
|
|
296
322
|
return st;
|
|
297
323
|
}
|
|
324
|
+
if (out)
|
|
325
|
+
*out = buf;
|
|
326
|
+
else
|
|
327
|
+
free(buf);
|
|
328
|
+
return MCDB_OK;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
mcdb_status mcdb_decode_v2_into(const unsigned char *in, size_t in_len,
|
|
332
|
+
uint64_t supplied_dictionary_ref, const unsigned char *dictionary,
|
|
333
|
+
size_t dictionary_len, ZSTD_DCtx *dctx, ZSTD_DDict *ddict,
|
|
334
|
+
unsigned char *out, size_t out_capacity, size_t *out_len,
|
|
335
|
+
char *errbuf) {
|
|
336
|
+
mcdb_header header;
|
|
337
|
+
const unsigned char *frame;
|
|
338
|
+
size_t frame_len;
|
|
339
|
+
size_t produced;
|
|
340
|
+
uint32_t dictionary_id;
|
|
341
|
+
uint32_t frame_dictionary_id;
|
|
342
|
+
mcdb_status st;
|
|
343
|
+
int own_dctx = 0;
|
|
344
|
+
|
|
345
|
+
if (out_len)
|
|
346
|
+
*out_len = 0;
|
|
347
|
+
if (errbuf)
|
|
348
|
+
errbuf[0] = '\0';
|
|
349
|
+
st = mcdb_parse_header(in, in_len, &header);
|
|
350
|
+
if (st != MCDB_OK)
|
|
351
|
+
return st;
|
|
352
|
+
if (header.version != MCDB_VERSION_V2)
|
|
353
|
+
return MCDB_ERR_VERSION;
|
|
354
|
+
if (supplied_dictionary_ref != header.dictionary_ref)
|
|
355
|
+
return MCDB_ERR_DICTIONARY_REF;
|
|
356
|
+
if (out == NULL || out_capacity < header.original_size)
|
|
357
|
+
return MCDB_ERR_SIZE_MISMATCH;
|
|
358
|
+
st = mcdb_validate_dictionary(dictionary, dictionary_len, &dictionary_id);
|
|
359
|
+
if (st != MCDB_OK)
|
|
360
|
+
return st;
|
|
361
|
+
st = mcdb_validate_frame(in, in_len, &header, &frame, &frame_len, errbuf);
|
|
362
|
+
if (st != MCDB_OK)
|
|
363
|
+
return st;
|
|
364
|
+
frame_dictionary_id = mcdb_zstd_frame_dictionary_id(frame, frame_len);
|
|
365
|
+
if (frame_dictionary_id == 0 || frame_dictionary_id != dictionary_id)
|
|
366
|
+
return MCDB_ERR_DICTIONARY_ID;
|
|
367
|
+
if (ddict == NULL)
|
|
368
|
+
return MCDB_ERR_DICTIONARY_REQUIRED;
|
|
369
|
+
if (dctx == NULL) {
|
|
370
|
+
dctx = ZSTD_createDCtx();
|
|
371
|
+
if (dctx == NULL)
|
|
372
|
+
return MCDB_ERR_ALLOC;
|
|
373
|
+
own_dctx = 1;
|
|
374
|
+
}
|
|
375
|
+
produced = ZSTD_decompress_usingDDict(dctx, out, (size_t)header.original_size, frame, frame_len,
|
|
376
|
+
ddict);
|
|
377
|
+
if (own_dctx)
|
|
378
|
+
ZSTD_freeDCtx(dctx);
|
|
379
|
+
if (ZSTD_isError(produced)) {
|
|
380
|
+
if (errbuf)
|
|
381
|
+
snprintf(errbuf, MCDB_ERRLEN, "MCDB: zstd dictionary error: %s",
|
|
382
|
+
ZSTD_getErrorName(produced));
|
|
383
|
+
return MCDB_ERR_DECOMPRESS;
|
|
384
|
+
}
|
|
385
|
+
return mcdb_finish_decoded(in, &header, out, produced, out_len, errbuf);
|
|
386
|
+
}
|
|
298
387
|
|
|
388
|
+
mcdb_status mcdb_decode_v2(const unsigned char *in, size_t in_len, uint64_t supplied_dictionary_ref,
|
|
389
|
+
const unsigned char *dictionary, size_t dictionary_len,
|
|
390
|
+
unsigned char **out, size_t *out_len, char *errbuf) {
|
|
391
|
+
mcdb_header header;
|
|
392
|
+
ZSTD_DDict *ddict;
|
|
393
|
+
mcdb_status st;
|
|
394
|
+
unsigned char *buf;
|
|
395
|
+
if (out)
|
|
396
|
+
*out = NULL;
|
|
397
|
+
if (out_len)
|
|
398
|
+
*out_len = 0;
|
|
399
|
+
st = mcdb_validate_v2_header(in, in_len, &header.original_size, NULL);
|
|
400
|
+
if (st != MCDB_OK)
|
|
401
|
+
return st;
|
|
402
|
+
st = mcdb_validate_dictionary(dictionary, dictionary_len, NULL);
|
|
403
|
+
if (st != MCDB_OK)
|
|
404
|
+
return st;
|
|
405
|
+
ddict = ZSTD_createDDict(dictionary, dictionary_len);
|
|
406
|
+
if (ddict == NULL)
|
|
407
|
+
return MCDB_ERR_ALLOC;
|
|
408
|
+
buf = (unsigned char *)malloc(header.original_size ? (size_t)header.original_size : 1);
|
|
409
|
+
if (buf == NULL) {
|
|
410
|
+
ZSTD_freeDDict(ddict);
|
|
411
|
+
return MCDB_ERR_ALLOC;
|
|
412
|
+
}
|
|
413
|
+
st = mcdb_decode_v2_into(in, in_len, supplied_dictionary_ref, dictionary, dictionary_len, NULL,
|
|
414
|
+
ddict, buf, (size_t)header.original_size, out_len, errbuf);
|
|
415
|
+
ZSTD_freeDDict(ddict);
|
|
416
|
+
if (st != MCDB_OK) {
|
|
417
|
+
free(buf);
|
|
418
|
+
return st;
|
|
419
|
+
}
|
|
299
420
|
if (out)
|
|
300
421
|
*out = buf;
|
|
301
422
|
else
|
|
@@ -303,6 +424,130 @@ mcdb_status mcdb_decode(const unsigned char *in, size_t in_len, unsigned char **
|
|
|
303
424
|
return MCDB_OK;
|
|
304
425
|
}
|
|
305
426
|
|
|
427
|
+
/* Tiny SHA-256 implementation; dictionary registry validation must not depend on pgcrypto/OpenSSL.
|
|
428
|
+
*/
|
|
429
|
+
typedef struct {
|
|
430
|
+
uint32_t state[8];
|
|
431
|
+
uint64_t bitlen;
|
|
432
|
+
unsigned char data[64];
|
|
433
|
+
size_t datalen;
|
|
434
|
+
} mcdb_sha256_ctx;
|
|
435
|
+
|
|
436
|
+
#define MCDB_ROTR32(x, n) (((x) >> (n)) | ((x) << (32u - (n))))
|
|
437
|
+
#define MCDB_CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
|
438
|
+
#define MCDB_MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
|
439
|
+
#define MCDB_EP0(x) (MCDB_ROTR32((x), 2) ^ MCDB_ROTR32((x), 13) ^ MCDB_ROTR32((x), 22))
|
|
440
|
+
#define MCDB_EP1(x) (MCDB_ROTR32((x), 6) ^ MCDB_ROTR32((x), 11) ^ MCDB_ROTR32((x), 25))
|
|
441
|
+
#define MCDB_SIG0(x) (MCDB_ROTR32((x), 7) ^ MCDB_ROTR32((x), 18) ^ ((x) >> 3))
|
|
442
|
+
#define MCDB_SIG1(x) (MCDB_ROTR32((x), 17) ^ MCDB_ROTR32((x), 19) ^ ((x) >> 10))
|
|
443
|
+
|
|
444
|
+
static const uint32_t MCDB_SHA256_K[64] = {
|
|
445
|
+
0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U,
|
|
446
|
+
0xab1c5ed5U, 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU,
|
|
447
|
+
0x9bdc06a7U, 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU,
|
|
448
|
+
0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
|
|
449
|
+
0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
|
|
450
|
+
0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U, 0xa2bfe8a1U, 0xa81a664bU,
|
|
451
|
+
0xc24b8b70U, 0xc76c51a3U, 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U,
|
|
452
|
+
0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
|
|
453
|
+
0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U,
|
|
454
|
+
0xc67178f2U,
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
static void mcdb_sha256_transform(mcdb_sha256_ctx *ctx, const unsigned char data[64]) {
|
|
458
|
+
uint32_t m[64];
|
|
459
|
+
uint32_t a, b, c, d, e, f, g, h;
|
|
460
|
+
uint32_t t1, t2;
|
|
461
|
+
size_t i;
|
|
462
|
+
for (i = 0; i < 16; i++) {
|
|
463
|
+
m[i] = ((uint32_t)data[i * 4] << 24) | ((uint32_t)data[i * 4 + 1] << 16) |
|
|
464
|
+
((uint32_t)data[i * 4 + 2] << 8) | (uint32_t)data[i * 4 + 3];
|
|
465
|
+
}
|
|
466
|
+
for (i = 16; i < 64; i++)
|
|
467
|
+
m[i] = MCDB_SIG1(m[i - 2]) + m[i - 7] + MCDB_SIG0(m[i - 15]) + m[i - 16];
|
|
468
|
+
a = ctx->state[0];
|
|
469
|
+
b = ctx->state[1];
|
|
470
|
+
c = ctx->state[2];
|
|
471
|
+
d = ctx->state[3];
|
|
472
|
+
e = ctx->state[4];
|
|
473
|
+
f = ctx->state[5];
|
|
474
|
+
g = ctx->state[6];
|
|
475
|
+
h = ctx->state[7];
|
|
476
|
+
for (i = 0; i < 64; i++) {
|
|
477
|
+
t1 = h + MCDB_EP1(e) + MCDB_CH(e, f, g) + MCDB_SHA256_K[i] + m[i];
|
|
478
|
+
t2 = MCDB_EP0(a) + MCDB_MAJ(a, b, c);
|
|
479
|
+
h = g;
|
|
480
|
+
g = f;
|
|
481
|
+
f = e;
|
|
482
|
+
e = d + t1;
|
|
483
|
+
d = c;
|
|
484
|
+
c = b;
|
|
485
|
+
b = a;
|
|
486
|
+
a = t1 + t2;
|
|
487
|
+
}
|
|
488
|
+
ctx->state[0] += a;
|
|
489
|
+
ctx->state[1] += b;
|
|
490
|
+
ctx->state[2] += c;
|
|
491
|
+
ctx->state[3] += d;
|
|
492
|
+
ctx->state[4] += e;
|
|
493
|
+
ctx->state[5] += f;
|
|
494
|
+
ctx->state[6] += g;
|
|
495
|
+
ctx->state[7] += h;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
static void mcdb_sha256_init(mcdb_sha256_ctx *ctx) {
|
|
499
|
+
static const uint32_t initial[8] = {0x6a09e667U, 0xbb67ae85U, 0x3c6ef372U, 0xa54ff53aU,
|
|
500
|
+
0x510e527fU, 0x9b05688cU, 0x1f83d9abU, 0x5be0cd19U};
|
|
501
|
+
memcpy(ctx->state, initial, sizeof(initial));
|
|
502
|
+
ctx->bitlen = 0;
|
|
503
|
+
ctx->datalen = 0;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
static void mcdb_sha256_update(mcdb_sha256_ctx *ctx, const unsigned char *data, size_t len) {
|
|
507
|
+
size_t i;
|
|
508
|
+
for (i = 0; i < len; i++) {
|
|
509
|
+
ctx->data[ctx->datalen++] = data[i];
|
|
510
|
+
if (ctx->datalen == 64) {
|
|
511
|
+
mcdb_sha256_transform(ctx, ctx->data);
|
|
512
|
+
ctx->bitlen += 512;
|
|
513
|
+
ctx->datalen = 0;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
static void mcdb_sha256_final(mcdb_sha256_ctx *ctx, unsigned char out[MCDB_SHA256_BYTES]) {
|
|
519
|
+
size_t i;
|
|
520
|
+
uint64_t bitlen;
|
|
521
|
+
ctx->bitlen += (uint64_t)ctx->datalen * 8u;
|
|
522
|
+
ctx->data[ctx->datalen++] = 0x80;
|
|
523
|
+
if (ctx->datalen > 56) {
|
|
524
|
+
while (ctx->datalen < 64)
|
|
525
|
+
ctx->data[ctx->datalen++] = 0;
|
|
526
|
+
mcdb_sha256_transform(ctx, ctx->data);
|
|
527
|
+
ctx->datalen = 0;
|
|
528
|
+
}
|
|
529
|
+
while (ctx->datalen < 56)
|
|
530
|
+
ctx->data[ctx->datalen++] = 0;
|
|
531
|
+
bitlen = ctx->bitlen;
|
|
532
|
+
for (i = 0; i < 8; i++)
|
|
533
|
+
ctx->data[63 - i] = (unsigned char)(bitlen >> (8u * i));
|
|
534
|
+
mcdb_sha256_transform(ctx, ctx->data);
|
|
535
|
+
for (i = 0; i < 8; i++) {
|
|
536
|
+
out[i * 4] = (unsigned char)(ctx->state[i] >> 24);
|
|
537
|
+
out[i * 4 + 1] = (unsigned char)(ctx->state[i] >> 16);
|
|
538
|
+
out[i * 4 + 2] = (unsigned char)(ctx->state[i] >> 8);
|
|
539
|
+
out[i * 4 + 3] = (unsigned char)ctx->state[i];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
void mcdb_sha256(const unsigned char *data, size_t len, unsigned char out[MCDB_SHA256_BYTES]) {
|
|
544
|
+
mcdb_sha256_ctx ctx;
|
|
545
|
+
mcdb_sha256_init(&ctx);
|
|
546
|
+
if (data != NULL && len > 0)
|
|
547
|
+
mcdb_sha256_update(&ctx, data, len);
|
|
548
|
+
mcdb_sha256_final(&ctx, out);
|
|
549
|
+
}
|
|
550
|
+
|
|
306
551
|
const char *mcdb_status_str(mcdb_status s) {
|
|
307
552
|
switch (s) {
|
|
308
553
|
case MCDB_OK:
|
|
@@ -321,6 +566,14 @@ const char *mcdb_status_str(mcdb_status s) {
|
|
|
321
566
|
return "reserved flags must be 0";
|
|
322
567
|
case MCDB_ERR_SIZE_LIMIT:
|
|
323
568
|
return "declared size over limit";
|
|
569
|
+
case MCDB_ERR_DICTIONARY_REQUIRED:
|
|
570
|
+
return "dictionary is required";
|
|
571
|
+
case MCDB_ERR_DICTIONARY_REF:
|
|
572
|
+
return "dictionary reference mismatch or invalid reference";
|
|
573
|
+
case MCDB_ERR_DICTIONARY_SIZE:
|
|
574
|
+
return "dictionary is empty or over limit";
|
|
575
|
+
case MCDB_ERR_DICTIONARY_ID:
|
|
576
|
+
return "zstd dictionary identifier mismatch or missing identifier";
|
|
324
577
|
case MCDB_ERR_DECOMPRESS:
|
|
325
578
|
return "corrupt zstd payload";
|
|
326
579
|
case MCDB_ERR_TRAILING_DATA:
|