SQLiteStatementBuilder.cpp (28051B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "Public/winget/SQLiteStatementBuilder.h" 5 6 namespace AppInstaller::SQLite::Builder 7 { 8 std::ostream& operator<<(std::ostream& out, const QualifiedColumn& column) 9 { 10 if (!column.Table.empty()) 11 { 12 out << '[' << column.Table << "]."; 13 } 14 out << '[' << column.Column << ']'; 15 return out; 16 } 17 18 std::ostream& operator<<(std::ostream& out, const QualifiedTable& table) 19 { 20 if (!table.Schema.empty()) 21 { 22 out << '[' << table.Schema << "]."; 23 } 24 out << '[' << table.Table << ']'; 25 return out; 26 } 27 28 std::ostream& operator<<(std::ostream& out, const details::SubBuilder& column) 29 { 30 out << column.GetString(); 31 return out; 32 } 33 34 namespace 35 { 36 void OutputColumns(std::ostream& out, std::string_view op, std::string_view column) 37 { 38 out << op << '[' << column << ']'; 39 } 40 41 void OutputColumns(std::ostream& out, std::string_view op, std::initializer_list<std::string_view> columns) 42 { 43 out << op; 44 bool isFirst = true; 45 for (const auto& c : columns) 46 { 47 out << (isFirst ? "[" : ", [") << c << ']'; 48 isFirst = false; 49 } 50 } 51 52 void OutputColumns(std::ostream& out, std::string_view op, const QualifiedColumn& column) 53 { 54 out << op << column; 55 } 56 57 void OutputColumns(std::ostream& out, std::string_view op, std::initializer_list<QualifiedColumn> columns) 58 { 59 out << op; 60 bool isFirst = true; 61 for (const auto& c : columns) 62 { 63 out << (isFirst ? "" : ", ") << c; 64 isFirst = false; 65 } 66 } 67 68 void OutputColumns(std::ostream& out, std::string_view op, std::initializer_list<details::SubBuilder> columns) 69 { 70 out << op; 71 bool isFirst = true; 72 for (const auto& c : columns) 73 { 74 out << (isFirst ? "" : ", ") << c; 75 isFirst = false; 76 } 77 } 78 79 void OutputAggregate(std::ostream& out, Aggregate op) 80 { 81 out << ' '; 82 switch (op) 83 { 84 case Aggregate::Min: 85 out << "MIN"; 86 break; 87 case Aggregate::Max: 88 out << "MAX"; 89 break; 90 default: 91 THROW_HR(E_UNEXPECTED); 92 } 93 } 94 95 void OutputColumns(std::ostream& out, Aggregate op, std::string_view column) 96 { 97 OutputAggregate(out, op); 98 out << "([" << column << "])"; 99 } 100 101 void OutputColumns(std::ostream& out, Aggregate op, const QualifiedColumn& column) 102 { 103 OutputAggregate(out, op); 104 out << '(' << column << ')'; 105 } 106 107 // Use to output operation and table name, such as " FROM [table]" 108 void OutputOperationAndTable(std::ostream& out, std::string_view op, std::string_view table) 109 { 110 out << op << " [" << table << ']'; 111 } 112 113 void OutputOperationAndTable(std::ostream& out, std::string_view op, QualifiedTable table) 114 { 115 out << op << table; 116 } 117 118 void OutputOperationAndTable(std::ostream& out, std::string_view op, std::initializer_list<std::string_view> table) 119 { 120 out << op << " ["; 121 for (std::string_view t : table) 122 { 123 out << t; 124 } 125 out << ']'; 126 } 127 128 void OutputType(std::ostream& out, Type type) 129 { 130 out << ' '; 131 switch (type) 132 { 133 case Type::Int: 134 out << "INT"; 135 break; 136 case Type::Int64: 137 out << "INT64"; 138 break; 139 case Type::Text: 140 out << "TEXT"; 141 break; 142 case Type::Blob: 143 out << "BLOB"; 144 break; 145 case Type::Integer: 146 out << "INTEGER"; 147 break; 148 case Type::None: 149 break; 150 default: 151 THROW_HR(E_UNEXPECTED); 152 } 153 } 154 } 155 156 IntegerPrimaryKey::IntegerPrimaryKey() 157 { 158 m_stream << SQLite::RowIDName << " INTEGER PRIMARY KEY"; 159 } 160 161 IntegerPrimaryKey& IntegerPrimaryKey::AutoIncrement(bool isTrue) 162 { 163 if (isTrue) 164 { 165 m_stream << " AUTOINCREMENT"; 166 } 167 return *this; 168 } 169 170 ColumnBuilder::ColumnBuilder(std::string_view column, Type type) 171 { 172 OutputColumns(m_stream, "", column); 173 OutputType(m_stream, type); 174 } 175 176 ColumnBuilder& ColumnBuilder::NotNull(bool isTrue) 177 { 178 if (isTrue) 179 { 180 m_stream << " NOT NULL"; 181 } 182 return *this; 183 } 184 185 ColumnBuilder& ColumnBuilder::CollateNoCase(bool isTrue) 186 { 187 if (isTrue) 188 { 189 m_stream << " COLLATE NOCASE"; 190 } 191 return *this; 192 } 193 194 ColumnBuilder& ColumnBuilder::Default(int64_t value) 195 { 196 m_stream << " DEFAULT " << value; 197 return *this; 198 } 199 200 ColumnBuilder& ColumnBuilder::Unique(bool isTrue) 201 { 202 if (isTrue) 203 { 204 m_stream << " UNIQUE"; 205 } 206 return *this; 207 } 208 209 ColumnBuilder& ColumnBuilder::PrimaryKey(bool isTrue) 210 { 211 if (isTrue) 212 { 213 m_stream << " PRIMARY KEY"; 214 } 215 return *this; 216 } 217 218 PrimaryKeyBuilder::PrimaryKeyBuilder(std::initializer_list<std::string_view> columns) 219 { 220 OutputColumns(m_stream, "PRIMARY KEY(", columns); 221 m_stream << ')'; 222 m_needsClosing = false; 223 } 224 225 PrimaryKeyBuilder::PrimaryKeyBuilder() 226 { 227 m_stream << "PRIMARY KEY("; 228 } 229 230 PrimaryKeyBuilder& PrimaryKeyBuilder::Column(std::string_view column) 231 { 232 if (m_isFirst) 233 { 234 m_isFirst = false; 235 } 236 else 237 { 238 m_stream << ", "; 239 } 240 OutputColumns(m_stream, "", column); 241 return *this; 242 } 243 244 PrimaryKeyBuilder::operator details::SubBuilder() 245 { 246 if (m_needsClosing) 247 { 248 m_stream << ')'; 249 m_needsClosing = false; 250 } 251 return { m_stream.str() }; 252 } 253 254 StatementBuilder& StatementBuilder::Select() 255 { 256 m_stream << "SELECT "; 257 m_needsComma = false; 258 return *this; 259 } 260 261 StatementBuilder& StatementBuilder::Select(std::string_view column) 262 { 263 OutputColumns(m_stream, "SELECT ", column); 264 return *this; 265 } 266 267 StatementBuilder& StatementBuilder::Select(std::initializer_list<std::string_view> columns) 268 { 269 OutputColumns(m_stream, "SELECT ", columns); 270 return *this; 271 } 272 273 StatementBuilder& StatementBuilder::Select(const QualifiedColumn& column) 274 { 275 OutputColumns(m_stream, "SELECT ", column); 276 return *this; 277 } 278 279 StatementBuilder& StatementBuilder::Select(std::initializer_list<QualifiedColumn> columns) 280 { 281 OutputColumns(m_stream, "SELECT ", columns); 282 return *this; 283 } 284 285 StatementBuilder& StatementBuilder::Select(details::rowcount_t) 286 { 287 m_stream << "SELECT COUNT(*)"; 288 return *this; 289 } 290 291 StatementBuilder& StatementBuilder::From() 292 { 293 m_stream << " FROM "; 294 return *this; 295 } 296 297 StatementBuilder& StatementBuilder::From(std::string_view table) 298 { 299 OutputOperationAndTable(m_stream, " FROM", table); 300 return *this; 301 } 302 303 StatementBuilder& StatementBuilder::From(QualifiedTable table) 304 { 305 OutputOperationAndTable(m_stream, " FROM", table); 306 return *this; 307 } 308 309 StatementBuilder& StatementBuilder::From(std::initializer_list<std::string_view> table) 310 { 311 OutputOperationAndTable(m_stream, " FROM", table); 312 return *this; 313 } 314 315 StatementBuilder& StatementBuilder::Where(std::string_view column) 316 { 317 OutputColumns(m_stream, " WHERE ", column); 318 return *this; 319 } 320 321 StatementBuilder& StatementBuilder::Where(const QualifiedColumn& column) 322 { 323 OutputColumns(m_stream, " WHERE ", column); 324 return *this; 325 } 326 327 StatementBuilder& StatementBuilder::WhereValueContainsEmbeddedNullCharacter(std::string_view column) 328 { 329 OutputColumns(m_stream, " WHERE instr(", column); 330 m_stream << ",char(0))>0"; 331 return *this; 332 } 333 334 StatementBuilder& StatementBuilder::WhereValueContainsEmbeddedNullCharacter(const QualifiedColumn& column) 335 { 336 OutputColumns(m_stream, " WHERE instr(", column); 337 m_stream << ",char(0))>0"; 338 return *this; 339 } 340 341 StatementBuilder& StatementBuilder::Equals(details::unbound_t, std::optional<size_t> index) 342 { 343 AppendOpAndBinder(Op::Equals, index); 344 return *this; 345 } 346 347 StatementBuilder& StatementBuilder::Equals(std::nullptr_t) 348 { 349 // This is almost certainly not what you want. 350 // In SQL, value = NULL is always false. 351 // Use StatementBuilder::IsNull instead. 352 THROW_HR(E_NOTIMPL); 353 } 354 355 StatementBuilder& StatementBuilder::Equals() 356 { 357 m_stream << " ="; 358 return *this; 359 } 360 361 StatementBuilder& StatementBuilder::Equals(const QualifiedColumn& column) 362 { 363 OutputColumns(m_stream, " = ", column); 364 return *this; 365 } 366 367 StatementBuilder& StatementBuilder::IsGreaterThan(details::unbound_t, std::optional<size_t> index) 368 { 369 AppendOpAndBinder(Op::GreaterThan, index); 370 return *this; 371 } 372 373 StatementBuilder& StatementBuilder::IsGreaterThanOrEqualTo(details::unbound_t, std::optional<size_t> index) 374 { 375 AppendOpAndBinder(Op::GreaterThanOrEqualTo, index); 376 return *this; 377 } 378 379 StatementBuilder& StatementBuilder::LikeWithEscape(std::string_view value) 380 { 381 AddBindFunctor(AppendOpAndBinder(Op::Like), EscapeStringForLike(value)); 382 return Escape(EscapeCharForLike); 383 } 384 385 StatementBuilder& StatementBuilder::Like(details::unbound_t) 386 { 387 AppendOpAndBinder(Op::Like); 388 return *this; 389 } 390 391 StatementBuilder& StatementBuilder::Escape(std::string_view escapeChar) 392 { 393 THROW_HR_IF(E_INVALIDARG, escapeChar.length() != 1); 394 AddBindFunctor(AppendOpAndBinder(Op::Escape), escapeChar); 395 return *this; 396 } 397 398 StatementBuilder& StatementBuilder::Not() 399 { 400 m_stream << " NOT"; 401 return *this; 402 } 403 404 StatementBuilder& StatementBuilder::In() 405 { 406 m_stream << " IN"; 407 return *this; 408 } 409 410 StatementBuilder& StatementBuilder::In(size_t count) 411 { 412 m_stream << " IN ("; 413 for (size_t i = 0; i < count; ++i) 414 { 415 m_stream << (i == 0 ? "?" : ", ?"); 416 } 417 m_stream << ')'; 418 419 m_bindIndex += static_cast<int>(count); 420 return *this; 421 } 422 423 StatementBuilder& StatementBuilder::IsNull(bool isNull) 424 { 425 m_stream << " IS " << (isNull ? "" : "NOT ") << "NULL"; 426 return *this; 427 } 428 429 StatementBuilder& StatementBuilder::And(std::string_view column) 430 { 431 OutputColumns(m_stream, " AND ", column); 432 return *this; 433 } 434 435 StatementBuilder& StatementBuilder::And(const QualifiedColumn& column) 436 { 437 OutputColumns(m_stream, " AND ", column); 438 return *this; 439 } 440 441 StatementBuilder& StatementBuilder::Or(const QualifiedColumn& column) 442 { 443 OutputColumns(m_stream, " OR ", column); 444 return *this; 445 } 446 447 StatementBuilder& StatementBuilder::Join(std::string_view table) 448 { 449 OutputOperationAndTable(m_stream, " JOIN", table); 450 return *this; 451 } 452 453 StatementBuilder& StatementBuilder::Join(QualifiedTable table) 454 { 455 OutputOperationAndTable(m_stream, " JOIN", table); 456 return *this; 457 } 458 459 StatementBuilder& StatementBuilder::Join(std::initializer_list<std::string_view> table) 460 { 461 OutputOperationAndTable(m_stream, " JOIN", table); 462 return *this; 463 } 464 465 StatementBuilder& StatementBuilder::LeftOuterJoin(std::string_view table) 466 { 467 OutputOperationAndTable(m_stream, " LEFT OUTER JOIN", table); 468 return *this; 469 } 470 471 StatementBuilder& StatementBuilder::LeftOuterJoin(QualifiedTable table) 472 { 473 OutputOperationAndTable(m_stream, " LEFT OUTER JOIN", table); 474 return *this; 475 } 476 477 StatementBuilder& StatementBuilder::LeftOuterJoin(std::initializer_list<std::string_view> table) 478 { 479 OutputOperationAndTable(m_stream, " LEFT OUTER JOIN", table); 480 return *this; 481 } 482 483 StatementBuilder& StatementBuilder::On(const QualifiedColumn& column1, const QualifiedColumn& column2) 484 { 485 m_stream << " ON " << column1 << " = " << column2; 486 return *this; 487 } 488 489 StatementBuilder& StatementBuilder::Limit(size_t rowCount) 490 { 491 m_stream << " LIMIT " << rowCount; 492 return *this; 493 } 494 495 StatementBuilder& StatementBuilder::GroupBy(std::string_view column) 496 { 497 OutputColumns(m_stream, " GROUP BY ", column); 498 return *this; 499 } 500 501 StatementBuilder& StatementBuilder::GroupBy(const QualifiedColumn& column) 502 { 503 OutputColumns(m_stream, " GROUP BY ", column); 504 return *this; 505 } 506 507 StatementBuilder& StatementBuilder::OrderBy(std::string_view column) 508 { 509 OutputColumns(m_stream, " ORDER BY ", column); 510 return *this; 511 } 512 513 StatementBuilder& StatementBuilder::OrderBy(const QualifiedColumn& column) 514 { 515 OutputColumns(m_stream, " ORDER BY ", column); 516 return *this; 517 } 518 519 StatementBuilder& StatementBuilder::OrderBy(std::initializer_list<std::string_view> columns) 520 { 521 OutputColumns(m_stream, " ORDER BY ", columns); 522 return *this; 523 } 524 525 StatementBuilder& StatementBuilder::Ascending() 526 { 527 m_stream << " ASC"; 528 return *this; 529 } 530 531 StatementBuilder& StatementBuilder::Descending() 532 { 533 m_stream << " DESC"; 534 return *this; 535 } 536 537 StatementBuilder& StatementBuilder::InsertInto(std::string_view table) 538 { 539 OutputOperationAndTable(m_stream, "INSERT INTO", table); 540 return *this; 541 } 542 543 StatementBuilder& StatementBuilder::InsertInto(QualifiedTable table) 544 { 545 OutputOperationAndTable(m_stream, "INSERT INTO", table); 546 return *this; 547 } 548 549 StatementBuilder& StatementBuilder::InsertInto(std::initializer_list<std::string_view> table) 550 { 551 OutputOperationAndTable(m_stream, "INSERT INTO", table); 552 return *this; 553 } 554 555 StatementBuilder& StatementBuilder::InsertOrIgnore(std::string_view table) 556 { 557 OutputOperationAndTable(m_stream, "INSERT OR IGNORE INTO", table); 558 return *this; 559 } 560 561 StatementBuilder& StatementBuilder::InsertOrIgnore(QualifiedTable table) 562 { 563 OutputOperationAndTable(m_stream, "INSERT OR IGNORE INTO", table); 564 return *this; 565 } 566 567 StatementBuilder& StatementBuilder::InsertOrIgnore(std::initializer_list<std::string_view> table) 568 { 569 OutputOperationAndTable(m_stream, "INSERT OR IGNORE INTO", table); 570 return *this; 571 } 572 573 StatementBuilder& StatementBuilder::Columns(std::string_view column) 574 { 575 OutputColumns(m_stream, "(", column); 576 m_stream << ')'; 577 return *this; 578 } 579 580 StatementBuilder& StatementBuilder::Columns(std::initializer_list<std::string_view> columns) 581 { 582 OutputColumns(m_stream, "(", columns); 583 m_stream << ')'; 584 return *this; 585 } 586 587 StatementBuilder& StatementBuilder::Columns(const QualifiedColumn& column) 588 { 589 OutputColumns(m_stream, "(", column); 590 m_stream << ')'; 591 return *this; 592 } 593 594 StatementBuilder& StatementBuilder::Columns(std::initializer_list<QualifiedColumn> columns) 595 { 596 OutputColumns(m_stream, "(", columns); 597 m_stream << ')'; 598 return *this; 599 } 600 601 StatementBuilder& StatementBuilder::Columns(std::initializer_list<details::SubBuilder> columns) 602 { 603 OutputColumns(m_stream, "(", columns); 604 m_stream << ')'; 605 return *this; 606 } 607 608 StatementBuilder& StatementBuilder::BeginColumns() 609 { 610 m_stream << '('; 611 m_needsComma = false; 612 return *this; 613 } 614 615 StatementBuilder& StatementBuilder::Column(std::string_view column) 616 { 617 if (m_needsComma) 618 { 619 m_stream << ", "; 620 } 621 OutputColumns(m_stream, "", column); 622 m_needsComma = true; 623 return *this; 624 } 625 626 StatementBuilder& StatementBuilder::Column(const QualifiedColumn& column) 627 { 628 if (m_needsComma) 629 { 630 m_stream << ", "; 631 } 632 OutputColumns(m_stream, "", column); 633 m_needsComma = true; 634 return *this; 635 } 636 637 StatementBuilder& StatementBuilder::Column(Aggregate aggOp, std::string_view column) 638 { 639 if (m_needsComma) 640 { 641 m_stream << ", "; 642 } 643 OutputColumns(m_stream, aggOp, column); 644 m_needsComma = true; 645 return *this; 646 } 647 648 StatementBuilder& StatementBuilder::Column(Aggregate aggOp, const QualifiedColumn& column) 649 { 650 if (m_needsComma) 651 { 652 m_stream << ", "; 653 } 654 OutputColumns(m_stream, aggOp, column); 655 m_needsComma = true; 656 return *this; 657 } 658 659 StatementBuilder& StatementBuilder::Column(const details::SubBuilder& column) 660 { 661 if (m_needsComma) 662 { 663 m_stream << ", "; 664 } 665 m_stream << column; 666 m_needsComma = true; 667 return *this; 668 } 669 670 StatementBuilder& StatementBuilder::EndColumns() 671 { 672 m_stream << ')'; 673 m_needsComma = false; 674 return *this; 675 } 676 677 StatementBuilder& StatementBuilder::NotNull(bool isTrue) 678 { 679 if (isTrue) 680 { 681 m_stream << " NOT NULL"; 682 } 683 return *this; 684 } 685 686 StatementBuilder& StatementBuilder::BeginValues() 687 { 688 m_stream << " VALUES ("; 689 m_needsComma = false; 690 return *this; 691 } 692 693 StatementBuilder& StatementBuilder::EndValues() 694 { 695 m_stream << ')'; 696 m_needsComma = false; 697 return *this; 698 } 699 700 StatementBuilder& StatementBuilder::CreateTable(std::string_view table) 701 { 702 OutputOperationAndTable(m_stream, "CREATE TABLE", table); 703 return *this; 704 } 705 706 StatementBuilder& StatementBuilder::CreateTable(QualifiedTable table) 707 { 708 OutputOperationAndTable(m_stream, "CREATE TABLE", table); 709 return *this; 710 } 711 712 StatementBuilder& StatementBuilder::CreateTable(std::initializer_list<std::string_view> table) 713 { 714 OutputOperationAndTable(m_stream, "CREATE TABLE", table); 715 return *this; 716 } 717 718 StatementBuilder& StatementBuilder::AlterTable(std::string_view table) 719 { 720 OutputOperationAndTable(m_stream, "ALTER TABLE", table); 721 return *this; 722 } 723 724 StatementBuilder& StatementBuilder::AlterTable(QualifiedTable table) 725 { 726 OutputOperationAndTable(m_stream, "ALTER TABLE", table); 727 return *this; 728 } 729 730 StatementBuilder& StatementBuilder::AlterTable(std::initializer_list<std::string_view> table) 731 { 732 OutputOperationAndTable(m_stream, "ALTER TABLE", table); 733 return *this; 734 } 735 736 StatementBuilder& StatementBuilder::Add(std::string_view column, Type type) 737 { 738 m_stream << " ADD " << column; 739 OutputType(m_stream, type); 740 return *this; 741 } 742 743 StatementBuilder& StatementBuilder::DropTable(std::string_view table) 744 { 745 OutputOperationAndTable(m_stream, "DROP TABLE", table); 746 return *this; 747 } 748 749 StatementBuilder& StatementBuilder::DropTable(QualifiedTable table) 750 { 751 OutputOperationAndTable(m_stream, "DROP TABLE", table); 752 return *this; 753 } 754 755 StatementBuilder& StatementBuilder::DropTable(std::initializer_list<std::string_view> table) 756 { 757 OutputOperationAndTable(m_stream, "DROP TABLE", table); 758 return *this; 759 } 760 761 StatementBuilder& StatementBuilder::DropTableIfExists(std::string_view table) 762 { 763 OutputOperationAndTable(m_stream, "DROP TABLE IF EXISTS", table); 764 return *this; 765 } 766 767 StatementBuilder& StatementBuilder::DropTableIfExists(QualifiedTable table) 768 { 769 OutputOperationAndTable(m_stream, "DROP TABLE IF EXISTS", table); 770 return *this; 771 } 772 773 StatementBuilder& StatementBuilder::DropTableIfExists(std::initializer_list<std::string_view> table) 774 { 775 OutputOperationAndTable(m_stream, "DROP TABLE IF EXISTS", table); 776 return *this; 777 } 778 779 StatementBuilder& StatementBuilder::CreateIndex(std::string_view table) 780 { 781 OutputOperationAndTable(m_stream, "CREATE INDEX", table); 782 return *this; 783 } 784 785 StatementBuilder& StatementBuilder::CreateIndex(QualifiedTable table) 786 { 787 OutputOperationAndTable(m_stream, "CREATE INDEX", table); 788 return *this; 789 } 790 791 StatementBuilder& StatementBuilder::CreateIndex(std::initializer_list<std::string_view> table) 792 { 793 OutputOperationAndTable(m_stream, "CREATE INDEX", table); 794 return *this; 795 } 796 797 StatementBuilder& StatementBuilder::CreateUniqueIndex(std::string_view table) 798 { 799 OutputOperationAndTable(m_stream, "CREATE UNIQUE INDEX", table); 800 return *this; 801 } 802 803 StatementBuilder& StatementBuilder::CreateUniqueIndex(QualifiedTable table) 804 { 805 OutputOperationAndTable(m_stream, "CREATE UNIQUE INDEX", table); 806 return *this; 807 } 808 809 StatementBuilder& StatementBuilder::CreateUniqueIndex(std::initializer_list<std::string_view> table) 810 { 811 OutputOperationAndTable(m_stream, "CREATE UNIQUE INDEX", table); 812 return *this; 813 } 814 815 StatementBuilder& StatementBuilder::DropIndex(std::string_view index) 816 { 817 OutputOperationAndTable(m_stream, "DROP INDEX", index); 818 return *this; 819 } 820 821 StatementBuilder& StatementBuilder::DropIndex(QualifiedTable index) 822 { 823 OutputOperationAndTable(m_stream, "DROP INDEX", index); 824 return *this; 825 } 826 827 StatementBuilder& StatementBuilder::DropIndex(std::initializer_list<std::string_view> index) 828 { 829 OutputOperationAndTable(m_stream, "DROP INDEX", index); 830 return *this; 831 } 832 833 StatementBuilder& StatementBuilder::On(std::string_view table) 834 { 835 OutputOperationAndTable(m_stream, " ON", table); 836 return *this; 837 } 838 839 StatementBuilder& StatementBuilder::On(std::initializer_list<std::string_view> table) 840 { 841 OutputOperationAndTable(m_stream, " ON", table); 842 return *this; 843 } 844 845 StatementBuilder& StatementBuilder::DeleteFrom(std::string_view table) 846 { 847 OutputOperationAndTable(m_stream, "DELETE FROM", table); 848 return *this; 849 } 850 851 StatementBuilder& StatementBuilder::DeleteFrom(QualifiedTable table) 852 { 853 OutputOperationAndTable(m_stream, "DELETE FROM", table); 854 return *this; 855 } 856 857 StatementBuilder& StatementBuilder::DeleteFrom(std::initializer_list<std::string_view> table) 858 { 859 OutputOperationAndTable(m_stream, "DELETE FROM", table); 860 return *this; 861 } 862 863 StatementBuilder& StatementBuilder::Update(std::string_view table) 864 { 865 OutputOperationAndTable(m_stream, "UPDATE", table); 866 return *this; 867 } 868 869 StatementBuilder& StatementBuilder::Update(QualifiedTable table) 870 { 871 OutputOperationAndTable(m_stream, "UPDATE", table); 872 return *this; 873 } 874 875 StatementBuilder& StatementBuilder::Update(std::initializer_list<std::string_view> table) 876 { 877 OutputOperationAndTable(m_stream, "UPDATE", table); 878 return *this; 879 } 880 881 StatementBuilder& StatementBuilder::UpdateOrReplace(std::string_view table) 882 { 883 OutputOperationAndTable(m_stream, "UPDATE OR REPLACE", table); 884 return *this; 885 } 886 887 StatementBuilder& StatementBuilder::UpdateOrReplace(QualifiedTable table) 888 { 889 OutputOperationAndTable(m_stream, "UPDATE OR REPLACE", table); 890 return *this; 891 } 892 893 StatementBuilder& StatementBuilder::UpdateOrReplace(std::initializer_list<std::string_view> table) 894 { 895 OutputOperationAndTable(m_stream, "UPDATE OR REPLACE", table); 896 return *this; 897 } 898 899 StatementBuilder& StatementBuilder::Set() 900 { 901 m_stream << " SET "; 902 m_needsComma = false; 903 return *this; 904 } 905 906 StatementBuilder& StatementBuilder::Vacuum() 907 { 908 m_stream << "VACUUM"; 909 return *this; 910 } 911 912 StatementBuilder& StatementBuilder::BeginParenthetical() 913 { 914 m_stream << '('; 915 return *this; 916 } 917 918 StatementBuilder& StatementBuilder::EndParenthetical() 919 { 920 m_stream << ')'; 921 return *this; 922 } 923 924 StatementBuilder& StatementBuilder::WithoutRowID() 925 { 926 m_stream << " WITHOUT ROWID"; 927 return *this; 928 } 929 930 931 StatementBuilder& StatementBuilder::As(std::string_view alias) 932 { 933 OutputOperationAndTable(m_stream, " AS", alias); 934 return *this; 935 } 936 937 Statement StatementBuilder::Prepare(const Connection& connection) 938 { 939 Statement result = Statement::Create(connection, m_stream.str()); 940 for (const auto& f : m_binders) 941 { 942 f(result); 943 } 944 return result; 945 } 946 947 void StatementBuilder::Execute(const Connection& connection) 948 { 949 Prepare(connection).Execute(); 950 } 951 952 int StatementBuilder::AppendOpAndBinder(Op op, std::optional<size_t> index) 953 { 954 switch (op) 955 { 956 case Op::Equals: 957 m_stream << " = ?"; 958 break; 959 case Op::Like: 960 m_stream << " LIKE ?"; 961 break; 962 case Op::Escape: 963 m_stream << " ESCAPE ?"; 964 break; 965 case Op::Literal: 966 m_stream << " ?"; 967 break; 968 case Op::GreaterThan: 969 m_stream << " > ?"; 970 break; 971 case Op::GreaterThanOrEqualTo: 972 m_stream << " >= ?"; 973 break; 974 default: 975 THROW_HR(E_UNEXPECTED); 976 } 977 978 if (index) 979 { 980 m_stream << index.value(); 981 } 982 983 return m_bindIndex++; 984 } 985 986 int StatementBuilder::AppendValuesAndBinders(size_t count) 987 { 988 m_stream << " VALUES ("; 989 for (size_t i = 0; i < count; ++i) 990 { 991 m_stream << (i == 0 ? "?" : ", ?"); 992 } 993 m_stream << ')'; 994 995 int result = m_bindIndex; 996 m_bindIndex += static_cast<int>(count); 997 return result; 998 } 999 1000 int StatementBuilder::AppendValueAndBinder() 1001 { 1002 if (m_needsComma) 1003 { 1004 m_stream << ", "; 1005 } 1006 m_stream << '?'; 1007 m_needsComma = true; 1008 return m_bindIndex++; 1009 } 1010 }