Serenity Operating System
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

LibSQL: Support 64-bit integer values and handle overflow errors

Currently, integers are stored in LibSQL as 32-bit signed integers, even
if the provided type is unsigned. This resulted in a series of unchecked
unsigned-to-signed conversions, and prevented storing 64-bit values.
Further, mathematical operations were performed without similar checks,
and without checking for overflow.

This changes SQL::Value to behave like SQLite for INTEGER types. In
SQLite, the INTEGER type does not imply a size or signedness of the
underlying type. Instead, SQLite determines on-the-fly what type is
needed as values are created and updated.

To do so, the SQL::Value variant can now hold an i64 or u64 integer. If
a specific type is requested, invalid conversions are now explictly an
error (e.g. converting a stored -1 to a u64 will fail). When binary
mathematical operations are performed, we now try to coerce the RHS
value to a type that works with the LHS value, failing the operation if
that isn't possible. Any overflow or invalid operation (e.g. bitshifting
a 64-bit value by more than 64 bytes) is an error.

+1240 -282
+1 -1
Tests/LibSQL/TestSqlBtreeIndex.cpp
··· 211 211 if (prev.size()) { 212 212 EXPECT(prev < key); 213 213 } 214 - auto key_value = key[0].to_int(); 214 + auto key_value = key[0].to_int<i32>(); 215 215 for (auto ix = 0; ix < num_keys; ix++) { 216 216 if (keys[ix] == key_value) { 217 217 EXPECT_EQ(key.pointer(), pointers[ix]);
+2 -2
Tests/LibSQL/TestSqlDatabase.cpp
··· 68 68 EXPECT(!rows_or_error.is_error()); 69 69 for (auto& row : rows_or_error.value()) { 70 70 StringBuilder builder; 71 - builder.appendff("Test{}", row["IntColumn"].to_int().value()); 71 + builder.appendff("Test{}", row["IntColumn"].to_int<i32>().value()); 72 72 EXPECT_EQ(row["TextColumn"].to_deprecated_string(), builder.build()); 73 73 count++; 74 - sum += row["IntColumn"].to_int().value(); 74 + sum += row["IntColumn"].to_int<i32>().value(); 75 75 } 76 76 EXPECT_EQ(count, expected_count); 77 77 EXPECT_EQ(sum, (expected_count * (expected_count - 1)) / 2);
+1 -1
Tests/LibSQL/TestSqlHashIndex.cpp
··· 268 268 int count = 0; 269 269 for (auto iter = hash_index->begin(); !iter.is_end(); iter++, count++) { 270 270 auto key = (*iter); 271 - auto key_value = key[0].to_int(); 271 + auto key_value = key[0].to_int<i32>(); 272 272 VERIFY(key_value.has_value()); 273 273 274 274 for (auto ix = 0; ix < num_keys; ix++) {
+28 -28
Tests/LibSQL/TestSqlStatementExecution.cpp
··· 105 105 EXPECT(!rows_or_error.is_error()); 106 106 for (auto& row : rows_or_error.value()) { 107 107 EXPECT_EQ(row["TEXTCOLUMN"].to_deprecated_string(), "Test"); 108 - EXPECT_EQ(row["INTCOLUMN"].to_int().value(), 42); 108 + EXPECT_EQ(row["INTCOLUMN"].to_int<i32>(), 42); 109 109 count++; 110 110 } 111 111 EXPECT_EQ(count, 1); ··· 318 318 result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable WHERE IntColumn > 44;"); 319 319 EXPECT_EQ(result.size(), 2u); 320 320 for (auto& row : result) { 321 - EXPECT(row.row[1].to_int().value() > 44); 321 + EXPECT(row.row[1].to_int<i32>().value() > 44); 322 322 } 323 323 } 324 324 ··· 348 348 EXPECT_EQ(result.size(), 25u); 349 349 for (auto& row : result) { 350 350 EXPECT(row.row.size() == 4); 351 - EXPECT(row.row[1].to_int().value() >= 42); 352 - EXPECT(row.row[1].to_int().value() <= 46); 353 - EXPECT(row.row[3].to_int().value() >= 40); 354 - EXPECT(row.row[3].to_int().value() <= 48); 351 + EXPECT(row.row[1].to_int<i32>().value() >= 42); 352 + EXPECT(row.row[1].to_int<i32>().value() <= 46); 353 + EXPECT(row.row[3].to_int<i32>().value() >= 40); 354 + EXPECT(row.row[3].to_int<i32>().value() <= 48); 355 355 } 356 356 } 357 357 ··· 383 383 "WHERE TestTable1.IntColumn = TestTable2.IntColumn;"); 384 384 EXPECT_EQ(result.size(), 1u); 385 385 EXPECT_EQ(result[0].row.size(), 3u); 386 - EXPECT_EQ(result[0].row[0].to_int().value(), 42); 386 + EXPECT_EQ(result[0].row[0].to_int<i32>(), 42); 387 387 EXPECT_EQ(result[0].row[1].to_deprecated_string(), "Test_1"); 388 388 EXPECT_EQ(result[0].row[2].to_deprecated_string(), "Test_12"); 389 389 } ··· 463 463 464 464 result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY IntColumn;"); 465 465 EXPECT_EQ(result.size(), 5u); 466 - EXPECT_EQ(result[0].row[1].to_int().value(), 40); 467 - EXPECT_EQ(result[1].row[1].to_int().value(), 41); 468 - EXPECT_EQ(result[2].row[1].to_int().value(), 42); 469 - EXPECT_EQ(result[3].row[1].to_int().value(), 44); 470 - EXPECT_EQ(result[4].row[1].to_int().value(), 47); 466 + EXPECT_EQ(result[0].row[1].to_int<i32>(), 40); 467 + EXPECT_EQ(result[1].row[1].to_int<i32>(), 41); 468 + EXPECT_EQ(result[2].row[1].to_int<i32>(), 42); 469 + EXPECT_EQ(result[3].row[1].to_int<i32>(), 44); 470 + EXPECT_EQ(result[4].row[1].to_int<i32>(), 47); 471 471 472 472 result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY TextColumn;"); 473 473 EXPECT_EQ(result.size(), 5u); ··· 547 547 result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY TextColumn, IntColumn;"); 548 548 EXPECT_EQ(result.size(), 5u); 549 549 EXPECT_EQ(result[0].row[0].to_deprecated_string(), "Test_1"); 550 - EXPECT_EQ(result[0].row[1].to_int().value(), 47); 550 + EXPECT_EQ(result[0].row[1].to_int<i32>(), 47); 551 551 EXPECT_EQ(result[1].row[0].to_deprecated_string(), "Test_2"); 552 - EXPECT_EQ(result[1].row[1].to_int().value(), 40); 552 + EXPECT_EQ(result[1].row[1].to_int<i32>(), 40); 553 553 EXPECT_EQ(result[2].row[0].to_deprecated_string(), "Test_2"); 554 - EXPECT_EQ(result[2].row[1].to_int().value(), 42); 554 + EXPECT_EQ(result[2].row[1].to_int<i32>(), 42); 555 555 EXPECT_EQ(result[3].row[0].to_deprecated_string(), "Test_4"); 556 - EXPECT_EQ(result[3].row[1].to_int().value(), 41); 556 + EXPECT_EQ(result[3].row[1].to_int<i32>(), 41); 557 557 EXPECT_EQ(result[4].row[0].to_deprecated_string(), "Test_5"); 558 - EXPECT_EQ(result[4].row[1].to_int().value(), 44); 558 + EXPECT_EQ(result[4].row[1].to_int<i32>(), 44); 559 559 } 560 560 561 561 TEST_CASE(select_with_order_by_column_not_in_result) ··· 626 626 } 627 627 auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY IntColumn LIMIT 10 OFFSET 10;"); 628 628 EXPECT_EQ(result.size(), 10u); 629 - EXPECT_EQ(result[0].row[1].to_int().value(), 10); 630 - EXPECT_EQ(result[1].row[1].to_int().value(), 11); 631 - EXPECT_EQ(result[2].row[1].to_int().value(), 12); 632 - EXPECT_EQ(result[3].row[1].to_int().value(), 13); 633 - EXPECT_EQ(result[4].row[1].to_int().value(), 14); 634 - EXPECT_EQ(result[5].row[1].to_int().value(), 15); 635 - EXPECT_EQ(result[6].row[1].to_int().value(), 16); 636 - EXPECT_EQ(result[7].row[1].to_int().value(), 17); 637 - EXPECT_EQ(result[8].row[1].to_int().value(), 18); 638 - EXPECT_EQ(result[9].row[1].to_int().value(), 19); 629 + EXPECT_EQ(result[0].row[1].to_int<i32>(), 10); 630 + EXPECT_EQ(result[1].row[1].to_int<i32>(), 11); 631 + EXPECT_EQ(result[2].row[1].to_int<i32>(), 12); 632 + EXPECT_EQ(result[3].row[1].to_int<i32>(), 13); 633 + EXPECT_EQ(result[4].row[1].to_int<i32>(), 14); 634 + EXPECT_EQ(result[5].row[1].to_int<i32>(), 15); 635 + EXPECT_EQ(result[6].row[1].to_int<i32>(), 16); 636 + EXPECT_EQ(result[7].row[1].to_int<i32>(), 17); 637 + EXPECT_EQ(result[8].row[1].to_int<i32>(), 18); 638 + EXPECT_EQ(result[9].row[1].to_int<i32>(), 19); 639 639 } 640 640 641 641 TEST_CASE(select_with_limit_out_of_bounds) ··· 707 707 auto const& result_row = result.at(i).row; 708 708 EXPECT_EQ(result_row.size(), 1u); 709 709 710 - auto result_column = result_row[0].to_int(); 710 + auto result_column = result_row[0].to_int<i32>(); 711 711 result_values.append(result_column.value()); 712 712 } 713 713
+767 -31
Tests/LibSQL/TestSqlValueAndTuple.cpp
··· 19 19 EXPECT_EQ(v.type(), SQL::SQLType::Null); 20 20 EXPECT_EQ(v.to_deprecated_string(), "(null)"sv); 21 21 EXPECT(!v.to_bool().has_value()); 22 - EXPECT(!v.to_int().has_value()); 23 - EXPECT(!v.to_u32().has_value()); 22 + EXPECT(!v.to_int<i32>().has_value()); 23 + EXPECT(!v.to_int<u32>().has_value()); 24 24 EXPECT(!v.to_double().has_value()); 25 25 } 26 26 ··· 72 72 SQL::Value v("42"); 73 73 EXPECT_EQ(v.type(), SQL::SQLType::Text); 74 74 75 - EXPECT(v.to_int().has_value()); 76 - EXPECT_EQ(v.to_int().value(), 42); 75 + EXPECT(v.to_int<i32>().has_value()); 76 + EXPECT_EQ(v.to_int<i32>().value(), 42); 77 77 78 78 EXPECT(v.to_double().has_value()); 79 79 EXPECT((v.to_double().value() - 42.0) < NumericLimits<double>().epsilon()); ··· 97 97 EXPECT_EQ(v.type(), SQL::SQLType::Text); 98 98 99 99 EXPECT(!v.to_bool().has_value()); 100 - EXPECT(!v.to_int().has_value()); 101 - EXPECT(!v.to_u32().has_value()); 100 + EXPECT(!v.to_int<i32>().has_value()); 101 + EXPECT(!v.to_int<u32>().has_value()); 102 102 EXPECT(!v.to_double().has_value()); 103 103 } 104 104 { ··· 147 147 v = 42; 148 148 EXPECT_EQ(v.type(), SQL::SQLType::Integer); 149 149 150 - EXPECT(v.to_int().has_value()); 151 - EXPECT_EQ(v.to_int().value(), 42); 150 + EXPECT(v.to_int<i32>().has_value()); 151 + EXPECT_EQ(v.to_int<i32>().value(), 42); 152 152 EXPECT_EQ(v.to_deprecated_string(), "42"sv); 153 153 154 154 EXPECT(v.to_double().has_value()); ··· 161 161 SQL::Value v(0); 162 162 EXPECT_EQ(v.type(), SQL::SQLType::Integer); 163 163 164 - EXPECT(v.to_int().has_value()); 165 - EXPECT_EQ(v.to_int().value(), 0); 164 + EXPECT(v.to_int<i32>().has_value()); 165 + EXPECT_EQ(v.to_int<i32>().value(), 0); 166 166 167 167 EXPECT(v.to_bool().has_value()); 168 168 EXPECT(!v.to_bool().value()); ··· 171 171 SQL::Value v(42); 172 172 EXPECT_EQ(v.type(), SQL::SQLType::Integer); 173 173 174 - EXPECT(v.to_int().has_value()); 175 - EXPECT_EQ(v.to_int().value(), 42); 174 + EXPECT(v.to_int<i32>().has_value()); 175 + EXPECT_EQ(v.to_int<i32>().value(), 42); 176 176 } 177 177 { 178 178 SQL::Value text("42"); 179 179 SQL::Value integer(SQL::SQLType::Integer); 180 180 integer = text; 181 181 182 - EXPECT(integer.to_int().has_value()); 183 - EXPECT_EQ(integer.to_int().value(), 42); 182 + EXPECT(integer.to_int<i32>().has_value()); 183 + EXPECT_EQ(integer.to_int<i32>().value(), 42); 184 184 } 185 185 } 186 186 ··· 200 200 EXPECT_EQ(v2, v); 201 201 } 202 202 203 + TEST_CASE(serialize_downsized_int_value) 204 + { 205 + auto run_test_for_value = [](auto value) { 206 + using T = decltype(value); 207 + SQL::Value v(value); 208 + 209 + SQL::Serializer serializer; 210 + serializer.serialize(v); 211 + serializer.rewind(); 212 + 213 + auto type_flags = serializer.deserialize<u8>(); 214 + auto type_data = type_flags & 0xf0; 215 + auto type = static_cast<SQL::SQLType>(type_flags & 0x0f); 216 + 217 + EXPECT_NE(type_data, 0); 218 + EXPECT_EQ(type, SQL::SQLType::Integer); 219 + 220 + auto deserialized = serializer.deserialize<T>(); 221 + EXPECT_EQ(deserialized, value); 222 + }; 223 + 224 + run_test_for_value(NumericLimits<i8>::min()); 225 + run_test_for_value(NumericLimits<i8>::max()); 226 + 227 + run_test_for_value(NumericLimits<i16>::min()); 228 + run_test_for_value(NumericLimits<i16>::max()); 229 + 230 + run_test_for_value(NumericLimits<i32>::min()); 231 + run_test_for_value(NumericLimits<i32>::max()); 232 + 233 + run_test_for_value(NumericLimits<i64>::min()); 234 + run_test_for_value(NumericLimits<i64>::max()); 235 + 236 + run_test_for_value(NumericLimits<u8>::min()); 237 + run_test_for_value(NumericLimits<u8>::max()); 238 + 239 + run_test_for_value(NumericLimits<u16>::min()); 240 + run_test_for_value(NumericLimits<u16>::max()); 241 + 242 + run_test_for_value(NumericLimits<u32>::min()); 243 + run_test_for_value(NumericLimits<u32>::max()); 244 + 245 + run_test_for_value(NumericLimits<u64>::min()); 246 + run_test_for_value(NumericLimits<u64>::max()); 247 + } 248 + 203 249 TEST_CASE(float_value) 204 250 { 205 251 { ··· 213 259 EXPECT(v.to_double().has_value()); 214 260 EXPECT((v.to_double().value() - 3.14) < NumericLimits<double>().epsilon()); 215 261 216 - EXPECT(v.to_int().has_value()); 217 - EXPECT_EQ(v.to_int().value(), 3); 262 + EXPECT(v.to_int<i32>().has_value()); 263 + EXPECT_EQ(v.to_int<i32>().value(), 3); 218 264 EXPECT_EQ(v.to_deprecated_string(), "3.14"); 219 265 220 266 EXPECT(v.to_bool().has_value()); ··· 226 272 EXPECT(v.to_double().has_value()); 227 273 EXPECT(v.to_double().value() < NumericLimits<double>().epsilon()); 228 274 229 - EXPECT(v.to_int().has_value()); 230 - EXPECT_EQ(v.to_int().value(), 0); 275 + EXPECT(v.to_int<i32>().has_value()); 276 + EXPECT_EQ(v.to_int<i32>().value(), 0); 231 277 EXPECT_EQ(v.to_deprecated_string(), "0"sv); 232 278 233 279 EXPECT(v.to_bool().has_value()); ··· 242 288 SQL::Value v(3.51); 243 289 EXPECT_EQ(v.type(), SQL::SQLType::Float); 244 290 245 - EXPECT(v.to_int().has_value()); 246 - EXPECT_EQ(v.to_int().value(), 4); 291 + EXPECT(v.to_int<i32>().has_value()); 292 + EXPECT_EQ(v.to_int<i32>().value(), 4); 247 293 } 248 294 { 249 295 SQL::Value v(-3.14); 250 296 EXPECT_EQ(v.type(), SQL::SQLType::Float); 251 297 252 - EXPECT(v.to_int().has_value()); 253 - EXPECT_EQ(v.to_int().value(), -3); 298 + EXPECT(v.to_int<i32>().has_value()); 299 + EXPECT_EQ(v.to_int<i32>().value(), -3); 254 300 } 255 301 { 256 302 SQL::Value v(-3.51); 257 303 EXPECT_EQ(v.type(), SQL::SQLType::Float); 258 304 259 - EXPECT(v.to_int().has_value()); 260 - EXPECT_EQ(v.to_int().value(), -4); 305 + EXPECT(v.to_int<i32>().has_value()); 306 + EXPECT_EQ(v.to_int<i32>().value(), -4); 261 307 } 262 308 } 263 309 ··· 284 330 EXPECT_EQ(copy, "42"sv); 285 331 } 286 332 287 - TEST_CASE(compare_text_to_int) 333 + TEST_CASE(to_int) 288 334 { 289 335 SQL::Value text("42"); 290 336 SQL::Value integer(42); 291 337 EXPECT_EQ(text, integer); 292 338 EXPECT_EQ(integer, text); 339 + 340 + SQL::Value int_64 { static_cast<i64>(123) }; 341 + EXPECT_EQ(int_64.to_int<i8>(), 123); 342 + EXPECT_EQ(int_64.to_int<i16>(), 123); 343 + EXPECT_EQ(int_64.to_int<i32>(), 123); 344 + EXPECT_EQ(int_64.to_int<u8>(), 123u); 345 + EXPECT_EQ(int_64.to_int<u16>(), 123u); 346 + EXPECT_EQ(int_64.to_int<u32>(), 123u); 347 + EXPECT_EQ(int_64.to_int<u64>(), 123u); 348 + 349 + SQL::Value uint_64 { static_cast<i64>(123) }; 350 + EXPECT_EQ(uint_64.to_int<i8>(), 123); 351 + EXPECT_EQ(uint_64.to_int<i16>(), 123); 352 + EXPECT_EQ(uint_64.to_int<i32>(), 123); 353 + EXPECT_EQ(uint_64.to_int<i64>(), 123); 354 + EXPECT_EQ(uint_64.to_int<u8>(), 123u); 355 + EXPECT_EQ(uint_64.to_int<u16>(), 123u); 356 + EXPECT_EQ(uint_64.to_int<u32>(), 123u); 357 + } 358 + 359 + TEST_CASE(to_int_failures) 360 + { 361 + SQL::Value large_int_64 { NumericLimits<i64>::max() }; 362 + EXPECT(!large_int_64.to_int<i8>().has_value()); 363 + EXPECT(!large_int_64.to_int<i16>().has_value()); 364 + EXPECT(!large_int_64.to_int<i32>().has_value()); 365 + EXPECT(!large_int_64.to_int<u8>().has_value()); 366 + EXPECT(!large_int_64.to_int<u16>().has_value()); 367 + EXPECT(!large_int_64.to_int<u32>().has_value()); 368 + 369 + SQL::Value large_int_32 { NumericLimits<i32>::max() }; 370 + EXPECT(!large_int_32.to_int<i8>().has_value()); 371 + EXPECT(!large_int_32.to_int<i16>().has_value()); 372 + EXPECT(!large_int_32.to_int<u8>().has_value()); 373 + EXPECT(!large_int_32.to_int<u16>().has_value()); 374 + 375 + SQL::Value small_int_64 { NumericLimits<i64>::min() }; 376 + EXPECT(!small_int_64.to_int<i8>().has_value()); 377 + EXPECT(!small_int_64.to_int<i16>().has_value()); 378 + EXPECT(!small_int_64.to_int<i32>().has_value()); 379 + EXPECT(!small_int_64.to_int<u8>().has_value()); 380 + EXPECT(!small_int_64.to_int<u16>().has_value()); 381 + EXPECT(!small_int_64.to_int<u32>().has_value()); 382 + EXPECT(!small_int_64.to_int<u64>().has_value()); 383 + 384 + SQL::Value small_int_32 { NumericLimits<i32>::min() }; 385 + EXPECT(!small_int_32.to_int<i8>().has_value()); 386 + EXPECT(!small_int_32.to_int<i16>().has_value()); 387 + EXPECT(!small_int_32.to_int<u8>().has_value()); 388 + EXPECT(!small_int_32.to_int<u16>().has_value()); 389 + EXPECT(!small_int_32.to_int<u32>().has_value()); 390 + EXPECT(!small_int_32.to_int<u64>().has_value()); 391 + 392 + SQL::Value large_uint_64 { NumericLimits<u64>::max() }; 393 + EXPECT(!large_uint_64.to_int<i8>().has_value()); 394 + EXPECT(!large_uint_64.to_int<i16>().has_value()); 395 + EXPECT(!large_uint_64.to_int<i32>().has_value()); 396 + EXPECT(!large_uint_64.to_int<i64>().has_value()); 397 + EXPECT(!large_uint_64.to_int<u8>().has_value()); 398 + EXPECT(!large_uint_64.to_int<u16>().has_value()); 399 + EXPECT(!large_uint_64.to_int<u32>().has_value()); 400 + 401 + SQL::Value large_uint_32 { NumericLimits<u32>::max() }; 402 + EXPECT(!large_uint_32.to_int<i8>().has_value()); 403 + EXPECT(!large_uint_32.to_int<i16>().has_value()); 404 + EXPECT(!large_uint_32.to_int<u8>().has_value()); 405 + EXPECT(!large_uint_32.to_int<u16>().has_value()); 293 406 } 294 407 295 408 TEST_CASE(bool_value) ··· 305 418 EXPECT(v.to_bool().has_value()); 306 419 EXPECT(v.to_bool().value()); 307 420 308 - EXPECT(v.to_int().has_value()); 309 - EXPECT_EQ(v.to_int().value(), 1); 421 + EXPECT(v.to_int<i32>().has_value()); 422 + EXPECT_EQ(v.to_int<i32>().value(), 1); 310 423 EXPECT_EQ(v.to_deprecated_string(), "true"sv); 311 424 312 425 EXPECT(v.to_double().has_value()); ··· 319 432 EXPECT(v.to_bool().has_value()); 320 433 EXPECT(!v.to_bool().value()); 321 434 322 - EXPECT(v.to_int().has_value()); 323 - EXPECT_EQ(v.to_int().value(), 0); 435 + EXPECT(v.to_int<i32>().has_value()); 436 + EXPECT_EQ(v.to_int<i32>().value(), 0); 324 437 EXPECT_EQ(v.to_deprecated_string(), "false"sv); 325 438 326 439 EXPECT(v.to_double().has_value()); ··· 333 446 EXPECT(v.to_bool().has_value()); 334 447 EXPECT(v.to_bool().value()); 335 448 336 - EXPECT(v.to_int().has_value()); 337 - EXPECT_EQ(v.to_int().value(), 1); 449 + EXPECT(v.to_int<i32>().has_value()); 450 + EXPECT_EQ(v.to_int<i32>().value(), 1); 338 451 EXPECT_EQ(v.to_deprecated_string(), "true"sv); 339 452 340 453 EXPECT(v.to_double().has_value()); ··· 567 680 EXPECT(tuple3 >= tuple1); 568 681 EXPECT(tuple3 > tuple1); 569 682 } 683 + 684 + TEST_CASE(add) 685 + { 686 + { 687 + SQL::Value value1 { 21 }; 688 + SQL::Value value2 { 42 }; 689 + 690 + auto result = value1.add(value2); 691 + EXPECT(!result.is_error()); 692 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 693 + EXPECT_EQ(result.value(), 63); 694 + } 695 + { 696 + SQL::Value value1 { 21 }; 697 + SQL::Value value2 { static_cast<u8>(42) }; 698 + 699 + auto result = value1.add(value2); 700 + EXPECT(!result.is_error()); 701 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 702 + EXPECT_EQ(result.value(), 63); 703 + } 704 + { 705 + SQL::Value value1 { static_cast<u8>(21) }; 706 + SQL::Value value2 { 42 }; 707 + 708 + auto result = value1.add(value2); 709 + EXPECT(!result.is_error()); 710 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 711 + EXPECT_EQ(result.value(), 63); 712 + } 713 + { 714 + SQL::Value value1 { static_cast<double>(21) }; 715 + SQL::Value value2 { 42 }; 716 + 717 + auto result = value1.add(value2); 718 + EXPECT(!result.is_error()); 719 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 720 + EXPECT_EQ(result.value(), 63); 721 + } 722 + { 723 + SQL::Value value1 { static_cast<double>(21.5) }; 724 + SQL::Value value2 { 42 }; 725 + 726 + auto result = value1.add(value2); 727 + EXPECT(!result.is_error()); 728 + EXPECT_EQ(result.value().type(), SQL::SQLType::Float); 729 + EXPECT((result.value().to_double().value() - 63.5) < NumericLimits<double>().epsilon()); 730 + } 731 + } 732 + 733 + TEST_CASE(add_error) 734 + { 735 + { 736 + // Fails to coerce value2 to the signedness of value1. 737 + SQL::Value value1 { 1 }; 738 + SQL::Value value2 { NumericLimits<u64>::max() }; 739 + 740 + auto result = value1.add(value2); 741 + EXPECT(result.is_error()); 742 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 743 + } 744 + { 745 + // Fails to coerce value2 to the signedness of value1. 746 + SQL::Value value1 { static_cast<u64>(1) }; 747 + SQL::Value value2 { -1 }; 748 + 749 + auto result = value1.add(value2); 750 + EXPECT(result.is_error()); 751 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 752 + } 753 + { 754 + // The operation itself would overflow. 755 + SQL::Value value1 { static_cast<u64>(1) }; 756 + SQL::Value value2 { NumericLimits<u64>::max() }; 757 + 758 + auto result = value1.add(value2); 759 + EXPECT(result.is_error()); 760 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 761 + } 762 + { 763 + // Cannot convert value to a number. 764 + SQL::Value value1 { 1 }; 765 + SQL::Value value2 { "foo"sv }; 766 + 767 + auto result = value1.add(value2); 768 + EXPECT(result.is_error()); 769 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 770 + } 771 + } 772 + 773 + TEST_CASE(subtract) 774 + { 775 + { 776 + SQL::Value value1 { 21 }; 777 + SQL::Value value2 { 42 }; 778 + 779 + auto result = value1.subtract(value2); 780 + EXPECT(!result.is_error()); 781 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 782 + EXPECT_EQ(result.value(), -21); 783 + } 784 + { 785 + SQL::Value value1 { 21 }; 786 + SQL::Value value2 { static_cast<u8>(42) }; 787 + 788 + auto result = value1.subtract(value2); 789 + EXPECT(!result.is_error()); 790 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 791 + EXPECT_EQ(result.value(), -21); 792 + } 793 + { 794 + SQL::Value value1 { static_cast<u8>(42) }; 795 + SQL::Value value2 { 21 }; 796 + 797 + auto result = value1.subtract(value2); 798 + EXPECT(!result.is_error()); 799 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 800 + EXPECT_EQ(result.value(), 21); 801 + } 802 + { 803 + SQL::Value value1 { static_cast<double>(21) }; 804 + SQL::Value value2 { 42 }; 805 + 806 + auto result = value1.subtract(value2); 807 + EXPECT(!result.is_error()); 808 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 809 + EXPECT_EQ(result.value(), -21); 810 + } 811 + { 812 + SQL::Value value1 { static_cast<double>(21.5) }; 813 + SQL::Value value2 { 42 }; 814 + 815 + auto result = value1.subtract(value2); 816 + EXPECT(!result.is_error()); 817 + EXPECT_EQ(result.value().type(), SQL::SQLType::Float); 818 + EXPECT((result.value().to_double().value() - 20.5) < NumericLimits<double>().epsilon()); 819 + } 820 + } 821 + 822 + TEST_CASE(subtract_error) 823 + { 824 + { 825 + // Fails to coerce value2 to the signedness of value1. 826 + SQL::Value value1 { 1 }; 827 + SQL::Value value2 { NumericLimits<u64>::max() }; 828 + 829 + auto result = value1.subtract(value2); 830 + EXPECT(result.is_error()); 831 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 832 + } 833 + { 834 + // Fails to coerce value2 to the signedness of value1. 835 + SQL::Value value1 { static_cast<u64>(1) }; 836 + SQL::Value value2 { -1 }; 837 + 838 + auto result = value1.subtract(value2); 839 + EXPECT(result.is_error()); 840 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 841 + } 842 + { 843 + // The operation itself would overflow. 844 + SQL::Value value1 { static_cast<u64>(0) }; 845 + SQL::Value value2 { static_cast<u64>(1) }; 846 + 847 + auto result = value1.subtract(value2); 848 + EXPECT(result.is_error()); 849 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 850 + } 851 + { 852 + // Cannot convert value to a number. 853 + SQL::Value value1 { 1 }; 854 + SQL::Value value2 { "foo"sv }; 855 + 856 + auto result = value1.subtract(value2); 857 + EXPECT(result.is_error()); 858 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 859 + } 860 + } 861 + 862 + TEST_CASE(multiply) 863 + { 864 + { 865 + SQL::Value value1 { 2 }; 866 + SQL::Value value2 { 21 }; 867 + 868 + auto result = value1.multiply(value2); 869 + EXPECT(!result.is_error()); 870 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 871 + EXPECT_EQ(result.value(), 42); 872 + } 873 + { 874 + SQL::Value value1 { 2 }; 875 + SQL::Value value2 { static_cast<u8>(21) }; 876 + 877 + auto result = value1.multiply(value2); 878 + EXPECT(!result.is_error()); 879 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 880 + EXPECT_EQ(result.value(), 42); 881 + } 882 + { 883 + SQL::Value value1 { static_cast<u8>(2) }; 884 + SQL::Value value2 { 21 }; 885 + 886 + auto result = value1.multiply(value2); 887 + EXPECT(!result.is_error()); 888 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 889 + EXPECT_EQ(result.value(), 42); 890 + } 891 + { 892 + SQL::Value value1 { static_cast<double>(2) }; 893 + SQL::Value value2 { 21 }; 894 + 895 + auto result = value1.multiply(value2); 896 + EXPECT(!result.is_error()); 897 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 898 + EXPECT_EQ(result.value(), 42); 899 + } 900 + { 901 + SQL::Value value1 { static_cast<double>(2.5) }; 902 + SQL::Value value2 { 21 }; 903 + 904 + auto result = value1.multiply(value2); 905 + EXPECT(!result.is_error()); 906 + EXPECT_EQ(result.value().type(), SQL::SQLType::Float); 907 + EXPECT((result.value().to_double().value() - 52.5) < NumericLimits<double>().epsilon()); 908 + } 909 + } 910 + 911 + TEST_CASE(multiply_error) 912 + { 913 + { 914 + // Fails to coerce value2 to the signedness of value1. 915 + SQL::Value value1 { 1 }; 916 + SQL::Value value2 { NumericLimits<u64>::max() }; 917 + 918 + auto result = value1.multiply(value2); 919 + EXPECT(result.is_error()); 920 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 921 + } 922 + { 923 + // Fails to coerce value2 to the signedness of value1. 924 + SQL::Value value1 { static_cast<u64>(1) }; 925 + SQL::Value value2 { -1 }; 926 + 927 + auto result = value1.multiply(value2); 928 + EXPECT(result.is_error()); 929 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 930 + } 931 + { 932 + // The operation itself would overflow. 933 + SQL::Value value1 { NumericLimits<i64>::max() }; 934 + SQL::Value value2 { 2 }; 935 + 936 + auto result = value1.multiply(value2); 937 + EXPECT(result.is_error()); 938 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 939 + } 940 + { 941 + // Cannot convert value to a number. 942 + SQL::Value value1 { 1 }; 943 + SQL::Value value2 { "foo"sv }; 944 + 945 + auto result = value1.multiply(value2); 946 + EXPECT(result.is_error()); 947 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 948 + } 949 + } 950 + 951 + TEST_CASE(divide) 952 + { 953 + { 954 + SQL::Value value1 { 42 }; 955 + SQL::Value value2 { -2 }; 956 + 957 + auto result = value1.divide(value2); 958 + EXPECT(!result.is_error()); 959 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 960 + EXPECT_EQ(result.value(), -21); 961 + } 962 + { 963 + SQL::Value value1 { 42 }; 964 + SQL::Value value2 { static_cast<u8>(2) }; 965 + 966 + auto result = value1.divide(value2); 967 + EXPECT(!result.is_error()); 968 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 969 + EXPECT_EQ(result.value(), 21); 970 + } 971 + { 972 + SQL::Value value1 { static_cast<u8>(42) }; 973 + SQL::Value value2 { 2 }; 974 + 975 + auto result = value1.divide(value2); 976 + EXPECT(!result.is_error()); 977 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 978 + EXPECT_EQ(result.value(), 21); 979 + } 980 + { 981 + SQL::Value value1 { static_cast<double>(42) }; 982 + SQL::Value value2 { 2 }; 983 + 984 + auto result = value1.divide(value2); 985 + EXPECT(!result.is_error()); 986 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 987 + EXPECT_EQ(result.value(), 21); 988 + } 989 + { 990 + SQL::Value value1 { static_cast<double>(43) }; 991 + SQL::Value value2 { 2 }; 992 + 993 + auto result = value1.divide(value2); 994 + EXPECT(!result.is_error()); 995 + EXPECT_EQ(result.value().type(), SQL::SQLType::Float); 996 + EXPECT((result.value().to_double().value() - 21.5) < NumericLimits<double>().epsilon()); 997 + } 998 + } 999 + 1000 + TEST_CASE(divide_error) 1001 + { 1002 + { 1003 + // The operation itself would overflow. 1004 + SQL::Value value1 { 1 }; 1005 + SQL::Value value2 { 0 }; 1006 + 1007 + auto result = value1.divide(value2); 1008 + EXPECT(result.is_error()); 1009 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1010 + } 1011 + { 1012 + // Cannot convert value to a number. 1013 + SQL::Value value1 { 1 }; 1014 + SQL::Value value2 { "foo"sv }; 1015 + 1016 + auto result = value1.divide(value2); 1017 + EXPECT(result.is_error()); 1018 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1019 + } 1020 + } 1021 + 1022 + TEST_CASE(modulo) 1023 + { 1024 + { 1025 + SQL::Value value1 { 21 }; 1026 + SQL::Value value2 { 2 }; 1027 + 1028 + auto result = value1.modulo(value2); 1029 + EXPECT(!result.is_error()); 1030 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1031 + EXPECT_EQ(result.value(), 1); 1032 + } 1033 + { 1034 + SQL::Value value1 { 21 }; 1035 + SQL::Value value2 { static_cast<u8>(2) }; 1036 + 1037 + auto result = value1.modulo(value2); 1038 + EXPECT(!result.is_error()); 1039 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1040 + EXPECT_EQ(result.value(), 1); 1041 + } 1042 + { 1043 + SQL::Value value1 { static_cast<u8>(21) }; 1044 + SQL::Value value2 { 2 }; 1045 + 1046 + auto result = value1.modulo(value2); 1047 + EXPECT(!result.is_error()); 1048 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1049 + EXPECT_EQ(result.value(), 1); 1050 + } 1051 + { 1052 + SQL::Value value1 { static_cast<double>(21) }; 1053 + SQL::Value value2 { 2 }; 1054 + 1055 + auto result = value1.modulo(value2); 1056 + EXPECT(!result.is_error()); 1057 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1058 + EXPECT_EQ(result.value(), 1); 1059 + } 1060 + } 1061 + 1062 + TEST_CASE(modulo_error) 1063 + { 1064 + { 1065 + // Fails to coerce value2 to the signedness of value1. 1066 + SQL::Value value1 { 1 }; 1067 + SQL::Value value2 { NumericLimits<u64>::max() }; 1068 + 1069 + auto result = value1.modulo(value2); 1070 + EXPECT(result.is_error()); 1071 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1072 + } 1073 + { 1074 + // Fails to coerce value2 to the signedness of value1. 1075 + SQL::Value value1 { static_cast<u64>(1) }; 1076 + SQL::Value value2 { -1 }; 1077 + 1078 + auto result = value1.modulo(value2); 1079 + EXPECT(result.is_error()); 1080 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1081 + } 1082 + { 1083 + // The operation itself would overflow. 1084 + SQL::Value value1 { 21 }; 1085 + SQL::Value value2 { 0 }; 1086 + 1087 + auto result = value1.modulo(value2); 1088 + EXPECT(result.is_error()); 1089 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1090 + } 1091 + { 1092 + // Cannot convert value to an integer. 1093 + SQL::Value value1 { 1 }; 1094 + SQL::Value value2 { "foo"sv }; 1095 + 1096 + auto result = value1.modulo(value2); 1097 + EXPECT(result.is_error()); 1098 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1099 + } 1100 + { 1101 + // Cannot convert value to an integer. 1102 + SQL::Value value1 { static_cast<double>(21.5) }; 1103 + SQL::Value value2 { 2 }; 1104 + 1105 + auto result = value1.modulo(value2); 1106 + EXPECT(result.is_error()); 1107 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1108 + } 1109 + } 1110 + 1111 + TEST_CASE(shift_left) 1112 + { 1113 + { 1114 + SQL::Value value1 { 0b0011'0000 }; 1115 + SQL::Value value2 { 2 }; 1116 + 1117 + auto result = value1.shift_left(value2); 1118 + EXPECT(!result.is_error()); 1119 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1120 + EXPECT_EQ(result.value(), 0b1100'0000); 1121 + } 1122 + { 1123 + SQL::Value value1 { 0b0011'0000 }; 1124 + SQL::Value value2 { static_cast<u8>(2) }; 1125 + 1126 + auto result = value1.shift_left(value2); 1127 + EXPECT(!result.is_error()); 1128 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1129 + EXPECT_EQ(result.value(), 0b1100'0000); 1130 + } 1131 + { 1132 + SQL::Value value1 { static_cast<u8>(0b0011'0000) }; 1133 + SQL::Value value2 { 2 }; 1134 + 1135 + auto result = value1.shift_left(value2); 1136 + EXPECT(!result.is_error()); 1137 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1138 + EXPECT_EQ(result.value(), 0b1100'0000); 1139 + } 1140 + { 1141 + SQL::Value value1 { static_cast<double>(0b0011'0000) }; 1142 + SQL::Value value2 { 2 }; 1143 + 1144 + auto result = value1.shift_left(value2); 1145 + EXPECT(!result.is_error()); 1146 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1147 + EXPECT_EQ(result.value(), 0b1100'0000); 1148 + } 1149 + } 1150 + 1151 + TEST_CASE(shift_left_error) 1152 + { 1153 + { 1154 + // Fails to coerce value2 to the signedness of value1. 1155 + SQL::Value value1 { 1 }; 1156 + SQL::Value value2 { NumericLimits<u64>::max() }; 1157 + 1158 + auto result = value1.shift_left(value2); 1159 + EXPECT(result.is_error()); 1160 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1161 + } 1162 + { 1163 + // Fails to coerce value2 to the signedness of value1. 1164 + SQL::Value value1 { static_cast<u64>(1) }; 1165 + SQL::Value value2 { -1 }; 1166 + 1167 + auto result = value1.shift_left(value2); 1168 + EXPECT(result.is_error()); 1169 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1170 + } 1171 + { 1172 + // The operation itself would overflow. 1173 + SQL::Value value1 { 21 }; 1174 + SQL::Value value2 { -1 }; 1175 + 1176 + auto result = value1.shift_left(value2); 1177 + EXPECT(result.is_error()); 1178 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1179 + } 1180 + { 1181 + // The operation itself would overflow. 1182 + SQL::Value value1 { 21 }; 1183 + SQL::Value value2 { 64 }; 1184 + 1185 + auto result = value1.shift_left(value2); 1186 + EXPECT(result.is_error()); 1187 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1188 + } 1189 + { 1190 + // Cannot convert value to an integer. 1191 + SQL::Value value1 { 1 }; 1192 + SQL::Value value2 { "foo"sv }; 1193 + 1194 + auto result = value1.shift_left(value2); 1195 + EXPECT(result.is_error()); 1196 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1197 + } 1198 + { 1199 + // Cannot convert value to an integer. 1200 + SQL::Value value1 { static_cast<double>(21.5) }; 1201 + SQL::Value value2 { 2 }; 1202 + 1203 + auto result = value1.shift_left(value2); 1204 + EXPECT(result.is_error()); 1205 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1206 + } 1207 + } 1208 + 1209 + TEST_CASE(shift_right) 1210 + { 1211 + { 1212 + SQL::Value value1 { 0b0011'0000 }; 1213 + SQL::Value value2 { 2 }; 1214 + 1215 + auto result = value1.shift_right(value2); 1216 + EXPECT(!result.is_error()); 1217 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1218 + EXPECT_EQ(result.value(), 0b0000'1100); 1219 + } 1220 + { 1221 + SQL::Value value1 { 0b0011'0000 }; 1222 + SQL::Value value2 { static_cast<u8>(2) }; 1223 + 1224 + auto result = value1.shift_right(value2); 1225 + EXPECT(!result.is_error()); 1226 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1227 + EXPECT_EQ(result.value(), 0b0000'1100); 1228 + } 1229 + { 1230 + SQL::Value value1 { static_cast<u8>(0b0011'0000) }; 1231 + SQL::Value value2 { 2 }; 1232 + 1233 + auto result = value1.shift_right(value2); 1234 + EXPECT(!result.is_error()); 1235 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1236 + EXPECT_EQ(result.value(), 0b0000'1100); 1237 + } 1238 + { 1239 + SQL::Value value1 { static_cast<double>(0b0011'0000) }; 1240 + SQL::Value value2 { 2 }; 1241 + 1242 + auto result = value1.shift_right(value2); 1243 + EXPECT(!result.is_error()); 1244 + EXPECT_EQ(result.value().type(), SQL::SQLType::Integer); 1245 + EXPECT_EQ(result.value(), 0b0000'1100); 1246 + } 1247 + } 1248 + 1249 + TEST_CASE(shift_right_error) 1250 + { 1251 + { 1252 + // Fails to coerce value2 to the signedness of value1. 1253 + SQL::Value value1 { 1 }; 1254 + SQL::Value value2 { NumericLimits<u64>::max() }; 1255 + 1256 + auto result = value1.shift_right(value2); 1257 + EXPECT(result.is_error()); 1258 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1259 + } 1260 + { 1261 + // Fails to coerce value2 to the signedness of value1. 1262 + SQL::Value value1 { static_cast<u64>(1) }; 1263 + SQL::Value value2 { -1 }; 1264 + 1265 + auto result = value1.shift_right(value2); 1266 + EXPECT(result.is_error()); 1267 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1268 + } 1269 + { 1270 + // The operation itself would overflow. 1271 + SQL::Value value1 { 21 }; 1272 + SQL::Value value2 { -1 }; 1273 + 1274 + auto result = value1.shift_right(value2); 1275 + EXPECT(result.is_error()); 1276 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1277 + } 1278 + { 1279 + // The operation itself would overflow. 1280 + SQL::Value value1 { 21 }; 1281 + SQL::Value value2 { 64 }; 1282 + 1283 + auto result = value1.shift_right(value2); 1284 + EXPECT(result.is_error()); 1285 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::IntegerOverflow); 1286 + } 1287 + { 1288 + // Cannot convert value to an integer. 1289 + SQL::Value value1 { 1 }; 1290 + SQL::Value value2 { "foo"sv }; 1291 + 1292 + auto result = value1.shift_right(value2); 1293 + EXPECT(result.is_error()); 1294 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1295 + } 1296 + { 1297 + // Cannot convert value to an integer. 1298 + SQL::Value value1 { static_cast<double>(21.5) }; 1299 + SQL::Value value2 { 2 }; 1300 + 1301 + auto result = value1.shift_right(value2); 1302 + EXPECT(result.is_error()); 1303 + EXPECT_EQ(result.error().error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch); 1304 + } 1305 + }
+2 -14
Userland/Libraries/LibSQL/AST/Expression.cpp
··· 128 128 return expression_value; 129 129 return Result { SQLCommand::Unknown, SQLErrorCode::NumericOperatorTypeMismatch, UnaryOperator_name(type()) }; 130 130 case UnaryOperator::Minus: 131 - if (expression_value.type() == SQLType::Integer) { 132 - expression_value = -expression_value.to_int().value(); 133 - return expression_value; 134 - } 135 - if (expression_value.type() == SQLType::Float) { 136 - expression_value = -expression_value.to_double().value(); 137 - return expression_value; 138 - } 139 - return Result { SQLCommand::Unknown, SQLErrorCode::NumericOperatorTypeMismatch, UnaryOperator_name(type()) }; 131 + return expression_value.negate(); 140 132 case UnaryOperator::Not: 141 133 if (expression_value.type() == SQLType::Boolean) { 142 134 expression_value = !expression_value.to_bool().value(); ··· 144 136 } 145 137 return Result { SQLCommand::Unknown, SQLErrorCode::BooleanOperatorTypeMismatch, UnaryOperator_name(type()) }; 146 138 case UnaryOperator::BitwiseNot: 147 - if (expression_value.type() == SQLType::Integer) { 148 - expression_value = ~expression_value.to_u32().value(); 149 - return expression_value; 150 - } 151 - return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOperatorTypeMismatch, UnaryOperator_name(type()) }; 139 + return expression_value.bitwise_not(); 152 140 default: 153 141 VERIFY_NOT_REACHED(); 154 142 }
+2 -2
Userland/Libraries/LibSQL/AST/Select.cpp
··· 119 119 120 120 auto limit = TRY(m_limit_clause->limit_expression()->evaluate(context)); 121 121 if (!limit.is_null()) { 122 - auto limit_value_maybe = limit.to_u32(); 122 + auto limit_value_maybe = limit.to_int<size_t>(); 123 123 if (!limit_value_maybe.has_value()) 124 124 return Result { SQLCommand::Select, SQLErrorCode::SyntaxError, "LIMIT clause must evaluate to an integer value"sv }; 125 125 ··· 129 129 if (m_limit_clause->offset_expression() != nullptr) { 130 130 auto offset = TRY(m_limit_clause->offset_expression()->evaluate(context)); 131 131 if (!offset.is_null()) { 132 - auto offset_value_maybe = offset.to_u32(); 132 + auto offset_value_maybe = offset.to_int<size_t>(); 133 133 if (!offset_value_maybe.has_value()) 134 134 return Result { SQLCommand::Select, SQLErrorCode::SyntaxError, "OFFSET clause must evaluate to an integer value"sv }; 135 135
+1 -1
Userland/Libraries/LibSQL/Database.cpp
··· 165 165 166 166 auto table_hash = table_def->hash(); 167 167 auto column_key = ColumnDef::make_key(table_def); 168 - for (auto it = m_table_columns->find(column_key); !it.is_end() && ((*it)["table_hash"].to_u32().value() == table_hash); ++it) 168 + for (auto it = m_table_columns->find(column_key); !it.is_end() && ((*it)["table_hash"].to_int<u32>() == table_hash); ++it) 169 169 table_def->append_column(*it); 170 170 171 171 return table_def;
+1 -1
Userland/Libraries/LibSQL/Heap.h
··· 33 33 C_OBJECT(Heap); 34 34 35 35 public: 36 - static constexpr inline u32 current_version = 2; 36 + static constexpr inline u32 current_version = 3; 37 37 38 38 virtual ~Heap() override; 39 39
+3 -3
Userland/Libraries/LibSQL/Meta.cpp
··· 59 59 { 60 60 auto key = Key(index_def()); 61 61 key["table_hash"] = parent_relation()->hash(); 62 - key["column_number"] = (int)column_number(); 62 + key["column_number"] = column_number(); 63 63 key["column_name"] = name(); 64 - key["column_type"] = (int)type(); 64 + key["column_type"] = to_underlying(type()); 65 65 return key; 66 66 } 67 67 ··· 183 183 184 184 void TableDef::append_column(Key const& column) 185 185 { 186 - auto column_type = column["column_type"].to_int(); 186 + auto column_type = column["column_type"].to_int<UnderlyingType<SQLType>>(); 187 187 VERIFY(column_type.has_value()); 188 188 189 189 append_column(column["column_name"].to_deprecated_string(), static_cast<SQLType>(*column_type));
+1
Userland/Libraries/LibSQL/Result.h
··· 48 48 S(DatabaseDoesNotExist, "Database '{}' does not exist") \ 49 49 S(DatabaseUnavailable, "Database Unavailable") \ 50 50 S(IntegerOperatorTypeMismatch, "Cannot apply '{}' operator to non-numeric operands") \ 51 + S(IntegerOverflow, "Operation would cause integer overflow") \ 51 52 S(InternalError, "{}") \ 52 53 S(InvalidDatabaseName, "Invalid database name '{}'") \ 53 54 S(InvalidNumberOfPlaceholderValues, "Number of values does not match number of placeholders") \
+359 -183
Userland/Libraries/LibSQL/Value.cpp
··· 12 12 #include <LibSQL/Serializer.h> 13 13 #include <LibSQL/TupleDescriptor.h> 14 14 #include <LibSQL/Value.h> 15 - #include <math.h> 16 15 #include <string.h> 17 16 18 17 namespace SQL { 19 18 20 - Value::Value(SQLType type) 21 - : m_type(type) 19 + // We use the upper 4 bits of the encoded type to store extra information about the type. This 20 + // includes if the value is null, and the encoded size of any integer type. Of course, this encoding 21 + // only works if the SQL type itself fits in the lower 4 bits. 22 + enum class SQLTypeWithCount { 23 + #undef __ENUMERATE_SQL_TYPE 24 + #define __ENUMERATE_SQL_TYPE(name, type) type, 25 + ENUMERATE_SQL_TYPES(__ENUMERATE_SQL_TYPE) 26 + #undef __ENUMERATE_SQL_TYPE 27 + Count, 28 + }; 29 + 30 + static_assert(to_underlying(SQLTypeWithCount::Count) <= 0x0f, "Too many SQL types for current encoding"); 31 + 32 + // Adding to this list is fine, but changing the order of any value here will result in LibSQL 33 + // becoming unable to read existing .db files. If the order must absolutely be changed, be sure 34 + // to bump Heap::current_version. 35 + enum class TypeData : u8 { 36 + Null = 1 << 4, 37 + Int8 = 2 << 4, 38 + Int16 = 3 << 4, 39 + Int32 = 4 << 4, 40 + Int64 = 5 << 4, 41 + Uint8 = 6 << 4, 42 + Uint16 = 7 << 4, 43 + Uint32 = 8 << 4, 44 + Uint64 = 9 << 4, 45 + }; 46 + 47 + template<typename Callback> 48 + static decltype(auto) downsize_integer(Integer auto value, Callback&& callback) 22 49 { 50 + if constexpr (IsSigned<decltype(value)>) { 51 + if (AK::is_within_range<i8>(value)) 52 + return callback(static_cast<i8>(value), TypeData::Int8); 53 + if (AK::is_within_range<i16>(value)) 54 + return callback(static_cast<i16>(value), TypeData::Int16); 55 + if (AK::is_within_range<i32>(value)) 56 + return callback(static_cast<i32>(value), TypeData::Int32); 57 + return callback(value, TypeData::Int64); 58 + } else { 59 + if (AK::is_within_range<u8>(value)) 60 + return callback(static_cast<i8>(value), TypeData::Uint8); 61 + if (AK::is_within_range<u16>(value)) 62 + return callback(static_cast<i16>(value), TypeData::Uint16); 63 + if (AK::is_within_range<u32>(value)) 64 + return callback(static_cast<i32>(value), TypeData::Uint32); 65 + return callback(value, TypeData::Uint64); 66 + } 23 67 } 24 68 25 - Value::Value(DeprecatedString value) 26 - : m_type(SQLType::Text) 27 - , m_value(move(value)) 69 + template<typename Callback> 70 + static decltype(auto) downsize_integer(Value const& value, Callback&& callback) 28 71 { 72 + VERIFY(value.is_int()); 73 + 74 + if (value.value().has<i64>()) 75 + return downsize_integer(value.value().get<i64>(), forward<Callback>(callback)); 76 + return downsize_integer(value.value().get<u64>(), forward<Callback>(callback)); 29 77 } 30 78 31 - Value::Value(int value) 32 - : m_type(SQLType::Integer) 33 - , m_value(value) 79 + template<typename Callback> 80 + static ResultOr<Value> perform_integer_operation(Value const& lhs, Value const& rhs, Callback&& callback) 34 81 { 82 + VERIFY(lhs.is_int()); 83 + VERIFY(rhs.is_int()); 84 + 85 + if (lhs.value().has<i64>()) { 86 + if (auto rhs_value = rhs.to_int<i64>(); rhs_value.has_value()) 87 + return callback(lhs.to_int<i64>().value(), rhs_value.value()); 88 + } else { 89 + if (auto rhs_value = rhs.to_int<u64>(); rhs_value.has_value()) 90 + return callback(lhs.to_int<u64>().value(), rhs_value.value()); 91 + } 92 + 93 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 35 94 } 36 95 37 - Value::Value(u32 value) 38 - : m_type(SQLType::Integer) 39 - , m_value(static_cast<int>(value)) // FIXME: Handle signed overflow. 96 + Value::Value(SQLType type) 97 + : m_type(type) 98 + { 99 + } 100 + 101 + Value::Value(DeprecatedString value) 102 + : m_type(SQLType::Text) 103 + , m_value(move(value)) 40 104 { 41 105 } 42 106 43 107 Value::Value(double value) 44 - : m_type(SQLType::Float) 45 - , m_value(value) 46 108 { 109 + if (trunc(value) == value) { 110 + if (AK::is_within_range<i64>(value)) { 111 + m_type = SQLType::Integer; 112 + m_value = static_cast<i64>(value); 113 + return; 114 + } 115 + if (AK::is_within_range<u64>(value)) { 116 + m_type = SQLType::Integer; 117 + m_value = static_cast<u64>(value); 118 + return; 119 + } 120 + } 121 + 122 + m_type = SQLType::Float; 123 + m_value = value; 47 124 } 48 125 49 126 Value::Value(NonnullRefPtr<TupleDescriptor> descriptor, Vector<Value> values) ··· 122 199 return !m_value.has_value(); 123 200 } 124 201 202 + bool Value::is_int() const 203 + { 204 + return m_value.has_value() && (m_value->has<i64>() || m_value->has<u64>()); 205 + } 206 + 125 207 DeprecatedString Value::to_deprecated_string() const 126 208 { 127 209 if (is_null()) ··· 129 211 130 212 return m_value->visit( 131 213 [](DeprecatedString const& value) -> DeprecatedString { return value; }, 132 - [](int value) -> DeprecatedString { return DeprecatedString::number(value); }, 214 + [](Integer auto value) -> DeprecatedString { return DeprecatedString::number(value); }, 133 215 [](double value) -> DeprecatedString { return DeprecatedString::number(value); }, 134 216 [](bool value) -> DeprecatedString { return value ? "true"sv : "false"sv; }, 135 217 [](TupleValue const& value) -> DeprecatedString { ··· 143 225 }); 144 226 } 145 227 146 - Optional<int> Value::to_int() const 147 - { 148 - if (is_null()) 149 - return {}; 150 - 151 - return m_value->visit( 152 - [](DeprecatedString const& value) -> Optional<int> { return value.to_int(); }, 153 - [](int value) -> Optional<int> { return value; }, 154 - [](double value) -> Optional<int> { 155 - if (value > static_cast<double>(NumericLimits<int>::max())) 156 - return {}; 157 - if (value < static_cast<double>(NumericLimits<int>::min())) 158 - return {}; 159 - return static_cast<int>(round(value)); 160 - }, 161 - [](bool value) -> Optional<int> { return static_cast<int>(value); }, 162 - [](TupleValue const&) -> Optional<int> { return {}; }); 163 - } 164 - 165 - Optional<u32> Value::to_u32() const 166 - { 167 - // FIXME: Handle negative values. 168 - if (auto result = to_int(); result.has_value()) 169 - return static_cast<u32>(result.value()); 170 - return {}; 171 - } 172 - 173 228 Optional<double> Value::to_double() const 174 229 { 175 230 if (is_null()) ··· 184 239 return {}; 185 240 return result; 186 241 }, 187 - [](int value) -> Optional<double> { return static_cast<double>(value); }, 242 + [](Integer auto value) -> Optional<double> { return static_cast<double>(value); }, 188 243 [](double value) -> Optional<double> { return value; }, 189 244 [](bool value) -> Optional<double> { return static_cast<double>(value); }, 190 245 [](TupleValue const&) -> Optional<double> { return {}; }); ··· 203 258 return false; 204 259 return {}; 205 260 }, 206 - [](int value) -> Optional<bool> { return static_cast<bool>(value); }, 261 + [](Integer auto value) -> Optional<bool> { return static_cast<bool>(value); }, 207 262 [](double value) -> Optional<bool> { return fabs(value) > NumericLimits<double>::epsilon(); }, 208 263 [](bool value) -> Optional<bool> { return value; }, 209 264 [](TupleValue const& value) -> Optional<bool> { ··· 242 297 return *this; 243 298 } 244 299 245 - Value& Value::operator=(int value) 246 - { 247 - m_type = SQLType::Integer; 248 - m_value = value; 249 - return *this; 250 - } 251 - 252 - Value& Value::operator=(u32 value) 253 - { 254 - m_type = SQLType::Integer; 255 - m_value = static_cast<int>(value); // FIXME: Handle signed overflow. 256 - return *this; 257 - } 258 - 259 300 Value& Value::operator=(double value) 260 301 { 261 302 m_type = SQLType::Float; ··· 318 359 // FIXME: This seems to be more of an encoded byte size rather than a length. 319 360 return m_value->visit( 320 361 [](DeprecatedString const& value) -> size_t { return sizeof(u32) + value.length(); }, 321 - [](int value) -> size_t { return sizeof(value); }, 362 + [](Integer auto value) -> size_t { 363 + return downsize_integer(value, [](auto integer, auto) { 364 + return sizeof(integer); 365 + }); 366 + }, 322 367 [](double value) -> size_t { return sizeof(value); }, 323 368 [](bool value) -> size_t { return sizeof(value); }, 324 369 [](TupleValue const& value) -> size_t { ··· 338 383 339 384 return m_value->visit( 340 385 [](DeprecatedString const& value) -> u32 { return value.hash(); }, 341 - [](int value) -> u32 { return int_hash(value); }, 386 + [](Integer auto value) -> u32 { 387 + return downsize_integer(value, [](auto integer, auto) { 388 + if constexpr (sizeof(decltype(integer)) == 8) 389 + return u64_hash(integer); 390 + else 391 + return int_hash(integer); 392 + }); 393 + }, 342 394 [](double) -> u32 { VERIFY_NOT_REACHED(); }, 343 395 [](bool value) -> u32 { return int_hash(value); }, 344 396 [](TupleValue const& value) -> u32 { ··· 364 416 365 417 return m_value->visit( 366 418 [&](DeprecatedString const& value) -> int { return value.view().compare(other.to_deprecated_string()); }, 367 - [&](int value) -> int { 368 - auto casted = other.to_int(); 419 + [&](Integer auto value) -> int { 420 + auto casted = other.to_int<IntegerType<decltype(value)>>(); 369 421 if (!casted.has_value()) 370 422 return 1; 371 423 ··· 427 479 return to_deprecated_string() == value; 428 480 } 429 481 430 - bool Value::operator==(int value) const 431 - { 432 - return to_int() == value; 433 - } 434 - 435 - bool Value::operator==(u32 value) const 436 - { 437 - return to_u32() == value; 438 - } 439 - 440 482 bool Value::operator==(double value) const 441 483 { 442 484 return to_double() == value; ··· 467 509 return compare(value) >= 0; 468 510 } 469 511 470 - static Result invalid_type_for_numeric_operator(AST::BinaryOperator op) 512 + template<typename Operator> 513 + static Result invalid_type_for_numeric_operator(Operator op) 471 514 { 472 - return { SQLCommand::Unknown, SQLErrorCode::NumericOperatorTypeMismatch, BinaryOperator_name(op) }; 515 + if constexpr (IsSame<Operator, AST::BinaryOperator>) 516 + return { SQLCommand::Unknown, SQLErrorCode::NumericOperatorTypeMismatch, BinaryOperator_name(op) }; 517 + else if constexpr (IsSame<Operator, AST::UnaryOperator>) 518 + return { SQLCommand::Unknown, SQLErrorCode::NumericOperatorTypeMismatch, UnaryOperator_name(op) }; 519 + else 520 + static_assert(DependentFalse<Operator>); 473 521 } 474 522 475 523 ResultOr<Value> Value::add(Value const& other) const 476 524 { 477 - if (auto double_maybe = to_double(); double_maybe.has_value()) { 478 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 479 - return Value(double_maybe.value() + other_double_maybe.value()); 480 - if (auto int_maybe = other.to_int(); int_maybe.has_value()) 481 - return Value(double_maybe.value() + (double)int_maybe.value()); 482 - } else if (auto int_maybe = to_int(); int_maybe.has_value()) { 483 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 484 - return Value(other_double_maybe.value() + (double)int_maybe.value()); 485 - if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) 486 - return Value(int_maybe.value() + other_int_maybe.value()); 525 + if (is_int() && other.is_int()) { 526 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 527 + Checked result { lhs }; 528 + result.add(rhs); 529 + 530 + if (result.has_overflow()) 531 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 532 + return Value { result.value_unchecked() }; 533 + }); 487 534 } 488 - return invalid_type_for_numeric_operator(AST::BinaryOperator::Plus); 535 + 536 + auto lhs = to_double(); 537 + auto rhs = other.to_double(); 538 + 539 + if (!lhs.has_value() || !rhs.has_value()) 540 + return invalid_type_for_numeric_operator(AST::BinaryOperator::Plus); 541 + return Value { lhs.value() + rhs.value() }; 489 542 } 490 543 491 544 ResultOr<Value> Value::subtract(Value const& other) const 492 545 { 493 - if (auto double_maybe = to_double(); double_maybe.has_value()) { 494 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 495 - return Value(double_maybe.value() - other_double_maybe.value()); 496 - if (auto int_maybe = other.to_int(); int_maybe.has_value()) 497 - return Value(double_maybe.value() - (double)int_maybe.value()); 498 - } else if (auto int_maybe = to_int(); int_maybe.has_value()) { 499 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 500 - return Value((double)int_maybe.value() - other_double_maybe.value()); 501 - if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) 502 - return Value(int_maybe.value() - other_int_maybe.value()); 546 + if (is_int() && other.is_int()) { 547 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 548 + Checked result { lhs }; 549 + result.sub(rhs); 550 + 551 + if (result.has_overflow()) 552 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 553 + return Value { result.value_unchecked() }; 554 + }); 503 555 } 504 - return invalid_type_for_numeric_operator(AST::BinaryOperator::Minus); 556 + 557 + auto lhs = to_double(); 558 + auto rhs = other.to_double(); 559 + 560 + if (!lhs.has_value() || !rhs.has_value()) 561 + return invalid_type_for_numeric_operator(AST::BinaryOperator::Minus); 562 + return Value { lhs.value() - rhs.value() }; 505 563 } 506 564 507 565 ResultOr<Value> Value::multiply(Value const& other) const 508 566 { 509 - if (auto double_maybe = to_double(); double_maybe.has_value()) { 510 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 511 - return Value(double_maybe.value() * other_double_maybe.value()); 512 - if (auto int_maybe = other.to_int(); int_maybe.has_value()) 513 - return Value(double_maybe.value() * (double)int_maybe.value()); 514 - } else if (auto int_maybe = to_int(); int_maybe.has_value()) { 515 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 516 - return Value((double)int_maybe.value() * other_double_maybe.value()); 517 - if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) 518 - return Value(int_maybe.value() * other_int_maybe.value()); 567 + if (is_int() && other.is_int()) { 568 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 569 + Checked result { lhs }; 570 + result.mul(rhs); 571 + 572 + if (result.has_overflow()) 573 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 574 + return Value { result.value_unchecked() }; 575 + }); 519 576 } 520 - return invalid_type_for_numeric_operator(AST::BinaryOperator::Multiplication); 577 + 578 + auto lhs = to_double(); 579 + auto rhs = other.to_double(); 580 + 581 + if (!lhs.has_value() || !rhs.has_value()) 582 + return invalid_type_for_numeric_operator(AST::BinaryOperator::Multiplication); 583 + return Value { lhs.value() * rhs.value() }; 521 584 } 522 585 523 586 ResultOr<Value> Value::divide(Value const& other) const 524 587 { 525 - if (auto double_maybe = to_double(); double_maybe.has_value()) { 526 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 527 - return Value(double_maybe.value() / other_double_maybe.value()); 528 - if (auto int_maybe = other.to_int(); int_maybe.has_value()) 529 - return Value(double_maybe.value() / (double)int_maybe.value()); 530 - } else if (auto int_maybe = to_int(); int_maybe.has_value()) { 531 - if (auto other_double_maybe = other.to_double(); other_double_maybe.has_value()) 532 - return Value((double)int_maybe.value() / other_double_maybe.value()); 533 - if (auto other_int_maybe = other.to_int(); other_int_maybe.has_value()) 534 - return Value(int_maybe.value() / other_int_maybe.value()); 535 - } 536 - return invalid_type_for_numeric_operator(AST::BinaryOperator::Division); 588 + auto lhs = to_double(); 589 + auto rhs = other.to_double(); 590 + 591 + if (!lhs.has_value() || !rhs.has_value()) 592 + return invalid_type_for_numeric_operator(AST::BinaryOperator::Division); 593 + if (rhs == 0.0) 594 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 595 + 596 + return Value { lhs.value() / rhs.value() }; 537 597 } 538 598 539 599 ResultOr<Value> Value::modulo(Value const& other) const 540 600 { 541 - auto int_maybe_1 = to_int(); 542 - auto int_maybe_2 = other.to_int(); 543 - if (!int_maybe_1.has_value() || !int_maybe_2.has_value()) 601 + if (!is_int() || !other.is_int()) 544 602 return invalid_type_for_numeric_operator(AST::BinaryOperator::Modulo); 545 - return Value(int_maybe_1.value() % int_maybe_2.value()); 603 + 604 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 605 + Checked result { lhs }; 606 + result.mod(rhs); 607 + 608 + if (result.has_overflow()) 609 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 610 + return Value { result.value_unchecked() }; 611 + }); 612 + } 613 + 614 + ResultOr<Value> Value::negate() const 615 + { 616 + if (type() == SQLType::Integer) { 617 + auto value = to_int<i64>(); 618 + if (!value.has_value()) 619 + return invalid_type_for_numeric_operator(AST::UnaryOperator::Minus); 620 + 621 + return Value { value.value() * -1 }; 622 + } 623 + 624 + if (type() == SQLType::Float) 625 + return Value { -to_double().value() }; 626 + 627 + return invalid_type_for_numeric_operator(AST::UnaryOperator::Minus); 546 628 } 547 629 548 630 ResultOr<Value> Value::shift_left(Value const& other) const 549 631 { 550 - auto u32_maybe = to_u32(); 551 - auto num_bytes_maybe = other.to_int(); 552 - if (!u32_maybe.has_value() || !num_bytes_maybe.has_value()) 632 + if (!is_int() || !other.is_int()) 553 633 return invalid_type_for_numeric_operator(AST::BinaryOperator::ShiftLeft); 554 - return Value(u32_maybe.value() << num_bytes_maybe.value()); 634 + 635 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 636 + using LHS = decltype(lhs); 637 + using RHS = decltype(rhs); 638 + 639 + static constexpr auto max_shift = static_cast<RHS>(sizeof(LHS) * 8); 640 + if (rhs < 0 || rhs >= max_shift) 641 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 642 + 643 + return Value { lhs << rhs }; 644 + }); 555 645 } 556 646 557 647 ResultOr<Value> Value::shift_right(Value const& other) const 558 648 { 559 - auto u32_maybe = to_u32(); 560 - auto num_bytes_maybe = other.to_int(); 561 - if (!u32_maybe.has_value() || !num_bytes_maybe.has_value()) 649 + if (!is_int() || !other.is_int()) 562 650 return invalid_type_for_numeric_operator(AST::BinaryOperator::ShiftRight); 563 - return Value(u32_maybe.value() >> num_bytes_maybe.value()); 651 + 652 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) -> ResultOr<Value> { 653 + using LHS = decltype(lhs); 654 + using RHS = decltype(rhs); 655 + 656 + static constexpr auto max_shift = static_cast<RHS>(sizeof(LHS) * 8); 657 + if (rhs < 0 || rhs >= max_shift) 658 + return Result { SQLCommand::Unknown, SQLErrorCode::IntegerOverflow }; 659 + 660 + return Value { lhs >> rhs }; 661 + }); 564 662 } 565 663 566 664 ResultOr<Value> Value::bitwise_or(Value const& other) const 567 665 { 568 - auto u32_maybe_1 = to_u32(); 569 - auto u32_maybe_2 = other.to_u32(); 570 - if (!u32_maybe_1.has_value() || !u32_maybe_2.has_value()) 666 + if (!is_int() || !other.is_int()) 571 667 return invalid_type_for_numeric_operator(AST::BinaryOperator::BitwiseOr); 572 - return Value(u32_maybe_1.value() | u32_maybe_2.value()); 668 + 669 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) { 670 + return Value { lhs | rhs }; 671 + }); 573 672 } 574 673 575 674 ResultOr<Value> Value::bitwise_and(Value const& other) const 576 675 { 577 - auto u32_maybe_1 = to_u32(); 578 - auto u32_maybe_2 = other.to_u32(); 579 - if (!u32_maybe_1.has_value() || !u32_maybe_2.has_value()) 676 + if (!is_int() || !other.is_int()) 580 677 return invalid_type_for_numeric_operator(AST::BinaryOperator::BitwiseAnd); 581 - return Value(u32_maybe_1.value() & u32_maybe_2.value()); 678 + 679 + return perform_integer_operation(*this, other, [](auto lhs, auto rhs) { 680 + return Value { lhs & rhs }; 681 + }); 582 682 } 583 683 584 - static constexpr auto sql_type_null_as_flag = static_cast<u8>(SQLType::Null); 684 + ResultOr<Value> Value::bitwise_not() const 685 + { 686 + if (!is_int()) 687 + return invalid_type_for_numeric_operator(AST::UnaryOperator::BitwiseNot); 688 + 689 + return downsize_integer(*this, [](auto value, auto) { 690 + return Value { ~value }; 691 + }); 692 + } 693 + 694 + static u8 encode_type_flags(Value const& value) 695 + { 696 + auto type_flags = to_underlying(value.type()); 697 + 698 + if (value.is_null()) { 699 + type_flags |= to_underlying(TypeData::Null); 700 + } else if (value.is_int()) { 701 + downsize_integer(value, [&](auto, auto type_data) { 702 + type_flags |= to_underlying(type_data); 703 + }); 704 + } 705 + 706 + return type_flags; 707 + } 585 708 586 709 void Value::serialize(Serializer& serializer) const 587 710 { 588 - auto type_flags = static_cast<u8>(type()); 589 - if (is_null()) 590 - type_flags |= sql_type_null_as_flag; 591 - 711 + auto type_flags = encode_type_flags(*this); 592 712 serializer.serialize<u8>(type_flags); 593 713 594 714 if (is_null()) 595 715 return; 716 + 717 + if (is_int()) { 718 + downsize_integer(*this, [&](auto integer, auto) { 719 + serializer.serialize(integer); 720 + }); 721 + return; 722 + } 596 723 597 724 m_value->visit( 598 725 [&](TupleValue const& value) { ··· 608 735 void Value::deserialize(Serializer& serializer) 609 736 { 610 737 auto type_flags = serializer.deserialize<u8>(); 611 - bool has_value = true; 612 738 613 - if ((type_flags & sql_type_null_as_flag) && (type_flags != sql_type_null_as_flag)) { 614 - type_flags &= ~sql_type_null_as_flag; 615 - has_value = false; 616 - } 617 - 618 - m_type = static_cast<SQLType>(type_flags); 739 + auto type_data = static_cast<TypeData>(type_flags & 0xf0); 740 + m_type = static_cast<SQLType>(type_flags & 0x0f); 619 741 620 - if (!has_value) 742 + if (type_data == TypeData::Null) 621 743 return; 622 744 623 745 switch (m_type) { ··· 628 750 m_value = serializer.deserialize<DeprecatedString>(); 629 751 break; 630 752 case SQLType::Integer: 631 - m_value = serializer.deserialize<int>(0); 753 + switch (type_data) { 754 + case TypeData::Int8: 755 + m_value = static_cast<i64>(serializer.deserialize<i8>(0)); 756 + break; 757 + case TypeData::Int16: 758 + m_value = static_cast<i64>(serializer.deserialize<i16>(0)); 759 + break; 760 + case TypeData::Int32: 761 + m_value = static_cast<i64>(serializer.deserialize<i32>(0)); 762 + break; 763 + case TypeData::Int64: 764 + m_value = static_cast<i64>(serializer.deserialize<i64>(0)); 765 + break; 766 + case TypeData::Uint8: 767 + m_value = static_cast<u64>(serializer.deserialize<u8>(0)); 768 + break; 769 + case TypeData::Uint16: 770 + m_value = static_cast<u64>(serializer.deserialize<u16>(0)); 771 + break; 772 + case TypeData::Uint32: 773 + m_value = static_cast<u64>(serializer.deserialize<u32>(0)); 774 + break; 775 + case TypeData::Uint64: 776 + m_value = static_cast<u64>(serializer.deserialize<u64>(0)); 777 + break; 778 + default: 779 + VERIFY_NOT_REACHED(); 780 + break; 781 + } 632 782 break; 633 783 case SQLType::Float: 634 784 m_value = serializer.deserialize<double>(0.0); ··· 673 823 template<> 674 824 bool IPC::encode(Encoder& encoder, SQL::Value const& value) 675 825 { 676 - auto type_flags = to_underlying(value.type()); 677 - if (value.is_null()) 678 - type_flags |= SQL::sql_type_null_as_flag; 679 - 826 + auto type_flags = encode_type_flags(value); 680 827 encoder << type_flags; 828 + 681 829 if (value.is_null()) 682 830 return true; 683 831 ··· 688 836 encoder << value.to_deprecated_string(); 689 837 break; 690 838 case SQL::SQLType::Integer: 691 - encoder << value.to_int().value(); 839 + SQL::downsize_integer(value, [&](auto integer, auto) { 840 + encoder << integer; 841 + }); 692 842 break; 693 843 case SQL::SQLType::Float: 694 844 encoder << value.to_double().value(); ··· 702 852 } 703 853 704 854 return true; 855 + } 856 + 857 + template<typename T> 858 + static ErrorOr<void> decode_scalar(IPC::Decoder& decoder, SQL::Value& value) 859 + { 860 + T decoded {}; 861 + TRY(decoder.decode(decoded)); 862 + value = move(decoded); 863 + return {}; 705 864 } 706 865 707 866 template<> 708 867 ErrorOr<void> IPC::decode(Decoder& decoder, SQL::Value& value) 709 868 { 710 - UnderlyingType<SQL::SQLType> type_flags; 869 + u8 type_flags { 0 }; 711 870 TRY(decoder.decode(type_flags)); 712 871 713 - if ((type_flags & SQL::sql_type_null_as_flag) && (type_flags != SQL::sql_type_null_as_flag)) { 714 - type_flags &= ~SQL::sql_type_null_as_flag; 872 + auto type_data = static_cast<SQL::TypeData>(type_flags & 0xf0); 873 + auto type = static_cast<SQL::SQLType>(type_flags & 0x0f); 715 874 716 - value = SQL::Value(static_cast<SQL::SQLType>(type_flags)); 875 + if (type_data == SQL::TypeData::Null) { 876 + value = SQL::Value(type); 717 877 return {}; 718 878 } 719 879 720 - switch (static_cast<SQL::SQLType>(type_flags)) { 880 + switch (type) { 721 881 case SQL::SQLType::Null: 722 882 break; 723 - case SQL::SQLType::Text: { 724 - DeprecatedString text; 725 - TRY(decoder.decode(text)); 726 - value = move(text); 883 + case SQL::SQLType::Text: 884 + TRY(decode_scalar<DeprecatedString>(decoder, value)); 727 885 break; 728 - } 729 - case SQL::SQLType::Integer: { 730 - int number { 0 }; 731 - TRY(decoder.decode(number)); 732 - value = number; 886 + case SQL::SQLType::Integer: 887 + switch (type_data) { 888 + case SQL::TypeData::Int8: 889 + TRY(decode_scalar<i8>(decoder, value)); 890 + break; 891 + case SQL::TypeData::Int16: 892 + TRY(decode_scalar<i16>(decoder, value)); 893 + break; 894 + case SQL::TypeData::Int32: 895 + TRY(decode_scalar<i32>(decoder, value)); 896 + break; 897 + case SQL::TypeData::Int64: 898 + TRY(decode_scalar<i64>(decoder, value)); 899 + break; 900 + case SQL::TypeData::Uint8: 901 + TRY(decode_scalar<u8>(decoder, value)); 902 + break; 903 + case SQL::TypeData::Uint16: 904 + TRY(decode_scalar<u16>(decoder, value)); 905 + break; 906 + case SQL::TypeData::Uint32: 907 + TRY(decode_scalar<u32>(decoder, value)); 908 + break; 909 + case SQL::TypeData::Uint64: 910 + TRY(decode_scalar<u64>(decoder, value)); 911 + break; 912 + default: 913 + VERIFY_NOT_REACHED(); 914 + break; 915 + } 733 916 break; 734 - } 735 - case SQL::SQLType::Float: { 736 - double number { 0.0 }; 737 - TRY(decoder.decode(number)); 738 - value = number; 917 + case SQL::SQLType::Float: 918 + TRY(decode_scalar<double>(decoder, value)); 739 919 break; 740 - } 741 - case SQL::SQLType::Boolean: { 742 - bool boolean { false }; 743 - TRY(decoder.decode(boolean)); 744 - value = boolean; 920 + case SQL::SQLType::Boolean: 921 + TRY(decode_scalar<bool>(decoder, value)); 745 922 break; 746 - } 747 923 case SQL::SQLType::Tuple: { 748 924 Vector<SQL::Value> tuple; 749 925 TRY(decoder.decode(tuple));
+72 -15
Userland/Libraries/LibSQL/Value.h
··· 7 7 8 8 #pragma once 9 9 10 + #include <AK/Checked.h> 10 11 #include <AK/DeprecatedString.h> 11 12 #include <AK/Format.h> 12 13 #include <AK/Optional.h> ··· 17 18 #include <LibSQL/Forward.h> 18 19 #include <LibSQL/Result.h> 19 20 #include <LibSQL/Type.h> 21 + #include <math.h> 20 22 21 23 namespace SQL { 22 24 25 + template<typename T> 26 + concept Boolean = SameAs<RemoveCVReference<T>, bool>; 27 + 28 + template<typename T> 29 + concept Integer = (Integral<T> && !Boolean<T>); 30 + 23 31 /** 24 32 * A `Value` is an atomic piece of SQL data`. A `Value` has a basic type 25 33 * (Text/String, Integer, Float, etc). Richer types are implemented in higher 26 34 * level layers, but the resulting data is stored in these `Value` objects. 27 35 */ 28 36 class Value { 37 + template<Integer T> 38 + using IntegerType = Conditional<IsSigned<T>, i64, u64>; 39 + 29 40 public: 30 41 explicit Value(SQLType sql_type = SQLType::Null); 31 42 explicit Value(DeprecatedString); 32 - explicit Value(int); 33 - explicit Value(u32); 34 43 explicit Value(double); 35 44 Value(Value const&); 36 45 Value(Value&&); 37 46 ~Value(); 38 47 39 - static ResultOr<Value> create_tuple(NonnullRefPtr<TupleDescriptor>); 40 - static ResultOr<Value> create_tuple(Vector<Value>); 48 + explicit Value(Integer auto value) 49 + : m_type(SQLType::Integer) 50 + , m_value(static_cast<IntegerType<decltype(value)>>(value)) 51 + { 52 + } 41 53 42 - template<typename T> 43 - requires(SameAs<RemoveCVReference<T>, bool>) explicit Value(T value) 54 + explicit Value(Boolean auto value) 44 55 : m_type(SQLType::Boolean) 45 56 , m_value(value) 46 57 { 47 58 } 48 59 60 + static ResultOr<Value> create_tuple(NonnullRefPtr<TupleDescriptor>); 61 + static ResultOr<Value> create_tuple(Vector<Value>); 62 + 49 63 [[nodiscard]] SQLType type() const; 50 64 [[nodiscard]] StringView type_name() const; 51 65 [[nodiscard]] bool is_type_compatible_with(SQLType) const; 52 66 [[nodiscard]] bool is_null() const; 67 + [[nodiscard]] bool is_int() const; 68 + 69 + [[nodiscard]] auto const& value() const 70 + { 71 + VERIFY(m_value.has_value()); 72 + return *m_value; 73 + } 53 74 54 75 [[nodiscard]] DeprecatedString to_deprecated_string() const; 55 - [[nodiscard]] Optional<int> to_int() const; 56 - [[nodiscard]] Optional<u32> to_u32() const; 57 76 [[nodiscard]] Optional<double> to_double() const; 58 77 [[nodiscard]] Optional<bool> to_bool() const; 59 78 [[nodiscard]] Optional<Vector<Value>> to_vector() const; 60 79 80 + template<Integer T> 81 + [[nodiscard]] Optional<T> to_int() const 82 + { 83 + if (is_null()) 84 + return {}; 85 + 86 + return m_value->visit( 87 + [](DeprecatedString const& value) -> Optional<T> { 88 + if constexpr (IsSigned<T>) 89 + return value.to_int<T>(); 90 + else 91 + return value.to_uint<T>(); 92 + }, 93 + [](Integer auto value) -> Optional<T> { 94 + if (!AK::is_within_range<T>(value)) 95 + return {}; 96 + return static_cast<T>(value); 97 + }, 98 + [](double value) -> Optional<T> { 99 + if (!AK::is_within_range<T>(value)) 100 + return {}; 101 + return static_cast<T>(round(value)); 102 + }, 103 + [](bool value) -> Optional<T> { return static_cast<T>(value); }, 104 + [](TupleValue const&) -> Optional<T> { return {}; }); 105 + } 106 + 61 107 Value& operator=(Value); 62 108 Value& operator=(DeprecatedString); 63 - Value& operator=(int); 64 - Value& operator=(u32); 65 109 Value& operator=(double); 66 110 111 + Value& operator=(Integer auto value) 112 + { 113 + m_type = SQLType::Integer; 114 + m_value = static_cast<IntegerType<decltype(value)>>(value); 115 + return *this; 116 + } 117 + 67 118 ResultOr<void> assign_tuple(NonnullRefPtr<TupleDescriptor>); 68 119 ResultOr<void> assign_tuple(Vector<Value>); 69 120 70 - template<typename T> 71 - requires(SameAs<RemoveCVReference<T>, bool>) Value& operator=(T value) 121 + Value& operator=(Boolean auto value) 72 122 { 73 123 m_type = SQLType::Boolean; 74 124 m_value = value; ··· 83 133 [[nodiscard]] int compare(Value const&) const; 84 134 bool operator==(Value const&) const; 85 135 bool operator==(StringView) const; 86 - bool operator==(int) const; 87 - bool operator==(u32) const; 88 136 bool operator==(double) const; 137 + 138 + template<Integer T> 139 + bool operator==(T value) 140 + { 141 + return to_int<T>() == value; 142 + } 143 + 89 144 bool operator!=(Value const&) const; 90 145 bool operator<(Value const&) const; 91 146 bool operator<=(Value const&) const; ··· 97 152 ResultOr<Value> multiply(Value const&) const; 98 153 ResultOr<Value> divide(Value const&) const; 99 154 ResultOr<Value> modulo(Value const&) const; 155 + ResultOr<Value> negate() const; 100 156 ResultOr<Value> shift_left(Value const&) const; 101 157 ResultOr<Value> shift_right(Value const&) const; 102 158 ResultOr<Value> bitwise_or(Value const&) const; 103 159 ResultOr<Value> bitwise_and(Value const&) const; 160 + ResultOr<Value> bitwise_not() const; 104 161 105 162 [[nodiscard]] TupleElementDescriptor descriptor() const; 106 163 ··· 112 169 Vector<Value> values; 113 170 }; 114 171 115 - using ValueType = Variant<DeprecatedString, int, double, bool, TupleValue>; 172 + using ValueType = Variant<DeprecatedString, i64, u64, double, bool, TupleValue>; 116 173 117 174 static ResultOr<NonnullRefPtr<TupleDescriptor>> infer_tuple_descriptor(Vector<Value> const& values); 118 175 Value(NonnullRefPtr<TupleDescriptor> descriptor, Vector<Value> values);