|
| 1 | +PostgreSQL contrib module int16 |
| 2 | +=================================== |
| 3 | + |
| 4 | +This module provides the int16 data type, a 128-bit signed integer with a |
| 5 | +range of approximately -1.7e38 to +1.7e38. |
| 6 | + |
| 7 | +DESCRIPTION |
| 8 | +----------- |
| 9 | + |
| 10 | +The int16 extension adds a 128-bit signed integer data type to PostgreSQL, |
| 11 | +extending the built-in int8 (bigint) type. It is designed for applications |
| 12 | +that require integer values beyond the 64-bit range. |
| 13 | + |
| 14 | +Key features: |
| 15 | +- Storage: 16 bytes, passed by reference, aligned on 8-byte boundary |
| 16 | +- Full arithmetic: +, -, *, /, %, unary -, unary +, abs() |
| 17 | +- Full comparison: =, <>, <, >, <=, >=, and 3-way cmp() |
| 18 | +- Bitwise operators: &, |, #, ~, <<, >> |
| 19 | +- Cross-type operations with int2, int4, int8 (arithmetic and comparison) |
| 20 | +- Type casts: implicit from int2/int4/int8/numeric, assignment to int2/int4/int8/numeric |
| 21 | +- B-tree and Hash index support (including deduplication and skip scan) |
| 22 | +- Aggregates: sum(), avg(), min(), max() (parallel-safe) |
| 23 | +- Window functions: RANGE support via in_range() |
| 24 | +- generate_series() for int16 ranges |
| 25 | +- Mathematical functions: gcd(), lcm(), factorial() |
| 26 | + |
| 27 | + |
| 28 | +BUILDING |
| 29 | +-------- |
| 30 | + |
| 31 | +To build the module from the PostgreSQL source tree: |
| 32 | + |
| 33 | + cd contrib/int16 |
| 34 | + make USE_PGXS=1 |
| 35 | + make USE_PGXS=1 install |
| 36 | + |
| 37 | +After installation, enable the extension in your database: |
| 38 | + |
| 39 | + CREATE EXTENSION int16; |
| 40 | + |
| 41 | +USAGE |
| 42 | +----- |
| 43 | + |
| 44 | +Once installed, the int16 type is available in all schemas. |
| 45 | + |
| 46 | +Basic usage: |
| 47 | + |
| 48 | + SELECT '123456789012345678901234567890'::int16; |
| 49 | + |
| 50 | +Create tables with int16 columns: |
| 51 | + |
| 52 | + CREATE TABLE t (id serial PRIMARY KEY, value int16); |
| 53 | + INSERT INTO t (value) VALUES ('170141183460469231731687303715884105727'::int16); |
| 54 | + SELECT * FROM t WHERE value > '100000000000000000000'::int16; |
| 55 | + |
| 56 | +FUNCTIONS AND OPERATORS |
| 57 | +----------------------- |
| 58 | + |
| 59 | +Input/Output: |
| 60 | + int16in(cstring) - Parse string to int16 |
| 61 | + int16out(int16) - Convert int16 to string |
| 62 | + int16recv(internal) - Receive binary data (16 bytes, network byte order) |
| 63 | + int16send(int16) - Send binary data |
| 64 | + |
| 65 | +Arithmetic (int16 op int16): |
| 66 | + + int16pl - Addition |
| 67 | + - int16mi - Subtraction |
| 68 | + * int16mul - Multiplication |
| 69 | + / int16div - Integer division |
| 70 | + % int16mod - Remainder |
| 71 | + - int16um - Unary minus |
| 72 | + + int16up - Unary plus |
| 73 | + @ int16abs - Absolute value |
| 74 | + |
| 75 | +Comparison (int16 op int16): |
| 76 | + = int16eq - Equal |
| 77 | + <> int16ne - Not equal |
| 78 | + < int16lt - Less than |
| 79 | + > int16gt - Greater than |
| 80 | + <= int16le - Less than or equal |
| 81 | + >= int16ge - Greater than or equal |
| 82 | + int16_cmp(a,b) - Three-way comparison (-1, 0, 1) |
| 83 | + |
| 84 | +Bitwise: |
| 85 | + & int16and - Bitwise AND |
| 86 | + | int16or - Bitwise OR |
| 87 | + # int16xor - Bitwise XOR |
| 88 | + ~ int16not - Bitwise NOT |
| 89 | + << int16shl - Left shift (n is int4) |
| 90 | + >> int16shr - Arithmetic right shift (n is int4) |
| 91 | + |
| 92 | +Cross-type arithmetic (int16 with int8/int4/int2, both directions): |
| 93 | + +, -, *, / - Functions: int168pl, int816pl, int164pl, int416pl, etc. |
| 94 | + |
| 95 | +Cross-type comparison (int16 with int8/int4/int2, both directions): |
| 96 | + =, <>, <, >, <=, >= - Functions: int168eq, int816eq, int164eq, etc. |
| 97 | + _cmp functions - int168cmp, int816cmp, int164cmp, etc. |
| 98 | + |
| 99 | +Type casts: |
| 100 | + int8/int4/int2 -> int16 IMPLICIT (widening) |
| 101 | + int16 -> int8/int4/int2 ASSIGNMENT (narrowing) |
| 102 | + int16 -> numeric IMPLICIT (widening) |
| 103 | + numeric -> int16 ASSIGNMENT (narrowing) |
| 104 | + |
| 105 | +Aggregates (parallel-safe): |
| 106 | + sum(int16) -> int16 - Sum (error on overflow) |
| 107 | + avg(int16) -> numeric - Average |
| 108 | + min(int16) -> int16 - Minimum |
| 109 | + max(int16) -> int16 - Maximum |
| 110 | + |
| 111 | +Mathematical functions: |
| 112 | + gcd(int16, int16) - Greatest common divisor |
| 113 | + lcm(int16, int16) - Least common multiple |
| 114 | + factorial(int16) - Factorial (returns numeric) |
| 115 | + |
| 116 | +generate_series: |
| 117 | + generate_series(start int16, stop int16) - Step 1 |
| 118 | + generate_series(start int16, stop int16, step int16) - Custom step |
| 119 | + |
| 120 | +Window functions: |
| 121 | + in_range(val int16, base int16, offset int16, ...) - RANGE frame support |
| 122 | + |
| 123 | +Index support: |
| 124 | + B-tree - int16_ops (includes sortsupport, in_range, equalimage, skipsupport) |
| 125 | + Hash - int16_ops |
| 126 | + |
| 127 | +EXAMPLES |
| 128 | +-------- |
| 129 | + |
| 130 | +1. Basic arithmetic: |
| 131 | + |
| 132 | + SELECT '100000000000000000000'::int16 + '1'::int16; |
| 133 | + -- 100000000000000000001 |
| 134 | + |
| 135 | + SELECT '100000000000000000000'::int16 * '2'::int16; |
| 136 | + -- 200000000000000000000 |
| 137 | + |
| 138 | + SELECT '100000000000000000000'::int16 / '3'::int16; |
| 139 | + -- 33333333333333333333 |
| 140 | + |
| 141 | + SELECT @('-100000000000000000000'::int16); |
| 142 | + -- 100000000000000000000 |
| 143 | + |
| 144 | +2. Cross-type operations: |
| 145 | + |
| 146 | + SELECT '100'::int16 + 50; -- int16 + int4 -> int16 |
| 147 | + SELECT 50 + '100'::int16; -- int4 + int16 -> int16 |
| 148 | + SELECT '100'::int16 + 50::int8; -- int16 + int8 -> int16 |
| 149 | + SELECT '100'::int16 = 100; -- true |
| 150 | + |
| 151 | +3. Aggregates: |
| 152 | + |
| 153 | + CREATE TABLE big_values (val int16); |
| 154 | + INSERT INTO big_values VALUES |
| 155 | + ('100000000000000000000'::int16), |
| 156 | + ('200000000000000000000'::int16), |
| 157 | + ('300000000000000000000'::int16); |
| 158 | + |
| 159 | + SELECT sum(val) FROM big_values; -- 600000000000000000000 |
| 160 | + SELECT avg(val) FROM big_values; -- 200000000000000000000.0000000000000000 |
| 161 | + |
| 162 | +4. generate_series: |
| 163 | + |
| 164 | + SELECT * FROM generate_series('1'::int16, '5'::int16); |
| 165 | + SELECT * FROM generate_series('5'::int16, '1'::int16, '-1'::int16); |
| 166 | + |
| 167 | +5. Window functions with RANGE: |
| 168 | + |
| 169 | + SELECT id, amount, count(*) OVER ( |
| 170 | + ORDER BY amount |
| 171 | + RANGE BETWEEN '10'::int16 PRECEDING AND '10'::int16 FOLLOWING |
| 172 | + ) FROM sales; |
| 173 | + |
| 174 | +6. B-tree and Hash indexes: |
| 175 | + |
| 176 | + CREATE TABLE t (val int16); |
| 177 | + CREATE INDEX ON t USING btree (val); |
| 178 | + CREATE INDEX ON t USING hash (val); |
| 179 | + |
| 180 | +LIMITATIONS |
| 181 | +----------- |
| 182 | + |
| 183 | +- Passed by reference: int16 is 16 bytes and passed by reference (like uuid), |
| 184 | + not by value (like int8). This may introduce slight overhead compared to int8. |
| 185 | + |
| 186 | +- Missing functions: ceil(), floor(), round(), sign(), sqrt(), width_bucket() |
| 187 | + are not provided. Cast to numeric for these operations: |
| 188 | + SELECT round('123'::int16::numeric); |
| 189 | + |
| 190 | +- avg() returns numeric: Average is computed in numeric because int16 cannot |
| 191 | + always represent the exact division result. |
| 192 | + |
| 193 | +- sum() can overflow: Sum is computed as int16 and raises an error on overflow |
| 194 | + (unlike sum(int8) which uses numeric internally). |
| 195 | + |
| 196 | +- factorial() limited to 32177: For n > 32177, the result overflows numeric. |
| 197 | + |
| 198 | +- No GiST, GIN, SP-GiST, BRIN support: Only B-tree and Hash indexes are |
| 199 | + implemented. |
| 200 | + |
| 201 | +- Binary protocol: int16recv expects exactly 16 bytes in network byte order |
| 202 | + (most significant 64-bit block first). |
| 203 | + |
| 204 | +- gcd and lcm with INT16_MIN: |
| 205 | + gcd(INT16_MIN, 0), gcd(INT16_MIN, INT16_MIN), and lcm(INT16_MAX, 2) |
| 206 | + raise overflow errors because the absolute value of INT16_MIN is not |
| 207 | + representable in 128 bits. gcd(INT16_MIN, -1) returns 1. |
| 208 | + |
| 209 | + |
| 210 | +TESTING |
| 211 | +------- |
| 212 | + |
| 213 | +Run the regression tests (requires a running PostgreSQL server): |
| 214 | + |
| 215 | + cd contrib/int16 |
| 216 | + make installcheck |
| 217 | + |
| 218 | +Test files are located in sql/, expected results in expected/. |
0 commit comments