sql_cli/sql/functions/
bigint.rs

1use crate::data::datatable::DataValue;
2use crate::sql::functions::{ArgCount, FunctionCategory, FunctionSignature, SqlFunction};
3use anyhow::{anyhow, Result};
4use num_bigint::BigInt;
5use num_traits::{One, Signed, Zero};
6
7/// BIGINT - Convert to arbitrary precision integer
8pub struct BigIntFunction;
9
10impl SqlFunction for BigIntFunction {
11    fn signature(&self) -> FunctionSignature {
12        FunctionSignature {
13            name: "BIGINT",
14            category: FunctionCategory::BigNumber,
15            arg_count: ArgCount::Fixed(1),
16            description: "Convert value to arbitrary precision integer",
17            returns: "String representation of big integer",
18            examples: vec![
19                "SELECT BIGINT('123456789012345678901234567890')",
20                "SELECT BIGINT(2) ^ BIGINT(100)  -- 2^100",
21            ],
22        }
23    }
24
25    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
26        if args.len() != 1 {
27            return Err(anyhow!("BIGINT expects 1 argument"));
28        }
29
30        match &args[0] {
31            DataValue::String(s) => {
32                match s.parse::<BigInt>() {
33                    Ok(_) => Ok(DataValue::String(s.clone())), // Valid bigint string
34                    Err(_) => Err(anyhow!("Invalid big integer format: {}", s)),
35                }
36            }
37            DataValue::Integer(n) => Ok(DataValue::String(n.to_string())),
38            DataValue::Float(f) => Ok(DataValue::String((*f as i64).to_string())),
39            DataValue::Null => Ok(DataValue::Null),
40            _ => Err(anyhow!("BIGINT expects numeric or string input")),
41        }
42    }
43}
44
45/// BIGADD - Add two arbitrary precision integers
46pub struct BigAddFunction;
47
48impl SqlFunction for BigAddFunction {
49    fn signature(&self) -> FunctionSignature {
50        FunctionSignature {
51            name: "BIGADD",
52            category: FunctionCategory::BigNumber,
53            arg_count: ArgCount::Fixed(2),
54            description: "Add two arbitrary precision integers",
55            returns: "String representation of sum",
56            examples: vec![
57                "SELECT BIGADD('999999999999999999999', '1')",
58                "SELECT BIGADD('123456789012345678901234567890', '987654321098765432109876543210')",
59            ],
60        }
61    }
62
63    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
64        if args.len() != 2 {
65            return Err(anyhow!("BIGADD expects 2 arguments"));
66        }
67
68        let a = parse_bigint(&args[0])?;
69        let b = parse_bigint(&args[1])?;
70
71        Ok(DataValue::String((a + b).to_string()))
72    }
73}
74
75/// BIGMUL - Multiply two arbitrary precision integers
76pub struct BigMulFunction;
77
78impl SqlFunction for BigMulFunction {
79    fn signature(&self) -> FunctionSignature {
80        FunctionSignature {
81            name: "BIGMUL",
82            category: FunctionCategory::BigNumber,
83            arg_count: ArgCount::Fixed(2),
84            description: "Multiply two arbitrary precision integers",
85            returns: "String representation of product",
86            examples: vec![
87                "SELECT BIGMUL('999999999999999999999', '999999999999999999999')",
88                "SELECT BIGMUL('123456789', '987654321')",
89            ],
90        }
91    }
92
93    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
94        if args.len() != 2 {
95            return Err(anyhow!("BIGMUL expects 2 arguments"));
96        }
97
98        let a = parse_bigint(&args[0])?;
99        let b = parse_bigint(&args[1])?;
100
101        Ok(DataValue::String((a * b).to_string()))
102    }
103}
104
105/// BIGPOW - Raise arbitrary precision integer to a power
106pub struct BigPowFunction;
107
108impl SqlFunction for BigPowFunction {
109    fn signature(&self) -> FunctionSignature {
110        FunctionSignature {
111            name: "BIGPOW",
112            category: FunctionCategory::BigNumber,
113            arg_count: ArgCount::Fixed(2),
114            description: "Raise big integer to a power (base^exponent)",
115            returns: "String representation of result",
116            examples: vec![
117                "SELECT BIGPOW('2', 100)    -- 2^100",
118                "SELECT BIGPOW('10', 50)    -- 10^50",
119                "SELECT BIGPOW('99', 99)    -- 99^99",
120            ],
121        }
122    }
123
124    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
125        if args.len() != 2 {
126            return Err(anyhow!("BIGPOW expects 2 arguments"));
127        }
128
129        let base = parse_bigint(&args[0])?;
130        let exp = match &args[1] {
131            DataValue::Integer(n) => *n as u32,
132            DataValue::String(s) => s
133                .parse::<u32>()
134                .map_err(|_| anyhow!("Exponent must be a non-negative integer"))?,
135            _ => return Err(anyhow!("Exponent must be a non-negative integer")),
136        };
137
138        let result = base.pow(exp);
139        Ok(DataValue::String(result.to_string()))
140    }
141}
142
143/// BIGFACT - Calculate factorial of large numbers
144pub struct BigFactorialFunction;
145
146impl SqlFunction for BigFactorialFunction {
147    fn signature(&self) -> FunctionSignature {
148        FunctionSignature {
149            name: "BIGFACT",
150            category: FunctionCategory::BigNumber,
151            arg_count: ArgCount::Fixed(1),
152            description: "Calculate factorial of a number (n!)",
153            returns: "String representation of factorial",
154            examples: vec![
155                "SELECT BIGFACT(50)     -- 50!",
156                "SELECT BIGFACT(100)    -- 100!",
157                "SELECT LENGTH(BIGFACT(1000))  -- How many digits in 1000!",
158            ],
159        }
160    }
161
162    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
163        if args.len() != 1 {
164            return Err(anyhow!("BIGFACT expects 1 argument"));
165        }
166
167        let n = match &args[0] {
168            DataValue::Integer(n) => *n as u32,
169            DataValue::String(s) => s
170                .parse::<u32>()
171                .map_err(|_| anyhow!("Factorial input must be a non-negative integer"))?,
172            _ => return Err(anyhow!("Factorial input must be a non-negative integer")),
173        };
174
175        if n > 10000 {
176            return Err(anyhow!("Factorial input too large (max 10000)"));
177        }
178
179        let mut result = BigInt::one();
180        for i in 2..=n {
181            result *= i;
182        }
183
184        Ok(DataValue::String(result.to_string()))
185    }
186}
187
188/// TO_BINARY - Convert number to binary string
189pub struct ToBinaryFunction;
190
191impl SqlFunction for ToBinaryFunction {
192    fn signature(&self) -> FunctionSignature {
193        FunctionSignature {
194            name: "TO_BINARY",
195            category: FunctionCategory::BigNumber,
196            arg_count: ArgCount::Fixed(1),
197            description: "Convert number to binary string representation",
198            returns: "Binary string (e.g., '1010' for 10)",
199            examples: vec![
200                "SELECT TO_BINARY(42)                     -- '101010'",
201                "SELECT TO_BINARY('255')                  -- '11111111'",
202                "SELECT TO_BINARY(BIGPOW('2', 100))      -- Binary of 2^100",
203            ],
204        }
205    }
206
207    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
208        if args.len() != 1 {
209            return Err(anyhow!("TO_BINARY expects 1 argument"));
210        }
211
212        let num = parse_bigint(&args[0])?;
213        if num.sign() == num_bigint::Sign::Minus {
214            // For negative numbers, we'll show two's complement representation
215            // with a fixed bit width (64 bits for demonstration)
216            return Ok(DataValue::String(format!("-{}", num.abs().to_str_radix(2))));
217        }
218
219        Ok(DataValue::String(num.to_str_radix(2)))
220    }
221}
222
223/// FROM_BINARY - Convert binary string to decimal
224pub struct FromBinaryFunction;
225
226impl SqlFunction for FromBinaryFunction {
227    fn signature(&self) -> FunctionSignature {
228        FunctionSignature {
229            name: "FROM_BINARY",
230            category: FunctionCategory::BigNumber,
231            arg_count: ArgCount::Fixed(1),
232            description: "Convert binary string to decimal number",
233            returns: "Decimal string representation",
234            examples: vec![
235                "SELECT FROM_BINARY('101010')             -- '42'",
236                "SELECT FROM_BINARY('11111111')           -- '255'",
237                "SELECT FROM_BINARY('1' || REPEAT('0', 100)) -- 2^100",
238            ],
239        }
240    }
241
242    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
243        if args.len() != 1 {
244            return Err(anyhow!("FROM_BINARY expects 1 argument"));
245        }
246
247        let binary_str = match &args[0] {
248            DataValue::String(s) => s,
249            _ => return Err(anyhow!("FROM_BINARY expects a string argument")),
250        };
251
252        // Remove any spaces and validate
253        let clean_binary: String = binary_str
254            .chars()
255            .filter(|c| *c == '0' || *c == '1')
256            .collect();
257
258        if clean_binary.is_empty() {
259            return Err(anyhow!("Invalid binary string"));
260        }
261
262        match BigInt::parse_bytes(clean_binary.as_bytes(), 2) {
263            Some(num) => Ok(DataValue::String(num.to_string())),
264            None => Err(anyhow!("Invalid binary string: {}", binary_str)),
265        }
266    }
267}
268
269/// TO_HEX - Convert number to hexadecimal string
270pub struct ToHexFunction;
271
272impl SqlFunction for ToHexFunction {
273    fn signature(&self) -> FunctionSignature {
274        FunctionSignature {
275            name: "TO_HEX",
276            category: FunctionCategory::BigNumber,
277            arg_count: ArgCount::Fixed(1),
278            description: "Convert number to hexadecimal string",
279            returns: "Hexadecimal string (e.g., '2A' for 42)",
280            examples: vec![
281                "SELECT TO_HEX(255)                       -- 'ff'",
282                "SELECT TO_HEX(BIGPOW('16', 10))         -- '10000000000'",
283            ],
284        }
285    }
286
287    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
288        if args.len() != 1 {
289            return Err(anyhow!("TO_HEX expects 1 argument"));
290        }
291
292        let num = parse_bigint(&args[0])?;
293        if num.sign() == num_bigint::Sign::Minus {
294            return Ok(DataValue::String(format!(
295                "-{}",
296                num.abs().to_str_radix(16)
297            )));
298        }
299
300        Ok(DataValue::String(num.to_str_radix(16)))
301    }
302}
303
304/// FROM_HEX - Convert hexadecimal string to decimal
305pub struct FromHexFunction;
306
307impl SqlFunction for FromHexFunction {
308    fn signature(&self) -> FunctionSignature {
309        FunctionSignature {
310            name: "FROM_HEX",
311            category: FunctionCategory::BigNumber,
312            arg_count: ArgCount::Fixed(1),
313            description: "Convert hexadecimal string to decimal",
314            returns: "Decimal string representation",
315            examples: vec![
316                "SELECT FROM_HEX('FF')                    -- '255'",
317                "SELECT FROM_HEX('DEADBEEF')              -- '3735928559'",
318            ],
319        }
320    }
321
322    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
323        if args.len() != 1 {
324            return Err(anyhow!("FROM_HEX expects 1 argument"));
325        }
326
327        let hex_str = match &args[0] {
328            DataValue::String(s) => s,
329            _ => return Err(anyhow!("FROM_HEX expects a string argument")),
330        };
331
332        // Remove 0x prefix if present and clean
333        let clean_hex = hex_str
334            .trim()
335            .trim_start_matches("0x")
336            .trim_start_matches("0X");
337
338        match BigInt::parse_bytes(clean_hex.as_bytes(), 16) {
339            Some(num) => Ok(DataValue::String(num.to_string())),
340            None => Err(anyhow!("Invalid hexadecimal string: {}", hex_str)),
341        }
342    }
343}
344
345/// BITAND - Bitwise AND of two numbers
346pub struct BitAndFunction;
347
348impl SqlFunction for BitAndFunction {
349    fn signature(&self) -> FunctionSignature {
350        FunctionSignature {
351            name: "BITAND",
352            category: FunctionCategory::BigNumber,
353            arg_count: ArgCount::Fixed(2),
354            description: "Bitwise AND of two integers",
355            returns: "Result of bitwise AND",
356            examples: vec![
357                "SELECT BITAND(12, 10)                    -- 8 (1100 & 1010 = 1000)",
358                "SELECT TO_BINARY(BITAND(255, 15))       -- '1111'",
359            ],
360        }
361    }
362
363    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
364        if args.len() != 2 {
365            return Err(anyhow!("BITAND expects 2 arguments"));
366        }
367
368        let a = parse_bigint(&args[0])?;
369        let b = parse_bigint(&args[1])?;
370
371        Ok(DataValue::String((a & b).to_string()))
372    }
373}
374
375/// BITOR - Bitwise OR of two numbers
376pub struct BitOrFunction;
377
378impl SqlFunction for BitOrFunction {
379    fn signature(&self) -> FunctionSignature {
380        FunctionSignature {
381            name: "BITOR",
382            category: FunctionCategory::BigNumber,
383            arg_count: ArgCount::Fixed(2),
384            description: "Bitwise OR of two integers",
385            returns: "Result of bitwise OR",
386            examples: vec![
387                "SELECT BITOR(12, 10)                     -- 14 (1100 | 1010 = 1110)",
388                "SELECT TO_BINARY(BITOR(8, 4))           -- '1100'",
389            ],
390        }
391    }
392
393    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
394        if args.len() != 2 {
395            return Err(anyhow!("BITOR expects 2 arguments"));
396        }
397
398        let a = parse_bigint(&args[0])?;
399        let b = parse_bigint(&args[1])?;
400
401        Ok(DataValue::String((a | b).to_string()))
402    }
403}
404
405/// BITXOR - Bitwise XOR of two numbers
406pub struct BitXorFunction;
407
408impl SqlFunction for BitXorFunction {
409    fn signature(&self) -> FunctionSignature {
410        FunctionSignature {
411            name: "BITXOR",
412            category: FunctionCategory::BigNumber,
413            arg_count: ArgCount::Fixed(2),
414            description: "Bitwise XOR of two integers",
415            returns: "Result of bitwise XOR",
416            examples: vec![
417                "SELECT BITXOR(12, 10)                    -- 6 (1100 ^ 1010 = 0110)",
418                "SELECT TO_BINARY(BITXOR(255, 170))      -- '01010101'",
419            ],
420        }
421    }
422
423    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
424        if args.len() != 2 {
425            return Err(anyhow!("BITXOR expects 2 arguments"));
426        }
427
428        let a = parse_bigint(&args[0])?;
429        let b = parse_bigint(&args[1])?;
430
431        Ok(DataValue::String((a ^ b).to_string()))
432    }
433}
434
435/// BITSHIFT - Bit shift left (positive) or right (negative)
436pub struct BitShiftFunction;
437
438impl SqlFunction for BitShiftFunction {
439    fn signature(&self) -> FunctionSignature {
440        FunctionSignature {
441            name: "BITSHIFT",
442            category: FunctionCategory::BigNumber,
443            arg_count: ArgCount::Fixed(2),
444            description: "Bit shift: left for positive shift, right for negative",
445            returns: "Result of bit shift",
446            examples: vec![
447                "SELECT BITSHIFT(1, 10)                   -- 1024 (1 << 10)",
448                "SELECT BITSHIFT(1024, -10)               -- 1 (1024 >> 10)",
449                "SELECT TO_BINARY(BITSHIFT(1, 100))       -- 1 followed by 100 zeros",
450            ],
451        }
452    }
453
454    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
455        if args.len() != 2 {
456            return Err(anyhow!("BITSHIFT expects 2 arguments"));
457        }
458
459        let num = parse_bigint(&args[0])?;
460        let shift = match &args[1] {
461            DataValue::Integer(n) => *n,
462            DataValue::String(s) => s
463                .parse::<i64>()
464                .map_err(|_| anyhow!("Shift amount must be an integer"))?,
465            _ => return Err(anyhow!("Shift amount must be an integer")),
466        };
467
468        let result = if shift >= 0 {
469            num << (shift as usize)
470        } else {
471            num >> ((-shift) as usize)
472        };
473
474        Ok(DataValue::String(result.to_string()))
475    }
476}
477
478// Helper function to parse DataValue to BigInt
479fn parse_bigint(value: &DataValue) -> Result<BigInt> {
480    match value {
481        DataValue::String(s) => s
482            .parse::<BigInt>()
483            .map_err(|_| anyhow!("Invalid big integer format: {}", s)),
484        DataValue::Integer(n) => Ok(BigInt::from(*n)),
485        DataValue::Float(f) => Ok(BigInt::from(*f as i64)),
486        DataValue::Null => Ok(BigInt::zero()),
487        _ => Err(anyhow!("Expected numeric or string value for big integer")),
488    }
489}