From 36adab70c50cb23562458ffdf155b093cc3112e4 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 02:01:00 +0100 Subject: [PATCH 01/12] add 10 tpch style queries and test for them --- Makefile | 2 +- src/parser/bison_parser.cpp | 1104 ++++++++++++++++++----------------- src/sql/statements.cpp | 2 +- test/queries/tpc-h-01.sql | 9 + test/queries/tpc-h-02.sql | 10 + test/queries/tpc-h-03.sql | 7 + test/queries/tpc-h-04.sql | 6 + test/queries/tpc-h-05.sql | 9 + test/queries/tpc-h-06.sql | 5 + test/queries/tpc-h-07.sql | 11 + test/queries/tpc-h-08.sql | 10 + test/queries/tpc-h-09.sql | 10 + test/queries/tpc-h-10.sql | 9 + test/select_tests.cpp | 2 +- test/sql_grammar_test.cpp | 148 ++--- test/sql_tests.cpp | 217 +++---- test/tpc_h_tests.cpp | 43 ++ 17 files changed, 875 insertions(+), 729 deletions(-) create mode 100644 test/queries/tpc-h-01.sql create mode 100644 test/queries/tpc-h-02.sql create mode 100644 test/queries/tpc-h-03.sql create mode 100644 test/queries/tpc-h-04.sql create mode 100644 test/queries/tpc-h-05.sql create mode 100644 test/queries/tpc-h-06.sql create mode 100644 test/queries/tpc-h-07.sql create mode 100644 test/queries/tpc-h-08.sql create mode 100644 test/queries/tpc-h-09.sql create mode 100644 test/queries/tpc-h-10.sql create mode 100644 test/tpc_h_tests.cpp diff --git a/Makefile b/Makefile index 17212a6..3ab260f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ LIBOBJ = $(LIBCPP:%.cpp=%.o) TESTCPP = $(shell find test/ -name '*.cpp') ALLLIB = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(shell find $(SRC) -name '*.h' -not -path "$(SRCPARSER)/*") -ALLTEST = $(shell find test/lib/ -name '*.cpp') $(shell find test/lib/ -name '*.h') +ALLTEST = $(shell find test/ -name '*.cpp') $(shell find test/ -name '*.h') # compile & link flages CFLAGS = -std=c++11 -Wall -fPIC -g diff --git a/src/parser/bison_parser.cpp b/src/parser/bison_parser.cpp index 761c388..e2653d2 100644 --- a/src/parser/bison_parser.cpp +++ b/src/parser/bison_parser.cpp @@ -614,16 +614,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 46 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 449 +#define YYLAST 452 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 146 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 67 /* YYNRULES -- Number of rules. */ -#define YYNRULES 145 +#define YYNRULES 146 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 257 +#define YYNSTATES 261 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ @@ -687,16 +687,16 @@ static const yytype_uint16 yyrline[] = 310, 318, 322, 332, 338, 347, 348, 352, 353, 357, 364, 365, 366, 367, 377, 381, 393, 401, 413, 419, 429, 430, 440, 449, 450, 454, 466, 467, 471, 472, - 476, 481, 493, 494, 495, 499, 510, 511, 515, 520, - 525, 526, 530, 535, 539, 540, 543, 544, 548, 549, - 550, 555, 556, 557, 564, 565, 569, 570, 574, 581, - 582, 583, 584, 585, 589, 590, 591, 595, 596, 600, - 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, - 615, 616, 617, 618, 619, 620, 624, 628, 629, 633, - 634, 635, 639, 644, 645, 649, 653, 658, 669, 670, - 680, 681, 687, 692, 693, 698, 708, 716, 717, 722, - 723, 727, 728, 736, 748, 749, 750, 751, 752, 758, - 764, 768, 777, 778, 783, 784 + 476, 481, 490, 499, 500, 501, 505, 516, 517, 521, + 526, 531, 532, 536, 541, 545, 546, 549, 550, 554, + 555, 556, 561, 562, 563, 570, 571, 575, 576, 580, + 587, 588, 589, 590, 591, 595, 596, 597, 601, 602, + 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, + 616, 621, 622, 623, 624, 625, 626, 630, 634, 635, + 639, 640, 641, 645, 650, 651, 655, 659, 664, 675, + 676, 686, 687, 693, 698, 699, 704, 714, 722, 723, + 728, 729, 733, 734, 742, 754, 755, 756, 757, 758, + 764, 770, 774, 783, 784, 789, 790 }; #endif @@ -767,46 +767,47 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -209 +#define YYPACT_NINF -213 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-209))) + (!!((Yystate) == (-213))) -#define YYTABLE_NINF -141 +#define YYTABLE_NINF -142 #define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-141))) + (!!((Yytable_value) == (-142))) /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { - 212, 0, 32, 35, 72, -26, -3, -1, -6, 68, - 32, 25, -34, 99, -36, -209, -209, -209, -209, -209, - -209, -209, -209, -209, -209, -209, -209, -209, -209, 80, - 102, -33, -209, -30, -99, 10, 32, 16, 32, -209, - 8, 14, -209, 32, -24, -13, -209, 212, -209, -209, - -209, 13, -209, 60, 62, -209, 126, 11, 64, 212, - 27, 32, 67, -209, 55, 18, -66, -209, -209, -209, - 8, 8, -209, 8, -209, 65, 2, -209, 124, -209, - -209, -209, -209, -209, -209, -209, -209, -209, -209, -209, - -209, 148, -209, -209, -209, -209, 8, 87, 152, -209, - -209, -112, -209, -209, -36, 116, -59, 8, -209, 159, - 163, -25, 68, 172, 280, -45, 41, 3, 67, 8, - -209, 8, 8, 8, 8, 8, 89, 173, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, -209, -209, - 73, -54, -209, 183, 62, 136, -209, 11, 45, -209, - 83, 193, 231, 111, -209, -209, -107, 61, -209, 8, - -209, -209, -34, -209, 66, 96, 6, -209, 5, 141, - -209, 316, 252, 252, 316, 280, 8, -209, 267, 316, - 252, 252, -45, -45, 75, 75, 75, -209, 11, 148, - -209, -209, -209, -209, -209, 152, -209, -209, 118, 44, - -98, -209, 32, -209, 202, 11, 88, 76, 3, -209, - -209, -209, -209, -209, 119, 110, -209, 316, -209, -209, - -209, 159, -209, -209, -209, -209, -209, -209, 193, -209, - -209, -93, -209, 6, -209, 71, 4, 8, -209, -209, - -209, 115, 3, -34, -209, 106, -35, -209, 90, 8, - 8, -209, 6, 231, -209, 231, -209 + 225, 3, 32, 42, 47, 18, -11, -6, 20, 88, + 32, 41, -35, 113, -20, -213, -213, -213, -213, -213, + -213, -213, -213, -213, -213, -213, -213, -213, -213, 30, + 120, -14, -213, -10, -63, 25, 32, 28, 32, -213, + 8, 31, -213, 32, 4, 14, -213, 225, -213, -213, + -213, 37, -213, -35, 89, -213, 153, 1, 241, 225, + 50, 32, 82, -213, 79, 29, -107, -213, -213, -213, + 8, 8, -213, 8, -213, 80, 23, -213, 109, -213, + -213, -213, -213, -213, -213, -213, -213, -213, -213, -213, + -213, 171, -213, -213, -213, -213, 8, 105, 105, 170, + -213, -213, -101, -213, -213, -20, 136, -60, 8, -213, + 176, 178, -12, 88, 179, 306, -43, 40, 6, 82, + 8, -213, 8, 8, 8, 8, 8, 97, 184, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, -213, + -213, 67, -51, -213, 210, 89, 89, 140, -213, 1, + 48, -213, 83, 187, 260, 106, -213, -213, -86, 57, + -213, 8, -213, -213, -35, -213, 52, 10, 12, -213, + 63, 138, -213, 319, 240, 240, 319, 306, 8, -213, + 293, 319, 240, 240, -43, -43, 69, 69, 69, -213, + 1, 171, -213, -213, -213, -213, -213, -213, 170, -213, + -213, 130, -9, -64, -213, 32, -213, 209, 1, 76, + 75, 6, -213, -213, -213, -213, -213, 128, 107, -213, + 319, -213, -213, -213, 176, -213, -213, -213, -213, -213, + -213, 187, -213, -213, -39, -213, 12, -213, 78, 7, + 8, -213, -213, -213, 61, -213, 6, -35, -213, 108, + -25, -213, 85, 8, 8, -213, 12, 260, -213, 260, + -213 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -814,56 +815,57 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, - 0, 0, 0, 0, 143, 3, 6, 5, 15, 8, - 9, 14, 11, 12, 10, 13, 7, 46, 47, 67, - 0, 127, 37, 18, 0, 26, 0, 0, 0, 56, - 0, 0, 126, 0, 0, 0, 1, 142, 2, 53, - 54, 0, 52, 0, 73, 35, 0, 0, 0, 0, - 0, 0, 61, 21, 0, 41, 107, 112, 113, 115, - 0, 0, 116, 0, 117, 0, 58, 74, 132, 80, - 81, 82, 89, 83, 84, 86, 109, 110, 114, 85, - 111, 0, 34, 49, 48, 4, 0, 67, 0, 50, - 128, 0, 76, 16, 143, 0, 0, 0, 36, 0, - 0, 0, 57, 0, 88, 87, 0, 0, 61, 0, - 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 131, 78, - 0, 61, 43, 70, 73, 71, 19, 0, 0, 25, - 0, 0, 60, 0, 22, 144, 0, 0, 39, 0, - 108, 79, 0, 59, 118, 120, 132, 122, 138, 63, - 75, 101, 104, 105, 98, 96, 0, 129, 97, 100, - 102, 103, 91, 90, 93, 92, 94, 95, 0, 0, - 42, 69, 68, 66, 51, 0, 77, 17, 0, 0, - 0, 27, 0, 40, 0, 0, 0, 0, 0, 125, - 134, 135, 137, 136, 0, 0, 55, 99, 45, 44, - 72, 0, 31, 32, 33, 30, 29, 24, 0, 20, - 145, 0, 106, 0, 123, 119, 0, 0, 23, 28, - 38, 121, 0, 0, 140, 0, 65, 124, 0, 0, - 0, 62, 0, 141, 133, 64, 139 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, + 0, 0, 0, 0, 144, 3, 6, 5, 15, 8, + 9, 14, 11, 12, 10, 13, 7, 46, 47, 68, + 0, 128, 37, 18, 0, 26, 0, 0, 0, 57, + 0, 0, 127, 0, 0, 0, 1, 143, 2, 54, + 55, 0, 53, 0, 74, 35, 0, 0, 0, 0, + 0, 0, 62, 21, 0, 41, 108, 113, 114, 116, + 0, 0, 117, 0, 118, 0, 59, 75, 133, 81, + 82, 83, 90, 84, 85, 87, 110, 111, 115, 86, + 112, 0, 34, 49, 48, 4, 0, 68, 68, 0, + 50, 129, 0, 77, 16, 144, 0, 0, 0, 36, + 0, 0, 0, 58, 0, 89, 88, 0, 0, 62, + 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, + 79, 0, 62, 43, 71, 74, 74, 72, 19, 0, + 0, 25, 0, 0, 61, 0, 22, 145, 0, 0, + 39, 0, 109, 80, 0, 60, 119, 121, 133, 123, + 139, 64, 76, 102, 105, 106, 99, 97, 0, 130, + 98, 101, 103, 104, 92, 91, 94, 93, 95, 96, + 0, 0, 42, 70, 69, 67, 52, 51, 0, 78, + 17, 0, 0, 0, 27, 0, 40, 0, 0, 0, + 0, 0, 126, 135, 136, 138, 137, 0, 0, 56, + 100, 45, 44, 73, 0, 31, 32, 33, 30, 29, + 24, 0, 20, 146, 0, 107, 133, 124, 120, 0, + 0, 23, 28, 38, 132, 122, 0, 0, 141, 0, + 66, 125, 0, 0, 0, 63, 0, 142, 134, 65, + 140 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -209, -209, 168, 182, 174, -209, -209, -209, -209, 12, - -209, -209, -209, 7, -209, -209, -209, -209, -209, -209, - -209, -209, 52, -143, 222, 9, -209, 191, 134, -209, - -209, -89, -209, -209, 154, -209, 121, 26, 63, 147, - -68, -209, -209, -209, -209, -209, -209, -53, -108, -209, - -78, -209, -209, -209, -184, -209, 31, -209, -2, -208, - 104, -209, -209, 37, -209, 167, -209 + -213, -213, 165, 180, 167, -213, -213, -213, -213, 5, + -213, -213, -213, 0, -213, -213, -213, -213, -213, -213, + -213, -213, 43, -146, 17, 9, -213, 183, 131, -213, + -213, -91, -213, -213, 13, -213, -38, 16, 38, 125, + -69, -213, -213, -213, -213, -213, -213, -54, -94, -213, + -76, -213, -213, -213, -173, -213, 15, -213, -2, -212, + -142, -213, -213, 19, -213, 142, -213 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 13, 14, 15, 16, 17, 18, 19, 64, 153, - 20, 61, 200, 201, 226, 21, 22, 23, 24, 111, - 25, 141, 142, 26, 27, 28, 53, 29, 40, 75, - 118, 108, 216, 251, 54, 193, 99, 76, 101, 77, + -1, 13, 14, 15, 16, 17, 18, 19, 64, 155, + 20, 61, 203, 204, 229, 21, 22, 23, 24, 112, + 25, 142, 143, 26, 27, 28, 53, 29, 40, 75, + 119, 109, 219, 255, 54, 195, 100, 76, 102, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 163, 164, 235, 165, 41, 166, 138, - 139, 167, 214, 168, 254, 48, 156 + 88, 89, 90, 165, 166, 238, 167, 41, 168, 139, + 140, 169, 217, 170, 258, 48, 158 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -871,100 +873,102 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 32, 154, 114, 115, 102, 116, 31, 31, 42, 120, - 250, 66, 67, 68, 69, 67, 68, 69, 9, 207, - 145, 45, 107, 150, 234, 241, 146, 9, 143, 169, - 30, 203, 147, 157, 62, 31, 65, 204, 33, 152, - 227, 92, 58, 59, 256, 240, 228, 35, 121, 122, - 123, 147, 190, 171, 172, 173, 174, 175, 247, 106, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 210, 112, 222, 113, 1, 34, 211, 212, 151, 36, - 38, 37, 2, 39, 223, 134, 135, 136, 137, 3, - 189, 206, 49, 213, 196, 121, 122, 123, 43, 46, - 248, 5, 6, 12, 47, 55, 56, 57, 217, 119, - 7, 8, 9, 154, 93, 70, 9, 220, 127, 63, - 158, 10, 50, 91, 60, 94, 96, 120, 98, 100, - 124, 121, 122, 123, 105, 218, 109, 71, 72, 224, - 162, 243, 125, 107, 11, 73, 119, 117, 126, 225, - 51, 140, 102, 74, 52, 110, 74, 51, 69, 149, - 128, -140, 129, 67, 130, 131, 155, -140, -140, 132, - 133, 134, 135, 136, 137, 160, 177, 124, 176, 161, - -139, 253, 255, -140, -140, 195, -139, -139, 197, 125, - 121, 122, 123, 198, 188, 126, 199, 202, 205, 221, - 229, 12, -139, -139, 215, 230, 236, 128, 137, 129, - 208, 130, 131, 124, 233, 242, 132, 133, 134, 135, - 136, 137, 1, 237, 249, 125, 232, 104, 252, 95, - 2, 126, 103, 238, 44, 239, 127, 3, 121, 122, - 123, 219, 4, 128, 97, 129, 159, 130, 131, 5, - 6, 144, 132, 133, 134, 135, 136, 137, 7, 8, - -141, -141, 191, 246, 9, 194, 170, 244, 231, 10, - 209, 148, 124, 245, 121, 122, 123, 0, 0, 0, - 0, 0, 0, 0, 125, 192, 0, 121, 122, 123, - 126, 0, 11, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 128, 0, 129, 0, 130, 131, 0, 0, - 0, 132, 133, 134, 135, 136, 137, 0, 0, 0, - 124, 0, 0, 121, 122, 123, 0, 0, 0, 0, - 0, 0, 125, 0, 0, 0, 0, 0, 126, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, - 128, 0, 129, 0, 130, 131, 124, 0, 0, 132, - 133, 134, 135, 136, 137, 0, 0, 0, 125, 124, - 0, 0, 0, 0, 126, -141, -141, 0, 0, 0, - 132, 133, 134, 135, 136, 137, 0, 126, 129, 0, - 130, 131, 0, 0, 0, 132, 133, 134, 135, 136, - 137, 129, 0, 130, 131, 124, 0, 0, 132, 133, - 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, + 32, 115, 116, 103, 117, 67, 68, 69, 42, 31, + 31, 66, 67, 68, 69, 121, 156, 9, 210, 225, + 254, 45, 152, 147, 244, 108, 212, 144, 171, 44, + 113, 226, 114, 30, 62, 31, 65, 148, 237, 154, + 9, 92, 49, 149, 260, 33, 159, 122, 123, 124, + 34, 192, 206, 173, 174, 175, 176, 177, 207, 107, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 97, 36, 50, 251, 230, -141, 37, 153, 58, 59, + 231, -141, -141, 122, 123, 124, 227, 135, 136, 137, + 138, 35, 209, 191, 245, 199, 228, -141, -141, 243, + 51, 252, 12, 39, 52, 149, 38, 196, 197, 220, + 145, 146, 121, 46, 43, 70, 122, 123, 124, 120, + 47, 160, 223, 55, 128, 56, -140, 57, 213, 125, + 156, 63, -140, -140, 214, 215, 221, 71, 72, 60, + 91, 126, 93, 164, 247, 73, 74, 127, -140, -140, + 96, 216, 94, 74, 103, 99, 101, 106, 108, 129, + 110, 130, 118, 131, 132, 125, 111, 120, 133, 134, + 135, 136, 137, 138, 141, 51, 69, 126, 163, 151, + 67, 157, 162, 127, 257, 259, 178, 179, 190, 198, + 202, 200, 205, 201, 208, 129, 211, 130, 125, 131, + 132, 218, 138, 232, 133, 134, 135, 136, 137, 138, + 126, 224, 233, 236, 235, 239, 127, 122, 123, 124, + 240, 128, 246, 256, 105, 104, 253, 95, 129, 241, + 130, 242, 131, 132, 222, 1, 98, 133, 134, 135, + 136, 137, 138, 2, 161, 172, 234, 150, -142, -142, + 3, 1, 0, 0, 248, 4, 250, 0, 249, 2, + 0, 0, 5, 6, 0, 0, 3, 122, 123, 124, + 0, 7, 8, 0, 0, 0, 0, 9, 5, 6, + 0, 0, 10, 0, 0, 0, 0, 7, 8, 193, + 0, 0, 0, 9, 0, 0, 0, 0, 10, 125, + 122, 123, 124, 0, 0, 11, 0, 0, 0, 0, + 0, 126, 194, 122, 123, 124, 0, 127, 0, 0, + 0, 11, 0, 0, 0, 0, 122, 123, 124, 129, + 0, 130, 0, 131, 132, 0, 0, 0, 133, 134, + 135, 136, 137, 138, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 129, 0, 130, - 131, 0, 0, 0, 132, 133, 134, 135, 136, 137 + 0, 126, 12, -142, -142, 0, 0, 127, 133, 134, + 135, 136, 137, 138, 0, 0, 0, 0, 12, 129, + 0, 130, 125, 131, 132, 0, 0, 0, 133, 134, + 135, 136, 137, 138, 126, 125, 0, 0, 0, 0, + 127, 0, 0, 0, 0, 0, 0, 0, 125, 0, + 0, 0, 0, 127, 130, 0, 131, 132, 0, 0, + 0, 133, 134, 135, 136, 137, 138, 130, 0, 131, + 132, 0, 0, 0, 133, 134, 135, 136, 137, 138, + 130, 0, 131, 132, 0, 0, 0, 133, 134, 135, + 136, 137, 138 }; static const yytype_int16 yycheck[] = { - 2, 109, 70, 71, 57, 73, 3, 3, 10, 3, - 45, 3, 4, 5, 6, 4, 5, 6, 52, 162, - 98, 12, 76, 82, 208, 233, 138, 52, 96, 118, - 30, 138, 144, 58, 36, 3, 38, 144, 3, 107, - 138, 43, 141, 142, 252, 138, 144, 73, 7, 8, - 9, 144, 141, 121, 122, 123, 124, 125, 242, 61, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 65, 137, 28, 139, 10, 3, 71, 72, 137, 82, - 86, 82, 18, 15, 40, 130, 131, 132, 133, 25, - 144, 159, 12, 88, 147, 7, 8, 9, 73, 0, - 243, 37, 38, 137, 140, 3, 139, 137, 176, 144, - 46, 47, 52, 221, 138, 107, 52, 195, 112, 103, - 111, 57, 42, 109, 114, 138, 113, 3, 66, 3, - 89, 7, 8, 9, 107, 188, 81, 129, 130, 95, - 137, 137, 101, 76, 80, 137, 144, 82, 107, 105, - 70, 3, 205, 145, 74, 137, 145, 70, 6, 43, - 119, 65, 121, 4, 123, 124, 3, 71, 72, 128, - 129, 130, 131, 132, 133, 3, 3, 89, 89, 138, - 65, 249, 250, 87, 88, 49, 71, 72, 143, 101, - 7, 8, 9, 110, 121, 107, 3, 86, 137, 81, - 202, 137, 87, 88, 63, 3, 87, 119, 133, 121, - 144, 123, 124, 89, 138, 144, 128, 129, 130, 131, - 132, 133, 10, 113, 118, 101, 138, 59, 138, 47, - 18, 107, 58, 221, 12, 228, 112, 25, 7, 8, - 9, 189, 30, 119, 53, 121, 112, 123, 124, 37, - 38, 97, 128, 129, 130, 131, 132, 133, 46, 47, - 8, 9, 79, 237, 52, 144, 119, 236, 205, 57, - 166, 104, 89, 236, 7, 8, 9, -1, -1, -1, - -1, -1, -1, -1, 101, 102, -1, 7, 8, 9, - 107, -1, 80, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 119, -1, 121, -1, 123, 124, -1, -1, - -1, 128, 129, 130, 131, 132, 133, -1, -1, -1, - 89, -1, -1, 7, 8, 9, -1, -1, -1, -1, - -1, -1, 101, -1, -1, -1, -1, -1, 107, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 137, - 119, -1, 121, -1, 123, 124, 89, -1, -1, 128, - 129, 130, 131, 132, 133, -1, -1, -1, 101, 89, - -1, -1, -1, -1, 107, 123, 124, -1, -1, -1, - 128, 129, 130, 131, 132, 133, -1, 107, 121, -1, - 123, 124, -1, -1, -1, 128, 129, 130, 131, 132, - 133, 121, -1, 123, 124, 89, -1, -1, 128, 129, - 130, 131, 132, 133, -1, -1, -1, -1, -1, -1, + 2, 70, 71, 57, 73, 4, 5, 6, 10, 3, + 3, 3, 4, 5, 6, 3, 110, 52, 164, 28, + 45, 12, 82, 99, 236, 76, 168, 96, 119, 12, + 137, 40, 139, 30, 36, 3, 38, 138, 211, 108, + 52, 43, 12, 144, 256, 3, 58, 7, 8, 9, + 3, 142, 138, 122, 123, 124, 125, 126, 144, 61, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 53, 82, 42, 246, 138, 65, 82, 137, 141, 142, + 144, 71, 72, 7, 8, 9, 95, 130, 131, 132, + 133, 73, 161, 144, 236, 149, 105, 87, 88, 138, + 70, 247, 137, 15, 74, 144, 86, 145, 146, 178, + 97, 98, 3, 0, 73, 107, 7, 8, 9, 144, + 140, 112, 198, 3, 112, 139, 65, 137, 65, 89, + 224, 103, 71, 72, 71, 72, 190, 129, 130, 114, + 109, 101, 138, 137, 137, 137, 145, 107, 87, 88, + 113, 88, 138, 145, 208, 66, 3, 107, 76, 119, + 81, 121, 82, 123, 124, 89, 137, 144, 128, 129, + 130, 131, 132, 133, 3, 70, 6, 101, 138, 43, + 4, 3, 3, 107, 253, 254, 89, 3, 121, 49, + 3, 143, 86, 110, 137, 119, 144, 121, 89, 123, + 124, 63, 133, 205, 128, 129, 130, 131, 132, 133, + 101, 81, 3, 138, 138, 87, 107, 7, 8, 9, + 113, 112, 144, 138, 59, 58, 118, 47, 119, 224, + 121, 231, 123, 124, 191, 10, 53, 128, 129, 130, + 131, 132, 133, 18, 113, 120, 208, 105, 8, 9, + 25, 10, -1, -1, 239, 30, 240, -1, 239, 18, + -1, -1, 37, 38, -1, -1, 25, 7, 8, 9, + -1, 46, 47, -1, -1, -1, -1, 52, 37, 38, + -1, -1, 57, -1, -1, -1, -1, 46, 47, 79, + -1, -1, -1, 52, -1, -1, -1, -1, 57, 89, + 7, 8, 9, -1, -1, 80, -1, -1, -1, -1, + -1, 101, 102, 7, 8, 9, -1, 107, -1, -1, + -1, 80, -1, -1, -1, -1, 7, 8, 9, 119, + -1, 121, -1, 123, 124, -1, -1, -1, 128, 129, + 130, 131, 132, 133, -1, -1, -1, -1, -1, 89, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 121, -1, 123, - 124, -1, -1, -1, 128, 129, 130, 131, 132, 133 + -1, 101, 137, 123, 124, -1, -1, 107, 128, 129, + 130, 131, 132, 133, -1, -1, -1, -1, 137, 119, + -1, 121, 89, 123, 124, -1, -1, -1, 128, 129, + 130, 131, 132, 133, 101, 89, -1, -1, -1, -1, + 107, -1, -1, -1, -1, -1, -1, -1, 89, -1, + -1, -1, -1, 107, 121, -1, 123, 124, -1, -1, + -1, 128, 129, 130, 131, 132, 133, 121, -1, 123, + 124, -1, -1, -1, 128, 129, 130, 131, 132, 133, + 121, -1, 123, 124, -1, -1, -1, 128, 129, 130, + 131, 132, 133 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -980,23 +984,24 @@ static const yytype_uint8 yystos[] = 114, 157, 204, 103, 154, 204, 3, 4, 5, 6, 107, 129, 130, 137, 145, 175, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 109, 204, 138, 138, 149, 113, 173, 66, 182, - 3, 184, 193, 150, 148, 107, 204, 76, 177, 81, - 137, 165, 137, 139, 186, 186, 186, 82, 176, 144, - 3, 7, 8, 9, 89, 101, 107, 112, 119, 121, - 123, 124, 128, 129, 130, 131, 132, 133, 205, 206, - 3, 167, 168, 186, 180, 196, 138, 144, 211, 43, - 82, 137, 186, 155, 194, 3, 212, 58, 171, 174, - 3, 138, 137, 199, 200, 202, 204, 207, 209, 177, - 185, 186, 186, 186, 186, 186, 89, 3, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 121, 144, - 177, 79, 102, 181, 182, 49, 193, 143, 110, 3, - 158, 159, 86, 138, 144, 137, 186, 169, 144, 206, - 65, 71, 72, 88, 208, 63, 178, 186, 193, 168, - 196, 81, 28, 40, 95, 105, 160, 138, 144, 204, - 3, 184, 138, 138, 200, 201, 87, 113, 155, 159, - 138, 205, 144, 137, 202, 209, 183, 200, 169, 118, - 45, 179, 138, 186, 210, 186, 205 + 198, 109, 204, 138, 138, 149, 113, 170, 173, 66, + 182, 3, 184, 193, 150, 148, 107, 204, 76, 177, + 81, 137, 165, 137, 139, 186, 186, 186, 82, 176, + 144, 3, 7, 8, 9, 89, 101, 107, 112, 119, + 121, 123, 124, 128, 129, 130, 131, 132, 133, 205, + 206, 3, 167, 168, 186, 180, 180, 196, 138, 144, + 211, 43, 82, 137, 186, 155, 194, 3, 212, 58, + 171, 174, 3, 138, 137, 199, 200, 202, 204, 207, + 209, 177, 185, 186, 186, 186, 186, 186, 89, 3, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 121, 144, 177, 79, 102, 181, 182, 182, 49, 193, + 143, 110, 3, 158, 159, 86, 138, 144, 137, 186, + 169, 144, 206, 65, 71, 72, 88, 208, 63, 178, + 186, 193, 168, 196, 81, 28, 40, 95, 105, 160, + 138, 144, 204, 3, 184, 138, 138, 200, 201, 87, + 113, 155, 159, 138, 205, 206, 144, 137, 202, 209, + 183, 200, 169, 118, 45, 179, 138, 186, 210, 186, + 205 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -1007,16 +1012,16 @@ static const yytype_uint8 yyr1[] = 153, 154, 155, 156, 156, 157, 157, 158, 158, 159, 160, 160, 160, 160, 161, 161, 162, 163, 164, 164, 165, 165, 166, 167, 167, 168, 169, 169, 170, 170, - 171, 171, 172, 172, 172, 173, 174, 174, 175, 176, - 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, - 181, 182, 182, 182, 183, 183, 184, 184, 185, 186, - 186, 186, 186, 186, 187, 187, 187, 188, 188, 189, + 171, 171, 171, 172, 172, 172, 173, 174, 174, 175, + 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, + 181, 181, 182, 182, 182, 183, 183, 184, 184, 185, + 186, 186, 186, 186, 186, 187, 187, 187, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 190, 190, 190, 190, 190, 190, 191, 192, 192, 193, - 193, 193, 194, 195, 195, 196, 197, 198, 199, 199, - 200, 200, 200, 201, 201, 202, 203, 204, 204, 205, - 205, 206, 206, 207, 208, 208, 208, 208, 208, 209, - 209, 210, 211, 211, 212, 212 + 189, 190, 190, 190, 190, 190, 190, 191, 192, 192, + 193, 193, 193, 194, 195, 195, 196, 197, 198, 199, + 199, 200, 200, 200, 201, 201, 202, 203, 204, 204, + 205, 205, 206, 206, 207, 208, 208, 208, 208, 208, + 209, 209, 210, 211, 211, 212, 212 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -1027,16 +1032,16 @@ static const yytype_uint8 yyr2[] = 7, 1, 1, 8, 7, 3, 0, 1, 3, 2, 1, 1, 1, 1, 3, 3, 4, 2, 8, 5, 3, 0, 5, 1, 3, 3, 1, 1, 3, 3, - 3, 5, 1, 1, 1, 6, 1, 0, 1, 2, - 2, 0, 4, 0, 2, 0, 4, 0, 1, 1, - 0, 2, 4, 0, 1, 3, 1, 3, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, - 3, 3, 3, 3, 3, 3, 5, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 1, 4, 1, 1, 3, 2, 1, 1, 3, 2, - 1, 1, 0, 6, 1, 1, 1, 1, 0, 4, - 1, 1, 1, 0, 1, 3 + 3, 5, 5, 1, 1, 1, 6, 1, 0, 1, + 2, 2, 0, 4, 0, 2, 0, 4, 0, 1, + 1, 0, 2, 4, 0, 1, 3, 1, 3, 2, + 3, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 3, 3, 3, 3, 3, 3, 5, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 4, 1, 1, 3, 2, 1, 1, 3, + 2, 1, 1, 0, 6, 1, 1, 1, 1, 0, + 4, 1, 1, 1, 0, 1, 3 }; @@ -1535,103 +1540,103 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio case 3: /* IDENTIFIER */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1539 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1544 "bison_parser.cpp" /* yacc.c:1257 */ break; case 4: /* STRING */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1545 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1550 "bison_parser.cpp" /* yacc.c:1257 */ break; case 5: /* FLOATVAL */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1551 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1556 "bison_parser.cpp" /* yacc.c:1257 */ break; case 6: /* INTVAL */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1557 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1562 "bison_parser.cpp" /* yacc.c:1257 */ break; case 7: /* NOTEQUALS */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1563 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1568 "bison_parser.cpp" /* yacc.c:1257 */ break; case 8: /* LESSEQ */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1569 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1574 "bison_parser.cpp" /* yacc.c:1257 */ break; case 9: /* GREATEREQ */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1575 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1580 "bison_parser.cpp" /* yacc.c:1257 */ break; case 148: /* statement_list */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).stmt_list)); } -#line 1581 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1586 "bison_parser.cpp" /* yacc.c:1257 */ break; case 149: /* statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).statement)); } -#line 1587 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1592 "bison_parser.cpp" /* yacc.c:1257 */ break; case 150: /* preparable_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).statement)); } -#line 1593 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1598 "bison_parser.cpp" /* yacc.c:1257 */ break; case 151: /* prepare_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).prep_stmt)); } -#line 1599 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1604 "bison_parser.cpp" /* yacc.c:1257 */ break; case 152: /* execute_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).exec_stmt)); } -#line 1605 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1610 "bison_parser.cpp" /* yacc.c:1257 */ break; case 153: /* import_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).import_stmt)); } -#line 1611 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1616 "bison_parser.cpp" /* yacc.c:1257 */ break; case 154: /* import_file_type */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1617 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1622 "bison_parser.cpp" /* yacc.c:1257 */ break; case 155: /* file_path */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1623 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1628 "bison_parser.cpp" /* yacc.c:1257 */ break; case 156: /* create_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).create_stmt)); } -#line 1629 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1634 "bison_parser.cpp" /* yacc.c:1257 */ break; case 157: /* opt_not_exists */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1635 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1640 "bison_parser.cpp" /* yacc.c:1257 */ break; case 158: /* column_def_commalist */ @@ -1644,43 +1649,43 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).column_vec)); } -#line 1648 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1653 "bison_parser.cpp" /* yacc.c:1257 */ break; case 159: /* column_def */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).column_t)); } -#line 1654 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1659 "bison_parser.cpp" /* yacc.c:1257 */ break; case 160: /* column_type */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1660 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1665 "bison_parser.cpp" /* yacc.c:1257 */ break; case 161: /* drop_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).drop_stmt)); } -#line 1666 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1671 "bison_parser.cpp" /* yacc.c:1257 */ break; case 162: /* delete_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).delete_stmt)); } -#line 1672 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1677 "bison_parser.cpp" /* yacc.c:1257 */ break; case 163: /* truncate_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).delete_stmt)); } -#line 1678 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1683 "bison_parser.cpp" /* yacc.c:1257 */ break; case 164: /* insert_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).insert_stmt)); } -#line 1684 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1689 "bison_parser.cpp" /* yacc.c:1257 */ break; case 165: /* opt_column_list */ @@ -1693,13 +1698,13 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).str_vec)); } -#line 1697 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1702 "bison_parser.cpp" /* yacc.c:1257 */ break; case 166: /* update_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).update_stmt)); } -#line 1703 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1708 "bison_parser.cpp" /* yacc.c:1257 */ break; case 167: /* update_clause_commalist */ @@ -1712,43 +1717,43 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).update_vec)); } -#line 1716 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1721 "bison_parser.cpp" /* yacc.c:1257 */ break; case 168: /* update_clause */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).update_t)); } -#line 1722 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1727 "bison_parser.cpp" /* yacc.c:1257 */ break; case 169: /* select_statement */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).select_stmt)); } -#line 1728 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1733 "bison_parser.cpp" /* yacc.c:1257 */ break; case 170: /* select_with_paren */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).select_stmt)); } -#line 1734 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1739 "bison_parser.cpp" /* yacc.c:1257 */ break; case 171: /* select_no_paren */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).select_stmt)); } -#line 1740 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1745 "bison_parser.cpp" /* yacc.c:1257 */ break; case 173: /* select_clause */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).select_stmt)); } -#line 1746 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1751 "bison_parser.cpp" /* yacc.c:1257 */ break; case 174: /* opt_distinct */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1752 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1757 "bison_parser.cpp" /* yacc.c:1257 */ break; case 175: /* select_list */ @@ -1761,49 +1766,49 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).expr_vec)); } -#line 1765 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1770 "bison_parser.cpp" /* yacc.c:1257 */ break; case 176: /* from_clause */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1771 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1776 "bison_parser.cpp" /* yacc.c:1257 */ break; case 177: /* opt_where */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1777 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1782 "bison_parser.cpp" /* yacc.c:1257 */ break; case 178: /* opt_group */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).group_t)); } -#line 1783 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1788 "bison_parser.cpp" /* yacc.c:1257 */ break; case 179: /* opt_having */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1789 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1794 "bison_parser.cpp" /* yacc.c:1257 */ break; case 180: /* opt_order */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).order)); } -#line 1795 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1800 "bison_parser.cpp" /* yacc.c:1257 */ break; case 181: /* opt_order_type */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1801 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1806 "bison_parser.cpp" /* yacc.c:1257 */ break; case 182: /* opt_limit */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).limit)); } -#line 1807 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1812 "bison_parser.cpp" /* yacc.c:1257 */ break; case 183: /* expr_list */ @@ -1816,7 +1821,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).expr_vec)); } -#line 1820 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1825 "bison_parser.cpp" /* yacc.c:1257 */ break; case 184: /* literal_list */ @@ -1829,103 +1834,103 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).expr_vec)); } -#line 1833 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1838 "bison_parser.cpp" /* yacc.c:1257 */ break; case 185: /* expr_alias */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1839 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1844 "bison_parser.cpp" /* yacc.c:1257 */ break; case 186: /* expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1845 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1850 "bison_parser.cpp" /* yacc.c:1257 */ break; case 187: /* scalar_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1851 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1856 "bison_parser.cpp" /* yacc.c:1257 */ break; case 188: /* unary_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1857 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1862 "bison_parser.cpp" /* yacc.c:1257 */ break; case 189: /* binary_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1863 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1868 "bison_parser.cpp" /* yacc.c:1257 */ break; case 190: /* comp_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1869 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1874 "bison_parser.cpp" /* yacc.c:1257 */ break; case 191: /* function_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1875 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1880 "bison_parser.cpp" /* yacc.c:1257 */ break; case 192: /* column_name */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1881 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1886 "bison_parser.cpp" /* yacc.c:1257 */ break; case 193: /* literal */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1887 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1892 "bison_parser.cpp" /* yacc.c:1257 */ break; case 194: /* string_literal */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1893 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1898 "bison_parser.cpp" /* yacc.c:1257 */ break; case 195: /* num_literal */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1899 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1904 "bison_parser.cpp" /* yacc.c:1257 */ break; case 196: /* int_literal */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1905 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1910 "bison_parser.cpp" /* yacc.c:1257 */ break; case 197: /* star_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1911 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1916 "bison_parser.cpp" /* yacc.c:1257 */ break; case 198: /* placeholder_expr */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1917 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1922 "bison_parser.cpp" /* yacc.c:1257 */ break; case 199: /* table_ref */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1923 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1928 "bison_parser.cpp" /* yacc.c:1257 */ break; case 200: /* table_ref_atomic */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1929 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1934 "bison_parser.cpp" /* yacc.c:1257 */ break; case 201: /* table_ref_commalist */ @@ -1938,61 +1943,61 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).table_vec)); } -#line 1942 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1947 "bison_parser.cpp" /* yacc.c:1257 */ break; case 202: /* table_ref_name */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1948 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1953 "bison_parser.cpp" /* yacc.c:1257 */ break; case 203: /* table_ref_name_no_alias */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1954 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1959 "bison_parser.cpp" /* yacc.c:1257 */ break; case 204: /* table_name */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1960 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1965 "bison_parser.cpp" /* yacc.c:1257 */ break; case 205: /* alias */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1966 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1971 "bison_parser.cpp" /* yacc.c:1257 */ break; case 206: /* opt_alias */ #line 141 "bison_parser.y" /* yacc.c:1257 */ { free( (((*yyvaluep).sval)) ); } -#line 1972 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1977 "bison_parser.cpp" /* yacc.c:1257 */ break; case 207: /* join_clause */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1978 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1983 "bison_parser.cpp" /* yacc.c:1257 */ break; case 208: /* opt_join_type */ #line 140 "bison_parser.y" /* yacc.c:1257 */ { } -#line 1984 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1989 "bison_parser.cpp" /* yacc.c:1257 */ break; case 209: /* join_table */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).table)); } -#line 1990 "bison_parser.cpp" /* yacc.c:1257 */ +#line 1995 "bison_parser.cpp" /* yacc.c:1257 */ break; case 210: /* join_condition */ #line 150 "bison_parser.y" /* yacc.c:1257 */ { delete (((*yyvaluep).expr)); } -#line 1996 "bison_parser.cpp" /* yacc.c:1257 */ +#line 2001 "bison_parser.cpp" /* yacc.c:1257 */ break; case 212: /* ident_commalist */ @@ -2005,7 +2010,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio } delete (((*yyvaluep).str_vec)); } -#line 2009 "bison_parser.cpp" /* yacc.c:1257 */ +#line 2014 "bison_parser.cpp" /* yacc.c:1257 */ break; @@ -2124,7 +2129,7 @@ YYLTYPE yylloc = yyloc_default; yylloc.placeholder_id = 0; } -#line 2128 "bison_parser.cpp" /* yacc.c:1429 */ +#line 2133 "bison_parser.cpp" /* yacc.c:1429 */ yylsp[0] = yylloc; goto yysetstate; @@ -2315,19 +2320,19 @@ yyreduce: { *result = (yyvsp[-1].stmt_list); } -#line 2319 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2324 "bison_parser.cpp" /* yacc.c:1646 */ break; case 3: #line 250 "bison_parser.y" /* yacc.c:1646 */ { (yyval.stmt_list) = new SQLParserResult((yyvsp[0].statement)); } -#line 2325 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2330 "bison_parser.cpp" /* yacc.c:1646 */ break; case 4: #line 251 "bison_parser.y" /* yacc.c:1646 */ { (yyvsp[-2].stmt_list)->addStatement((yyvsp[0].statement)); (yyval.stmt_list) = (yyvsp[-2].stmt_list); } -#line 2331 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2336 "bison_parser.cpp" /* yacc.c:1646 */ break; case 5: @@ -2337,61 +2342,61 @@ yyreduce: yyloc.placeholder_list.clear(); (yyval.statement) = (yyvsp[0].prep_stmt); } -#line 2341 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2346 "bison_parser.cpp" /* yacc.c:1646 */ break; case 7: #line 265 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].select_stmt); } -#line 2347 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2352 "bison_parser.cpp" /* yacc.c:1646 */ break; case 8: #line 266 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].import_stmt); } -#line 2353 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2358 "bison_parser.cpp" /* yacc.c:1646 */ break; case 9: #line 267 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].create_stmt); } -#line 2359 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2364 "bison_parser.cpp" /* yacc.c:1646 */ break; case 10: #line 268 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].insert_stmt); } -#line 2365 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2370 "bison_parser.cpp" /* yacc.c:1646 */ break; case 11: #line 269 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].delete_stmt); } -#line 2371 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2376 "bison_parser.cpp" /* yacc.c:1646 */ break; case 12: #line 270 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].delete_stmt); } -#line 2377 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2382 "bison_parser.cpp" /* yacc.c:1646 */ break; case 13: #line 271 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].update_stmt); } -#line 2383 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2388 "bison_parser.cpp" /* yacc.c:1646 */ break; case 14: #line 272 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].drop_stmt); } -#line 2389 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2394 "bison_parser.cpp" /* yacc.c:1646 */ break; case 15: #line 273 "bison_parser.y" /* yacc.c:1646 */ { (yyval.statement) = (yyvsp[0].exec_stmt); } -#line 2395 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2400 "bison_parser.cpp" /* yacc.c:1646 */ break; case 16: @@ -2401,7 +2406,7 @@ yyreduce: (yyval.prep_stmt)->name = (yyvsp[-2].sval); (yyval.prep_stmt)->query = new SQLParserResult((yyvsp[0].statement)); } -#line 2405 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2410 "bison_parser.cpp" /* yacc.c:1646 */ break; case 17: @@ -2411,7 +2416,7 @@ yyreduce: (yyval.prep_stmt)->name = (yyvsp[-4].sval); (yyval.prep_stmt)->query = (yyvsp[-2].stmt_list); } -#line 2415 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2420 "bison_parser.cpp" /* yacc.c:1646 */ break; case 18: @@ -2420,7 +2425,7 @@ yyreduce: (yyval.exec_stmt) = new ExecuteStatement(); (yyval.exec_stmt)->name = (yyvsp[0].sval); } -#line 2424 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2429 "bison_parser.cpp" /* yacc.c:1646 */ break; case 19: @@ -2430,7 +2435,7 @@ yyreduce: (yyval.exec_stmt)->name = (yyvsp[-3].sval); (yyval.exec_stmt)->parameters = (yyvsp[-1].expr_vec); } -#line 2434 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2439 "bison_parser.cpp" /* yacc.c:1646 */ break; case 20: @@ -2440,19 +2445,19 @@ yyreduce: (yyval.import_stmt)->filePath = (yyvsp[-2].sval); (yyval.import_stmt)->tableName = (yyvsp[0].sval); } -#line 2444 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2449 "bison_parser.cpp" /* yacc.c:1646 */ break; case 21: #line 318 "bison_parser.y" /* yacc.c:1646 */ { (yyval.uval) = ImportStatement::kImportCSV; } -#line 2450 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2455 "bison_parser.cpp" /* yacc.c:1646 */ break; case 22: #line 322 "bison_parser.y" /* yacc.c:1646 */ { (yyval.sval) = strdup((yyvsp[0].expr)->name); delete (yyvsp[0].expr); } -#line 2456 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2461 "bison_parser.cpp" /* yacc.c:1646 */ break; case 23: @@ -2463,7 +2468,7 @@ yyreduce: (yyval.create_stmt)->tableName = (yyvsp[-4].sval); (yyval.create_stmt)->filePath = (yyvsp[0].sval); } -#line 2467 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2472 "bison_parser.cpp" /* yacc.c:1646 */ break; case 24: @@ -2474,31 +2479,31 @@ yyreduce: (yyval.create_stmt)->tableName = (yyvsp[-3].sval); (yyval.create_stmt)->columns = (yyvsp[-1].column_vec); } -#line 2478 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2483 "bison_parser.cpp" /* yacc.c:1646 */ break; case 25: #line 347 "bison_parser.y" /* yacc.c:1646 */ { (yyval.bval) = true; } -#line 2484 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2489 "bison_parser.cpp" /* yacc.c:1646 */ break; case 26: #line 348 "bison_parser.y" /* yacc.c:1646 */ { (yyval.bval) = false; } -#line 2490 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2495 "bison_parser.cpp" /* yacc.c:1646 */ break; case 27: #line 352 "bison_parser.y" /* yacc.c:1646 */ { (yyval.column_vec) = new std::vector(); (yyval.column_vec)->push_back((yyvsp[0].column_t)); } -#line 2496 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2501 "bison_parser.cpp" /* yacc.c:1646 */ break; case 28: #line 353 "bison_parser.y" /* yacc.c:1646 */ { (yyvsp[-2].column_vec)->push_back((yyvsp[0].column_t)); (yyval.column_vec) = (yyvsp[-2].column_vec); } -#line 2502 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2507 "bison_parser.cpp" /* yacc.c:1646 */ break; case 29: @@ -2506,31 +2511,31 @@ yyreduce: { (yyval.column_t) = new ColumnDefinition((yyvsp[-1].sval), (ColumnDefinition::DataType) (yyvsp[0].uval)); } -#line 2510 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2515 "bison_parser.cpp" /* yacc.c:1646 */ break; case 30: #line 364 "bison_parser.y" /* yacc.c:1646 */ { (yyval.uval) = ColumnDefinition::INT; } -#line 2516 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2521 "bison_parser.cpp" /* yacc.c:1646 */ break; case 31: #line 365 "bison_parser.y" /* yacc.c:1646 */ { (yyval.uval) = ColumnDefinition::INT; } -#line 2522 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2527 "bison_parser.cpp" /* yacc.c:1646 */ break; case 32: #line 366 "bison_parser.y" /* yacc.c:1646 */ { (yyval.uval) = ColumnDefinition::DOUBLE; } -#line 2528 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2533 "bison_parser.cpp" /* yacc.c:1646 */ break; case 33: #line 367 "bison_parser.y" /* yacc.c:1646 */ { (yyval.uval) = ColumnDefinition::TEXT; } -#line 2534 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2539 "bison_parser.cpp" /* yacc.c:1646 */ break; case 34: @@ -2539,7 +2544,7 @@ yyreduce: (yyval.drop_stmt) = new DropStatement(DropStatement::kTable); (yyval.drop_stmt)->name = (yyvsp[0].sval); } -#line 2543 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2548 "bison_parser.cpp" /* yacc.c:1646 */ break; case 35: @@ -2548,7 +2553,7 @@ yyreduce: (yyval.drop_stmt) = new DropStatement(DropStatement::kPreparedStatement); (yyval.drop_stmt)->name = (yyvsp[0].sval); } -#line 2552 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2557 "bison_parser.cpp" /* yacc.c:1646 */ break; case 36: @@ -2558,7 +2563,7 @@ yyreduce: (yyval.delete_stmt)->tableName = (yyvsp[-1].sval); (yyval.delete_stmt)->expr = (yyvsp[0].expr); } -#line 2562 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2567 "bison_parser.cpp" /* yacc.c:1646 */ break; case 37: @@ -2567,7 +2572,7 @@ yyreduce: (yyval.delete_stmt) = new DeleteStatement(); (yyval.delete_stmt)->tableName = (yyvsp[0].sval); } -#line 2571 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2576 "bison_parser.cpp" /* yacc.c:1646 */ break; case 38: @@ -2578,7 +2583,7 @@ yyreduce: (yyval.insert_stmt)->columns = (yyvsp[-4].str_vec); (yyval.insert_stmt)->values = (yyvsp[-1].expr_vec); } -#line 2582 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2587 "bison_parser.cpp" /* yacc.c:1646 */ break; case 39: @@ -2589,19 +2594,19 @@ yyreduce: (yyval.insert_stmt)->columns = (yyvsp[-1].str_vec); (yyval.insert_stmt)->select = (yyvsp[0].select_stmt); } -#line 2593 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2598 "bison_parser.cpp" /* yacc.c:1646 */ break; case 40: #line 429 "bison_parser.y" /* yacc.c:1646 */ { (yyval.str_vec) = (yyvsp[-1].str_vec); } -#line 2599 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2604 "bison_parser.cpp" /* yacc.c:1646 */ break; case 41: #line 430 "bison_parser.y" /* yacc.c:1646 */ { (yyval.str_vec) = NULL; } -#line 2605 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2610 "bison_parser.cpp" /* yacc.c:1646 */ break; case 42: @@ -2612,19 +2617,19 @@ yyreduce: (yyval.update_stmt)->updates = (yyvsp[-1].update_vec); (yyval.update_stmt)->where = (yyvsp[0].expr); } -#line 2616 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2621 "bison_parser.cpp" /* yacc.c:1646 */ break; case 43: #line 449 "bison_parser.y" /* yacc.c:1646 */ { (yyval.update_vec) = new std::vector(); (yyval.update_vec)->push_back((yyvsp[0].update_t)); } -#line 2622 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2627 "bison_parser.cpp" /* yacc.c:1646 */ break; case 44: #line 450 "bison_parser.y" /* yacc.c:1646 */ { (yyvsp[-2].update_vec)->push_back((yyvsp[0].update_t)); (yyval.update_vec) = (yyvsp[-2].update_vec); } -#line 2628 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2633 "bison_parser.cpp" /* yacc.c:1646 */ break; case 45: @@ -2634,19 +2639,19 @@ yyreduce: (yyval.update_t)->column = (yyvsp[-2].sval); (yyval.update_t)->value = (yyvsp[0].expr); } -#line 2638 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2643 "bison_parser.cpp" /* yacc.c:1646 */ break; case 48: #line 471 "bison_parser.y" /* yacc.c:1646 */ { (yyval.select_stmt) = (yyvsp[-1].select_stmt); } -#line 2644 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2649 "bison_parser.cpp" /* yacc.c:1646 */ break; case 49: #line 472 "bison_parser.y" /* yacc.c:1646 */ { (yyval.select_stmt) = (yyvsp[-1].select_stmt); } -#line 2650 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2655 "bison_parser.cpp" /* yacc.c:1646 */ break; case 50: @@ -2656,7 +2661,7 @@ yyreduce: (yyval.select_stmt)->order = (yyvsp[-1].order); (yyval.select_stmt)->limit = (yyvsp[0].limit); } -#line 2660 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2665 "bison_parser.cpp" /* yacc.c:1646 */ break; case 51: @@ -2670,11 +2675,22 @@ yyreduce: (yyval.select_stmt)->order = (yyvsp[-1].order); (yyval.select_stmt)->limit = (yyvsp[0].limit); } -#line 2674 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2679 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 55: -#line 499 "bison_parser.y" /* yacc.c:1646 */ + case 52: +#line 490 "bison_parser.y" /* yacc.c:1646 */ + { + (yyval.select_stmt) = (yyvsp[-4].select_stmt); + (yyval.select_stmt)->unionSelect = (yyvsp[-2].select_stmt); + (yyval.select_stmt)->order = (yyvsp[-1].order); + (yyval.select_stmt)->limit = (yyvsp[0].limit); + } +#line 2690 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 56: +#line 505 "bison_parser.y" /* yacc.c:1646 */ { (yyval.select_stmt) = new SelectStatement(); (yyval.select_stmt)->selectDistinct = (yyvsp[-4].bval); @@ -2683,381 +2699,381 @@ yyreduce: (yyval.select_stmt)->whereClause = (yyvsp[-1].expr); (yyval.select_stmt)->groupBy = (yyvsp[0].group_t); } -#line 2687 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 56: -#line 510 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.bval) = true; } -#line 2693 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2703 "bison_parser.cpp" /* yacc.c:1646 */ break; case 57: -#line 511 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.bval) = false; } -#line 2699 "bison_parser.cpp" /* yacc.c:1646 */ +#line 516 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.bval) = true; } +#line 2709 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 59: -#line 520 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.table) = (yyvsp[0].table); } -#line 2705 "bison_parser.cpp" /* yacc.c:1646 */ + case 58: +#line 517 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.bval) = false; } +#line 2715 "bison_parser.cpp" /* yacc.c:1646 */ break; case 60: -#line 525 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = (yyvsp[0].expr); } -#line 2711 "bison_parser.cpp" /* yacc.c:1646 */ +#line 526 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.table) = (yyvsp[0].table); } +#line 2721 "bison_parser.cpp" /* yacc.c:1646 */ break; case 61: -#line 526 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = NULL; } -#line 2717 "bison_parser.cpp" /* yacc.c:1646 */ +#line 531 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = (yyvsp[0].expr); } +#line 2727 "bison_parser.cpp" /* yacc.c:1646 */ break; case 62: -#line 530 "bison_parser.y" /* yacc.c:1646 */ +#line 532 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = NULL; } +#line 2733 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 63: +#line 536 "bison_parser.y" /* yacc.c:1646 */ { (yyval.group_t) = new GroupByDescription(); (yyval.group_t)->columns = (yyvsp[-1].expr_vec); (yyval.group_t)->having = (yyvsp[0].expr); } -#line 2727 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 63: -#line 535 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.group_t) = NULL; } -#line 2733 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2743 "bison_parser.cpp" /* yacc.c:1646 */ break; case 64: -#line 539 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = (yyvsp[0].expr); } -#line 2739 "bison_parser.cpp" /* yacc.c:1646 */ +#line 541 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.group_t) = NULL; } +#line 2749 "bison_parser.cpp" /* yacc.c:1646 */ break; case 65: -#line 540 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = NULL; } -#line 2745 "bison_parser.cpp" /* yacc.c:1646 */ +#line 545 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = (yyvsp[0].expr); } +#line 2755 "bison_parser.cpp" /* yacc.c:1646 */ break; case 66: -#line 543 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.order) = new OrderDescription((yyvsp[0].order_type), (yyvsp[-1].expr)); } -#line 2751 "bison_parser.cpp" /* yacc.c:1646 */ +#line 546 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = NULL; } +#line 2761 "bison_parser.cpp" /* yacc.c:1646 */ break; case 67: -#line 544 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.order) = NULL; } -#line 2757 "bison_parser.cpp" /* yacc.c:1646 */ +#line 549 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.order) = new OrderDescription((yyvsp[0].order_type), (yyvsp[-1].expr)); } +#line 2767 "bison_parser.cpp" /* yacc.c:1646 */ break; case 68: -#line 548 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.order_type) = kOrderAsc; } -#line 2763 "bison_parser.cpp" /* yacc.c:1646 */ +#line 550 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.order) = NULL; } +#line 2773 "bison_parser.cpp" /* yacc.c:1646 */ break; case 69: -#line 549 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.order_type) = kOrderDesc; } -#line 2769 "bison_parser.cpp" /* yacc.c:1646 */ +#line 554 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.order_type) = kOrderAsc; } +#line 2779 "bison_parser.cpp" /* yacc.c:1646 */ break; case 70: -#line 550 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.order_type) = kOrderAsc; } -#line 2775 "bison_parser.cpp" /* yacc.c:1646 */ +#line 555 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.order_type) = kOrderDesc; } +#line 2785 "bison_parser.cpp" /* yacc.c:1646 */ break; case 71: -#line 555 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.limit) = new LimitDescription((yyvsp[0].expr)->ival, kNoOffset); delete (yyvsp[0].expr); } -#line 2781 "bison_parser.cpp" /* yacc.c:1646 */ +#line 556 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.order_type) = kOrderAsc; } +#line 2791 "bison_parser.cpp" /* yacc.c:1646 */ break; case 72: -#line 556 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.limit) = new LimitDescription((yyvsp[-2].expr)->ival, (yyvsp[0].expr)->ival); delete (yyvsp[-2].expr); delete (yyvsp[0].expr); } -#line 2787 "bison_parser.cpp" /* yacc.c:1646 */ +#line 561 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.limit) = new LimitDescription((yyvsp[0].expr)->ival, kNoOffset); delete (yyvsp[0].expr); } +#line 2797 "bison_parser.cpp" /* yacc.c:1646 */ break; case 73: -#line 557 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.limit) = NULL; } -#line 2793 "bison_parser.cpp" /* yacc.c:1646 */ +#line 562 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.limit) = new LimitDescription((yyvsp[-2].expr)->ival, (yyvsp[0].expr)->ival); delete (yyvsp[-2].expr); delete (yyvsp[0].expr); } +#line 2803 "bison_parser.cpp" /* yacc.c:1646 */ break; case 74: -#line 564 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr_vec) = new std::vector(); (yyval.expr_vec)->push_back((yyvsp[0].expr)); } -#line 2799 "bison_parser.cpp" /* yacc.c:1646 */ +#line 563 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.limit) = NULL; } +#line 2809 "bison_parser.cpp" /* yacc.c:1646 */ break; case 75: -#line 565 "bison_parser.y" /* yacc.c:1646 */ - { (yyvsp[-2].expr_vec)->push_back((yyvsp[0].expr)); (yyval.expr_vec) = (yyvsp[-2].expr_vec); } -#line 2805 "bison_parser.cpp" /* yacc.c:1646 */ +#line 570 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr_vec) = new std::vector(); (yyval.expr_vec)->push_back((yyvsp[0].expr)); } +#line 2815 "bison_parser.cpp" /* yacc.c:1646 */ break; case 76: -#line 569 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr_vec) = new std::vector(); (yyval.expr_vec)->push_back((yyvsp[0].expr)); } -#line 2811 "bison_parser.cpp" /* yacc.c:1646 */ +#line 571 "bison_parser.y" /* yacc.c:1646 */ + { (yyvsp[-2].expr_vec)->push_back((yyvsp[0].expr)); (yyval.expr_vec) = (yyvsp[-2].expr_vec); } +#line 2821 "bison_parser.cpp" /* yacc.c:1646 */ break; case 77: -#line 570 "bison_parser.y" /* yacc.c:1646 */ - { (yyvsp[-2].expr_vec)->push_back((yyvsp[0].expr)); (yyval.expr_vec) = (yyvsp[-2].expr_vec); } -#line 2817 "bison_parser.cpp" /* yacc.c:1646 */ +#line 575 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr_vec) = new std::vector(); (yyval.expr_vec)->push_back((yyvsp[0].expr)); } +#line 2827 "bison_parser.cpp" /* yacc.c:1646 */ break; case 78: -#line 574 "bison_parser.y" /* yacc.c:1646 */ +#line 576 "bison_parser.y" /* yacc.c:1646 */ + { (yyvsp[-2].expr_vec)->push_back((yyvsp[0].expr)); (yyval.expr_vec) = (yyvsp[-2].expr_vec); } +#line 2833 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 79: +#line 580 "bison_parser.y" /* yacc.c:1646 */ { (yyval.expr) = (yyvsp[-1].expr); (yyval.expr)->alias = (yyvsp[0].sval); } -#line 2826 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2842 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 79: -#line 581 "bison_parser.y" /* yacc.c:1646 */ + case 80: +#line 587 "bison_parser.y" /* yacc.c:1646 */ { (yyval.expr) = (yyvsp[-1].expr); } -#line 2832 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 87: -#line 595 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpUnary(Expr::UMINUS, (yyvsp[0].expr)); } -#line 2838 "bison_parser.cpp" /* yacc.c:1646 */ +#line 2848 "bison_parser.cpp" /* yacc.c:1646 */ break; case 88: -#line 596 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpUnary(Expr::NOT, (yyvsp[0].expr)); } -#line 2844 "bison_parser.cpp" /* yacc.c:1646 */ +#line 601 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpUnary(Expr::UMINUS, (yyvsp[0].expr)); } +#line 2854 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 90: -#line 601 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '-', (yyvsp[0].expr)); } -#line 2850 "bison_parser.cpp" /* yacc.c:1646 */ + case 89: +#line 602 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpUnary(Expr::NOT, (yyvsp[0].expr)); } +#line 2860 "bison_parser.cpp" /* yacc.c:1646 */ break; case 91: -#line 602 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '+', (yyvsp[0].expr)); } -#line 2856 "bison_parser.cpp" /* yacc.c:1646 */ +#line 607 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '-', (yyvsp[0].expr)); } +#line 2866 "bison_parser.cpp" /* yacc.c:1646 */ break; case 92: -#line 603 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '/', (yyvsp[0].expr)); } -#line 2862 "bison_parser.cpp" /* yacc.c:1646 */ +#line 608 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '+', (yyvsp[0].expr)); } +#line 2872 "bison_parser.cpp" /* yacc.c:1646 */ break; case 93: -#line 604 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '*', (yyvsp[0].expr)); } -#line 2868 "bison_parser.cpp" /* yacc.c:1646 */ +#line 609 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '/', (yyvsp[0].expr)); } +#line 2878 "bison_parser.cpp" /* yacc.c:1646 */ break; case 94: -#line 605 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '%', (yyvsp[0].expr)); } -#line 2874 "bison_parser.cpp" /* yacc.c:1646 */ +#line 610 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '*', (yyvsp[0].expr)); } +#line 2884 "bison_parser.cpp" /* yacc.c:1646 */ break; case 95: -#line 606 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '^', (yyvsp[0].expr)); } -#line 2880 "bison_parser.cpp" /* yacc.c:1646 */ +#line 611 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '%', (yyvsp[0].expr)); } +#line 2890 "bison_parser.cpp" /* yacc.c:1646 */ break; case 96: -#line 607 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::AND, (yyvsp[0].expr)); } -#line 2886 "bison_parser.cpp" /* yacc.c:1646 */ +#line 612 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '^', (yyvsp[0].expr)); } +#line 2896 "bison_parser.cpp" /* yacc.c:1646 */ break; case 97: -#line 608 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::OR, (yyvsp[0].expr)); } -#line 2892 "bison_parser.cpp" /* yacc.c:1646 */ +#line 613 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::AND, (yyvsp[0].expr)); } +#line 2902 "bison_parser.cpp" /* yacc.c:1646 */ break; case 98: -#line 609 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::LIKE, (yyvsp[0].expr)); } -#line 2898 "bison_parser.cpp" /* yacc.c:1646 */ +#line 614 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::OR, (yyvsp[0].expr)); } +#line 2908 "bison_parser.cpp" /* yacc.c:1646 */ break; case 99: -#line 610 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-3].expr), Expr::NOT_LIKE, (yyvsp[0].expr)); } -#line 2904 "bison_parser.cpp" /* yacc.c:1646 */ +#line 615 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::LIKE, (yyvsp[0].expr)); } +#line 2914 "bison_parser.cpp" /* yacc.c:1646 */ break; case 100: -#line 615 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '=', (yyvsp[0].expr)); } -#line 2910 "bison_parser.cpp" /* yacc.c:1646 */ +#line 616 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-3].expr), Expr::NOT_LIKE, (yyvsp[0].expr)); } +#line 2920 "bison_parser.cpp" /* yacc.c:1646 */ break; case 101: -#line 616 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::NOT_EQUALS, (yyvsp[0].expr)); } -#line 2916 "bison_parser.cpp" /* yacc.c:1646 */ +#line 621 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '=', (yyvsp[0].expr)); } +#line 2926 "bison_parser.cpp" /* yacc.c:1646 */ break; case 102: -#line 617 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '<', (yyvsp[0].expr)); } -#line 2922 "bison_parser.cpp" /* yacc.c:1646 */ +#line 622 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::NOT_EQUALS, (yyvsp[0].expr)); } +#line 2932 "bison_parser.cpp" /* yacc.c:1646 */ break; case 103: -#line 618 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '>', (yyvsp[0].expr)); } -#line 2928 "bison_parser.cpp" /* yacc.c:1646 */ +#line 623 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '<', (yyvsp[0].expr)); } +#line 2938 "bison_parser.cpp" /* yacc.c:1646 */ break; case 104: -#line 619 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::LESS_EQ, (yyvsp[0].expr)); } -#line 2934 "bison_parser.cpp" /* yacc.c:1646 */ +#line 624 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), '>', (yyvsp[0].expr)); } +#line 2944 "bison_parser.cpp" /* yacc.c:1646 */ break; case 105: -#line 620 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::GREATER_EQ, (yyvsp[0].expr)); } -#line 2940 "bison_parser.cpp" /* yacc.c:1646 */ +#line 625 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::LESS_EQ, (yyvsp[0].expr)); } +#line 2950 "bison_parser.cpp" /* yacc.c:1646 */ break; case 106: -#line 624 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeFunctionRef((yyvsp[-4].sval), (yyvsp[-1].expr), (yyvsp[-2].bval)); } -#line 2946 "bison_parser.cpp" /* yacc.c:1646 */ +#line 626 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeOpBinary((yyvsp[-2].expr), Expr::GREATER_EQ, (yyvsp[0].expr)); } +#line 2956 "bison_parser.cpp" /* yacc.c:1646 */ break; case 107: -#line 628 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeColumnRef((yyvsp[0].sval)); } -#line 2952 "bison_parser.cpp" /* yacc.c:1646 */ +#line 630 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeFunctionRef((yyvsp[-4].sval), (yyvsp[-1].expr), (yyvsp[-2].bval)); } +#line 2962 "bison_parser.cpp" /* yacc.c:1646 */ break; case 108: -#line 629 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeColumnRef((yyvsp[-2].sval), (yyvsp[0].sval)); } -#line 2958 "bison_parser.cpp" /* yacc.c:1646 */ +#line 634 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeColumnRef((yyvsp[0].sval)); } +#line 2968 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 112: -#line 639 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeLiteral((yyvsp[0].sval)); } -#line 2964 "bison_parser.cpp" /* yacc.c:1646 */ + case 109: +#line 635 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeColumnRef((yyvsp[-2].sval), (yyvsp[0].sval)); } +#line 2974 "bison_parser.cpp" /* yacc.c:1646 */ break; case 113: -#line 644 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeLiteral((yyvsp[0].fval)); } -#line 2970 "bison_parser.cpp" /* yacc.c:1646 */ +#line 645 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeLiteral((yyvsp[0].sval)); } +#line 2980 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 115: -#line 649 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = Expr::makeLiteral((yyvsp[0].ival)); } -#line 2976 "bison_parser.cpp" /* yacc.c:1646 */ + case 114: +#line 650 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeLiteral((yyvsp[0].fval)); } +#line 2986 "bison_parser.cpp" /* yacc.c:1646 */ break; case 116: -#line 653 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.expr) = new Expr(kExprStar); } -#line 2982 "bison_parser.cpp" /* yacc.c:1646 */ +#line 655 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = Expr::makeLiteral((yyvsp[0].ival)); } +#line 2992 "bison_parser.cpp" /* yacc.c:1646 */ break; case 117: -#line 658 "bison_parser.y" /* yacc.c:1646 */ +#line 659 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.expr) = new Expr(kExprStar); } +#line 2998 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 118: +#line 664 "bison_parser.y" /* yacc.c:1646 */ { (yyval.expr) = Expr::makePlaceholder(yylloc.total_column); yyloc.placeholder_list.push_back((yyval.expr)); } -#line 2991 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3007 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 119: -#line 670 "bison_parser.y" /* yacc.c:1646 */ + case 120: +#line 676 "bison_parser.y" /* yacc.c:1646 */ { (yyvsp[0].table_vec)->push_back((yyvsp[-2].table)); auto tbl = new TableRef(kTableCrossProduct); tbl->list = (yyvsp[0].table_vec); (yyval.table) = tbl; } -#line 3002 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3018 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 121: -#line 681 "bison_parser.y" /* yacc.c:1646 */ + case 122: +#line 687 "bison_parser.y" /* yacc.c:1646 */ { auto tbl = new TableRef(kTableSelect); tbl->select = (yyvsp[-2].select_stmt); tbl->alias = (yyvsp[0].sval); (yyval.table) = tbl; } -#line 3013 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 123: -#line 692 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.table_vec) = new std::vector(); (yyval.table_vec)->push_back((yyvsp[0].table)); } -#line 3019 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3029 "bison_parser.cpp" /* yacc.c:1646 */ break; case 124: -#line 693 "bison_parser.y" /* yacc.c:1646 */ - { (yyvsp[-2].table_vec)->push_back((yyvsp[0].table)); (yyval.table_vec) = (yyvsp[-2].table_vec); } -#line 3025 "bison_parser.cpp" /* yacc.c:1646 */ +#line 698 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.table_vec) = new std::vector(); (yyval.table_vec)->push_back((yyvsp[0].table)); } +#line 3035 "bison_parser.cpp" /* yacc.c:1646 */ break; case 125: -#line 698 "bison_parser.y" /* yacc.c:1646 */ +#line 699 "bison_parser.y" /* yacc.c:1646 */ + { (yyvsp[-2].table_vec)->push_back((yyvsp[0].table)); (yyval.table_vec) = (yyvsp[-2].table_vec); } +#line 3041 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 126: +#line 704 "bison_parser.y" /* yacc.c:1646 */ { auto tbl = new TableRef(kTableName); tbl->name = (yyvsp[-1].sval); tbl->alias = (yyvsp[0].sval); (yyval.table) = tbl; } -#line 3036 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3052 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 126: -#line 708 "bison_parser.y" /* yacc.c:1646 */ + case 127: +#line 714 "bison_parser.y" /* yacc.c:1646 */ { (yyval.table) = new TableRef(kTableName); (yyval.table)->name = (yyvsp[0].sval); } -#line 3045 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3061 "bison_parser.cpp" /* yacc.c:1646 */ break; - case 129: -#line 722 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.sval) = (yyvsp[0].sval); } -#line 3051 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 132: + case 130: #line 728 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.sval) = NULL; } -#line 3057 "bison_parser.cpp" /* yacc.c:1646 */ + { (yyval.sval) = (yyvsp[0].sval); } +#line 3067 "bison_parser.cpp" /* yacc.c:1646 */ break; case 133: -#line 737 "bison_parser.y" /* yacc.c:1646 */ +#line 734 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.sval) = NULL; } +#line 3073 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 134: +#line 743 "bison_parser.y" /* yacc.c:1646 */ { (yyval.table) = new TableRef(kTableJoin); (yyval.table)->join = new JoinDefinition(); @@ -3066,64 +3082,64 @@ yyreduce: (yyval.table)->join->right = (yyvsp[-2].table); (yyval.table)->join->condition = (yyvsp[0].expr); } -#line 3070 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 134: -#line 748 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.uval) = kJoinInner; } -#line 3076 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3086 "bison_parser.cpp" /* yacc.c:1646 */ break; case 135: -#line 749 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.uval) = kJoinOuter; } -#line 3082 "bison_parser.cpp" /* yacc.c:1646 */ +#line 754 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.uval) = kJoinInner; } +#line 3092 "bison_parser.cpp" /* yacc.c:1646 */ break; case 136: -#line 750 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.uval) = kJoinLeft; } -#line 3088 "bison_parser.cpp" /* yacc.c:1646 */ +#line 755 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.uval) = kJoinOuter; } +#line 3098 "bison_parser.cpp" /* yacc.c:1646 */ break; case 137: -#line 751 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.uval) = kJoinRight; } -#line 3094 "bison_parser.cpp" /* yacc.c:1646 */ +#line 756 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.uval) = kJoinLeft; } +#line 3104 "bison_parser.cpp" /* yacc.c:1646 */ break; case 138: -#line 752 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.uval) = kJoinInner; } -#line 3100 "bison_parser.cpp" /* yacc.c:1646 */ +#line 757 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.uval) = kJoinRight; } +#line 3110 "bison_parser.cpp" /* yacc.c:1646 */ break; case 139: #line 758 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.uval) = kJoinInner; } +#line 3116 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 140: +#line 764 "bison_parser.y" /* yacc.c:1646 */ { auto tbl = new TableRef(kTableSelect); tbl->select = (yyvsp[-2].select_stmt); tbl->alias = (yyvsp[0].sval); (yyval.table) = tbl; } -#line 3111 "bison_parser.cpp" /* yacc.c:1646 */ - break; - - case 144: -#line 783 "bison_parser.y" /* yacc.c:1646 */ - { (yyval.str_vec) = new std::vector(); (yyval.str_vec)->push_back((yyvsp[0].sval)); } -#line 3117 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3127 "bison_parser.cpp" /* yacc.c:1646 */ break; case 145: -#line 784 "bison_parser.y" /* yacc.c:1646 */ +#line 789 "bison_parser.y" /* yacc.c:1646 */ + { (yyval.str_vec) = new std::vector(); (yyval.str_vec)->push_back((yyvsp[0].sval)); } +#line 3133 "bison_parser.cpp" /* yacc.c:1646 */ + break; + + case 146: +#line 790 "bison_parser.y" /* yacc.c:1646 */ { (yyvsp[-2].str_vec)->push_back((yyvsp[0].sval)); (yyval.str_vec) = (yyvsp[-2].str_vec); } -#line 3123 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3139 "bison_parser.cpp" /* yacc.c:1646 */ break; -#line 3127 "bison_parser.cpp" /* yacc.c:1646 */ +#line 3143 "bison_parser.cpp" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -3358,7 +3374,7 @@ yyreturn: #endif return yyresult; } -#line 787 "bison_parser.y" /* yacc.c:1906 */ +#line 793 "bison_parser.y" /* yacc.c:1906 */ /********************************* ** Section 4: Additional C code diff --git a/src/sql/statements.cpp b/src/sql/statements.cpp index c57982e..089966d 100644 --- a/src/sql/statements.cpp +++ b/src/sql/statements.cpp @@ -138,7 +138,7 @@ namespace hsql { placeholders.push_back((Expr*) e); } // Sort by col-id - std::sort(placeholders.begin(), placeholders.end(), [](Expr* i, Expr* j) -> bool { return (i->ival < j->ival); }); + std::sort(placeholders.begin(), placeholders.end(), [](Expr * i, Expr * j) -> bool { return (i->ival < j->ival); }); // Set the placeholder id on the Expr. This replaces the previously stored column id for (uintmax_t i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i; diff --git a/test/queries/tpc-h-01.sql b/test/queries/tpc-h-01.sql new file mode 100644 index 0000000..580b3b5 --- /dev/null +++ b/test/queries/tpc-h-01.sql @@ -0,0 +1,9 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT L_RETURNFLAG, L_LINESTATUS, SUM(L_QUANTITY) AS SUM_QTY, + SUM(L_EXTENDEDPRICE) AS SUM_BASE_PRICE, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS SUM_DISC_PRICE, + SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)*(1+L_TAX)) AS SUM_CHARGE, AVG(L_QUANTITY) AS AVG_QTY, + AVG(L_EXTENDEDPRICE) AS AVG_PRICE, AVG(L_DISCOUNT) AS AVG_DISC, COUNT(*) AS COUNT_ORDER +FROM LINEITEM +WHERE L_SHIPDATE <= dateadd(dd, -90, cast('1998-12-01' as datetime)) +GROUP BY L_RETURNFLAG, L_LINESTATUS +ORDER BY L_RETURNFLAG,L_LINESTATUS \ No newline at end of file diff --git a/test/queries/tpc-h-02.sql b/test/queries/tpc-h-02.sql new file mode 100644 index 0000000..c40be73 --- /dev/null +++ b/test/queries/tpc-h-02.sql @@ -0,0 +1,10 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT TOP 100 S_ACCTBAL, S_NAME, N_NAME, P_PARTKEY, P_MFGR, S_ADDRESS, S_PHONE, S_COMMENT +FROM PART, SUPPLIER, PARTSUPP, NATION, REGION +WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY AND P_SIZE = 15 AND +P_TYPE LIKE '%%BRASS' AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND +R_NAME = 'EUROPE' AND +PS_SUPPLYCOST = (SELECT MIN(PS_SUPPLYCOST) FROM PARTSUPP, SUPPLIER, NATION, REGION + WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY + AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND R_NAME = 'EUROPE') +ORDER BY S_ACCTBAL DESC, N_NAME, S_NAME, P_PARTKEY \ No newline at end of file diff --git a/test/queries/tpc-h-03.sql b/test/queries/tpc-h-03.sql new file mode 100644 index 0000000..5608c14 --- /dev/null +++ b/test/queries/tpc-h-03.sql @@ -0,0 +1,7 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT TOP 10 L_ORDERKEY, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE, O_ORDERDATE, O_SHIPPRIORITY +FROM CUSTOMER, ORDERS, LINEITEM +WHERE C_MKTSEGMENT = 'BUILDING' AND C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND +O_ORDERDATE < '1995-03-15' AND L_SHIPDATE > '1995-03-15' +GROUP BY L_ORDERKEY, O_ORDERDATE, O_SHIPPRIORITY +ORDER BY REVENUE DESC, O_ORDERDATE; \ No newline at end of file diff --git a/test/queries/tpc-h-04.sql b/test/queries/tpc-h-04.sql new file mode 100644 index 0000000..3d420b3 --- /dev/null +++ b/test/queries/tpc-h-04.sql @@ -0,0 +1,6 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT O_ORDERPRIORITY, COUNT(*) AS ORDER_COUNT FROM ORDERS +WHERE O_ORDERDATE >= '1993-07-01' AND O_ORDERDATE < dateadd(mm,3, cast('1993-07-01' as datetime)) +AND EXISTS (SELECT * FROM LINEITEM WHERE L_ORDERKEY = O_ORDERKEY AND L_COMMITDATE < L_RECEIPTDATE) +GROUP BY O_ORDERPRIORITY +ORDER BY O_ORDERPRIORITY \ No newline at end of file diff --git a/test/queries/tpc-h-05.sql b/test/queries/tpc-h-05.sql new file mode 100644 index 0000000..0469f3f --- /dev/null +++ b/test/queries/tpc-h-05.sql @@ -0,0 +1,9 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT N_NAME, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE +FROM CUSTOMER, ORDERS, LINEITEM, SUPPLIER, NATION, REGION +WHERE C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND L_SUPPKEY = S_SUPPKEY +AND C_NATIONKEY = S_NATIONKEY AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY +AND R_NAME = 'ASIA' AND O_ORDERDATE >= '1994-01-01' +AND O_ORDERDATE < DATEADD(YY, 1, cast('1994-01-01' as datetime)) +GROUP BY N_NAME +ORDER BY REVENUE DESC \ No newline at end of file diff --git a/test/queries/tpc-h-06.sql b/test/queries/tpc-h-06.sql new file mode 100644 index 0000000..394bba9 --- /dev/null +++ b/test/queries/tpc-h-06.sql @@ -0,0 +1,5 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT SUM(L_EXTENDEDPRICE*L_DISCOUNT) AS REVENUE +FROM LINEITEM +WHERE L_SHIPDATE >= '1994-01-01' AND L_SHIPDATE < dateadd(yy, 1, cast('1994-01-01' as datetime)) +AND L_DISCOUNT BETWEEN .06 - 0.01 AND .06 + 0.01 AND L_QUANTITY < 24 \ No newline at end of file diff --git a/test/queries/tpc-h-07.sql b/test/queries/tpc-h-07.sql new file mode 100644 index 0000000..449cc26 --- /dev/null +++ b/test/queries/tpc-h-07.sql @@ -0,0 +1,11 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT SUPP_NATION, CUST_NATION, L_YEAR, SUM(VOLUME) AS REVENUE +FROM ( SELECT N1.N_NAME AS SUPP_NATION, N2.N_NAME AS CUST_NATION, datepart(yy, L_SHIPDATE) AS L_YEAR, + L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME + FROM SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2 + WHERE S_SUPPKEY = L_SUPPKEY AND O_ORDERKEY = L_ORDERKEY AND C_CUSTKEY = O_CUSTKEY + AND S_NATIONKEY = N1.N_NATIONKEY AND C_NATIONKEY = N2.N_NATIONKEY AND ((N1.N_NAME = 'FRANCE' AND N2.N_NAME = 'GERMANY') OR + (N1.N_NAME = 'GERMANY' AND N2.N_NAME = 'FRANCE')) AND + L_SHIPDATE BETWEEN '1995-01-01' AND '1996-12-31' ) AS SHIPPING +GROUP BY SUPP_NATION, CUST_NATION, L_YEAR +ORDER BY SUPP_NATION, CUST_NATION, L_YEAR \ No newline at end of file diff --git a/test/queries/tpc-h-08.sql b/test/queries/tpc-h-08.sql new file mode 100644 index 0000000..7c0ff24 --- /dev/null +++ b/test/queries/tpc-h-08.sql @@ -0,0 +1,10 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT O_YEAR, SUM(CASE WHEN NATION = 'BRAZIL' THEN VOLUME ELSE 0 END)/SUM(VOLUME) AS MKT_SHARE +FROM (SELECT datepart(yy,O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME, N2.N_NAME AS NATION + FROM PART, SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION + WHERE P_PARTKEY = L_PARTKEY AND S_SUPPKEY = L_SUPPKEY AND L_ORDERKEY = O_ORDERKEY + AND O_CUSTKEY = C_CUSTKEY AND C_NATIONKEY = N1.N_NATIONKEY AND + N1.N_REGIONKEY = R_REGIONKEY AND R_NAME = 'AMERICA' AND S_NATIONKEY = N2.N_NATIONKEY + AND O_ORDERDATE BETWEEN '1995-01-01' AND '1996-12-31' AND P_TYPE= 'ECONOMY ANODIZED STEEL') AS ALL_NATIONS +GROUP BY O_YEAR +ORDER BY O_YEAR \ No newline at end of file diff --git a/test/queries/tpc-h-09.sql b/test/queries/tpc-h-09.sql new file mode 100644 index 0000000..a5856e0 --- /dev/null +++ b/test/queries/tpc-h-09.sql @@ -0,0 +1,10 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT NATION, O_YEAR, SUM(AMOUNT) AS SUM_PROFIT +FROM (SELECT N_NAME AS NATION, datepart(yy, O_ORDERDATE) AS O_YEAR, + L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY AS AMOUNT + FROM PART, SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION + WHERE S_SUPPKEY = L_SUPPKEY AND PS_SUPPKEY= L_SUPPKEY AND PS_PARTKEY = L_PARTKEY AND + P_PARTKEY= L_PARTKEY AND O_ORDERKEY = L_ORDERKEY AND S_NATIONKEY = N_NATIONKEY AND + P_NAME LIKE '%%green%%') AS PROFIT +GROUP BY NATION, O_YEAR +ORDER BY NATION, O_YEAR DESC \ No newline at end of file diff --git a/test/queries/tpc-h-10.sql b/test/queries/tpc-h-10.sql new file mode 100644 index 0000000..7229b24 --- /dev/null +++ b/test/queries/tpc-h-10.sql @@ -0,0 +1,9 @@ +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html +SELECT TOP 20 C_CUSTKEY, C_NAME, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE, C_ACCTBAL, +N_NAME, C_ADDRESS, C_PHONE, C_COMMENT +FROM CUSTOMER, ORDERS, LINEITEM, NATION +WHERE C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND O_ORDERDATE>= '1993-10-01' AND +O_ORDERDATE < dateadd(mm, 3, cast('1993-10-01' as datetime)) AND +L_RETURNFLAG = 'R' AND C_NATIONKEY = N_NATIONKEY +GROUP BY C_CUSTKEY, C_NAME, C_ACCTBAL, C_PHONE, N_NAME, C_ADDRESS, C_COMMENT +ORDER BY REVENUE DESC \ No newline at end of file diff --git a/test/select_tests.cpp b/test/select_tests.cpp index 90474d9..e302a84 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -46,7 +46,7 @@ TEST(SelectDistinctTest) { TEST_PARSE_SINGLE_SQL( "SELECT DISTINCT grade, city FROM students;", kStmtSelect, - SelectStatement, + SelectStatement, result, stmt); diff --git a/test/sql_grammar_test.cpp b/test/sql_grammar_test.cpp index 46e5c63..3bfecc8 100644 --- a/test/sql_grammar_test.cpp +++ b/test/sql_grammar_test.cpp @@ -13,96 +13,96 @@ using namespace hsql; std::vector readlines(std::string path) { - std::ifstream infile(path); - std::vector lines; - std::string line; - while (std::getline(infile, line)) { - std::istringstream iss(line); + std::ifstream infile(path); + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + std::istringstream iss(line); - // Skip comments - if (line[0] == '#' || - (line[0] == '-' && line[1] == '-')) { - continue; - } - - lines.push_back(line); + // Skip comments + if (line[0] == '#' || + (line[0] == '-' && line[1] == '-')) { + continue; } - return lines; + + lines.push_back(line); + } + return lines; } #define STREQ(a, b) (std::string(a).compare(std::string(b)) == 0) TEST(AutoGrammarTest) { - const std::vector& args = mt::Runtime::args(); - if (args.size() <= 1) { - fprintf(stderr, "Usage: grammar_test [--false] [-f path] query, ...\n"); - return; - } + const std::vector& args = mt::Runtime::args(); + if (args.size() <= 1) { + fprintf(stderr, "Usage: grammar_test [--false] [-f path] query, ...\n"); + return; + } - bool globalExpectFalse = false; - bool useFile = false; - std::string filePath = ""; - - // Parse command line arguments - uint i = 1; - for (; i < args.size(); ++i) { - if (STREQ(args[i], "--false")) globalExpectFalse = true; - else if (STREQ(args[i], "-f")) { - useFile = true; - filePath = args[++i]; - } else { - break; - } - } + bool globalExpectFalse = false; + bool useFile = false; + std::string filePath = ""; - - // Read list of queries for this rest - std::vector queries; - if (useFile) { - queries = readlines(filePath); + // Parse command line arguments + uint i = 1; + for (; i < args.size(); ++i) { + if (STREQ(args[i], "--false")) globalExpectFalse = true; + else if (STREQ(args[i], "-f")) { + useFile = true; + filePath = args[++i]; } else { - for (; i < args.size(); ++i) queries.push_back(args[i]); + break; + } + } + + + // Read list of queries for this rest + std::vector queries; + if (useFile) { + queries = readlines(filePath); + } else { + for (; i < args.size(); ++i) queries.push_back(args[i]); + } + + + // Execute queries + int numFailed = 0; + for (std::string sql : queries) { + bool expectFalse = globalExpectFalse; + if (sql.at(0) == '!') { + expectFalse = !expectFalse; + sql = sql.substr(1); } + // Measuring the parsing time + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); - // Execute queries - int numFailed = 0; - for (std::string sql : queries) { - bool expectFalse = globalExpectFalse; - if (sql.at(0) == '!') { - expectFalse = !expectFalse; - sql = sql.substr(1); - } + // Parsing + SQLParserResult* result = SQLParser::parseSQLString(sql.c_str()); - // Measuring the parsing time - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + double us = elapsed_seconds.count() * 1000 * 1000; - // Parsing - SQLParserResult* result = SQLParser::parseSQLString(sql.c_str()); - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end-start; - double us = elapsed_seconds.count() * 1000 * 1000; - - if (expectFalse == result->isValid()) { - printf("\033[0;31m{ failed}\033[0m\n"); - printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", result->errorMsg(), result->errorLine(), result->errorColumn()); - printf("\t%s\n", sql.c_str()); - numFailed++; - } else { - // TODO: indicate whether expectFalse was set - printf("\033[0;32m{ ok} (%.1fus)\033[0m %s\n", us, sql.c_str()); - } - - delete result; - } - - if (numFailed == 0) { - printf("\033[0;32m{ ok} \033[0mAll %lu grammar tests completed successfully!\n", queries.size()); + if (expectFalse == result->isValid()) { + printf("\033[0;31m{ failed}\033[0m\n"); + printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", result->errorMsg(), result->errorLine(), result->errorColumn()); + printf("\t%s\n", sql.c_str()); + numFailed++; } else { - fprintf(stderr, "\033[0;31m{ failed} \033[0mSome grammar tests failed! %d out of %lu tests failed!\n", numFailed, queries.size()); + // TODO: indicate whether expectFalse was set + printf("\033[0;32m{ ok} (%.1fus)\033[0m %s\n", us, sql.c_str()); } - ASSERT_EQ(numFailed, 0); + + delete result; + } + + if (numFailed == 0) { + printf("\033[0;32m{ ok} \033[0mAll %lu grammar tests completed successfully!\n", queries.size()); + } else { + fprintf(stderr, "\033[0;31m{ failed} \033[0mSome grammar tests failed! %d out of %lu tests failed!\n", numFailed, queries.size()); + } + ASSERT_EQ(numFailed, 0); } diff --git a/test/sql_tests.cpp b/test/sql_tests.cpp index f0d25a6..89ccf60 100644 --- a/test/sql_tests.cpp +++ b/test/sql_tests.cpp @@ -11,160 +11,161 @@ using namespace hsql; TEST(DeleteStatementTest) { - const SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;"); - ASSERT(result->isValid()); - ASSERT_EQ(result->size(), 1); - ASSERT(result->getStatement(0)->type() == kStmtDelete); + const SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;"); + ASSERT(result->isValid()); + ASSERT_EQ(result->size(), 1); + ASSERT(result->getStatement(0)->type() == kStmtDelete); - const DeleteStatement* stmt = (const DeleteStatement*) result->getStatement(0); - ASSERT_STREQ(stmt->tableName, "students"); - ASSERT_NOTNULL(stmt->expr); - ASSERT(stmt->expr->isType(kExprOperator)); - ASSERT_STREQ(stmt->expr->expr->name, "grade"); - ASSERT_EQ(stmt->expr->expr2->fval, 2.0); + const DeleteStatement* stmt = (const DeleteStatement*) result->getStatement(0); + ASSERT_STREQ(stmt->tableName, "students"); + ASSERT_NOTNULL(stmt->expr); + ASSERT(stmt->expr->isType(kExprOperator)); + ASSERT_STREQ(stmt->expr->expr->name, "grade"); + ASSERT_EQ(stmt->expr->expr2->fval, 2.0); - delete result; + delete result; } TEST(CreateStatementTest) { - const SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)"); - ASSERT(result->isValid()); - ASSERT_EQ(result->size(), 1); - ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate); + const SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)"); + ASSERT(result->isValid()); + ASSERT_EQ(result->size(), 1); + ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate); - const CreateStatement* stmt = (const CreateStatement*) result->getStatement(0); - ASSERT_EQ(stmt->type, CreateStatement::kTable); - ASSERT_STREQ(stmt->tableName, "students"); - ASSERT_NOTNULL(stmt->columns); - ASSERT_EQ(stmt->columns->size(), 4); - ASSERT_STREQ(stmt->columns->at(0)->name, "name"); - ASSERT_STREQ(stmt->columns->at(1)->name, "student_number"); - ASSERT_STREQ(stmt->columns->at(2)->name, "city"); - ASSERT_STREQ(stmt->columns->at(3)->name, "grade"); - ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT); - ASSERT_EQ(stmt->columns->at(1)->type, ColumnDefinition::INT); - ASSERT_EQ(stmt->columns->at(2)->type, ColumnDefinition::INT); - ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE); + const CreateStatement* stmt = (const CreateStatement*) result->getStatement(0); + ASSERT_EQ(stmt->type, CreateStatement::kTable); + ASSERT_STREQ(stmt->tableName, "students"); + ASSERT_NOTNULL(stmt->columns); + ASSERT_EQ(stmt->columns->size(), 4); + ASSERT_STREQ(stmt->columns->at(0)->name, "name"); + ASSERT_STREQ(stmt->columns->at(1)->name, "student_number"); + ASSERT_STREQ(stmt->columns->at(2)->name, "city"); + ASSERT_STREQ(stmt->columns->at(3)->name, "grade"); + ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT); + ASSERT_EQ(stmt->columns->at(1)->type, ColumnDefinition::INT); + ASSERT_EQ(stmt->columns->at(2)->type, ColumnDefinition::INT); + ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE); - delete result; + delete result; } TEST(UpdateStatementTest) { - const SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';"); - ASSERT(result->isValid()); - ASSERT_EQ(result->size(), 1); - ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate); + const SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';"); + ASSERT(result->isValid()); + ASSERT_EQ(result->size(), 1); + ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate); - const UpdateStatement* stmt = (const UpdateStatement*) result->getStatement(0); - ASSERT_NOTNULL(stmt->table); - ASSERT_STREQ(stmt->table->name, "students"); - - ASSERT_NOTNULL(stmt->updates); - ASSERT_EQ(stmt->updates->size(), 2); - ASSERT_STREQ(stmt->updates->at(0)->column, "grade"); - ASSERT_STREQ(stmt->updates->at(1)->column, "name"); - ASSERT(stmt->updates->at(0)->value->isType(kExprLiteralFloat)); - ASSERT(stmt->updates->at(1)->value->isType(kExprLiteralString)); - ASSERT_EQ(stmt->updates->at(0)->value->fval, 5.0); - ASSERT_STREQ(stmt->updates->at(1)->value->name, "test"); + const UpdateStatement* stmt = (const UpdateStatement*) result->getStatement(0); + ASSERT_NOTNULL(stmt->table); + ASSERT_STREQ(stmt->table->name, "students"); - ASSERT_NOTNULL(stmt->where); - ASSERT(stmt->where->isType(kExprOperator)); - ASSERT(stmt->where->isSimpleOp('=')); - ASSERT_STREQ(stmt->where->expr->name, "name"); - ASSERT_STREQ(stmt->where->expr2->name, "Max Mustermann");\ + ASSERT_NOTNULL(stmt->updates); + ASSERT_EQ(stmt->updates->size(), 2); + ASSERT_STREQ(stmt->updates->at(0)->column, "grade"); + ASSERT_STREQ(stmt->updates->at(1)->column, "name"); + ASSERT(stmt->updates->at(0)->value->isType(kExprLiteralFloat)); + ASSERT(stmt->updates->at(1)->value->isType(kExprLiteralString)); + ASSERT_EQ(stmt->updates->at(0)->value->fval, 5.0); + ASSERT_STREQ(stmt->updates->at(1)->value->name, "test"); - delete result; + ASSERT_NOTNULL(stmt->where); + ASSERT(stmt->where->isType(kExprOperator)); + ASSERT(stmt->where->isSimpleOp('=')); + ASSERT_STREQ(stmt->where->expr->name, "name"); + ASSERT_STREQ(stmt->where->expr2->name, "Max Mustermann"); + \ + + delete result; } TEST(InsertStatementTest) { - TEST_PARSE_SINGLE_SQL( - "INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)", - kStmtInsert, - InsertStatement, - result, - stmt); + TEST_PARSE_SINGLE_SQL( + "INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)", + kStmtInsert, + InsertStatement, + result, + stmt); - ASSERT_EQ(stmt->values->size(), 4); - // TODO + ASSERT_EQ(stmt->values->size(), 4); + // TODO - delete result; + delete result; } TEST(DropTableStatementTest) { - TEST_PARSE_SINGLE_SQL( - "DROP TABLE students", - kStmtDrop, - DropStatement, - result, - stmt); + TEST_PARSE_SINGLE_SQL( + "DROP TABLE students", + kStmtDrop, + DropStatement, + result, + stmt); - ASSERT_EQ(stmt->type, DropStatement::kTable); - ASSERT_NOTNULL(stmt->name); - ASSERT_STREQ(stmt->name, "students"); + ASSERT_EQ(stmt->type, DropStatement::kTable); + ASSERT_NOTNULL(stmt->name); + ASSERT_STREQ(stmt->name, "students"); - delete result; + delete result; } TEST(PrepareStatementTest) { - std::string query = "PREPARE test {" - "INSERT INTO test VALUES(?);" - "SELECT ?, test FROM test WHERE c1 = ?;" - "};" - "PREPARE stmt: SELECT * FROM data WHERE c1 = ?;" - "DEALLOCATE PREPARE stmt;"; + std::string query = "PREPARE test {" + "INSERT INTO test VALUES(?);" + "SELECT ?, test FROM test WHERE c1 = ?;" + "};" + "PREPARE stmt: SELECT * FROM data WHERE c1 = ?;" + "DEALLOCATE PREPARE stmt;"; - TEST_PARSE_SQL_QUERY(query, result, 3); + TEST_PARSE_SQL_QUERY(query, result, 3); - TEST_CAST_STMT(result, 0, kStmtPrepare, PrepareStatement, prep1); - TEST_CAST_STMT(result, 1, kStmtPrepare, PrepareStatement, prep2); - TEST_CAST_STMT(result, 2, kStmtDrop, DropStatement, drop); + TEST_CAST_STMT(result, 0, kStmtPrepare, PrepareStatement, prep1); + TEST_CAST_STMT(result, 1, kStmtPrepare, PrepareStatement, prep2); + TEST_CAST_STMT(result, 2, kStmtDrop, DropStatement, drop); - // Prepare Statement #1 - ASSERT_STREQ(prep1->name, "test"); - ASSERT_EQ(prep1->placeholders.size(), 3); - ASSERT_EQ(prep1->query->size(), 2); - - TEST_CAST_STMT(prep1->query, 0, kStmtInsert, InsertStatement, insert); - TEST_CAST_STMT(prep1->query, 1, kStmtSelect, SelectStatement, select); + // Prepare Statement #1 + ASSERT_STREQ(prep1->name, "test"); + ASSERT_EQ(prep1->placeholders.size(), 3); + ASSERT_EQ(prep1->query->size(), 2); - ASSERT(insert->values->at(0)->isType(kExprPlaceholder)); - ASSERT(select->selectList->at(0)->isType(kExprPlaceholder)); - ASSERT(select->whereClause->expr2->isType(kExprPlaceholder)); + TEST_CAST_STMT(prep1->query, 0, kStmtInsert, InsertStatement, insert); + TEST_CAST_STMT(prep1->query, 1, kStmtSelect, SelectStatement, select); - // Check IDs of placeholders - ASSERT_EQ(insert->values->at(0)->ival, 0); - ASSERT_EQ(insert->values->at(0), prep1->placeholders[0]); + ASSERT(insert->values->at(0)->isType(kExprPlaceholder)); + ASSERT(select->selectList->at(0)->isType(kExprPlaceholder)); + ASSERT(select->whereClause->expr2->isType(kExprPlaceholder)); - ASSERT_EQ(select->selectList->at(0)->ival, 1); - ASSERT_EQ(select->selectList->at(0), prep1->placeholders[1]); + // Check IDs of placeholders + ASSERT_EQ(insert->values->at(0)->ival, 0); + ASSERT_EQ(insert->values->at(0), prep1->placeholders[0]); - ASSERT_EQ(select->whereClause->expr2->ival, 2); - ASSERT_EQ(select->whereClause->expr2, prep1->placeholders[2]); + ASSERT_EQ(select->selectList->at(0)->ival, 1); + ASSERT_EQ(select->selectList->at(0), prep1->placeholders[1]); - // Prepare Statement #2 - ASSERT_STREQ(prep2->name, "stmt"); - ASSERT_EQ(prep2->placeholders.size(), 1); + ASSERT_EQ(select->whereClause->expr2->ival, 2); + ASSERT_EQ(select->whereClause->expr2, prep1->placeholders[2]); - // Deallocate Statement - ASSERT_EQ(drop->type, DropStatement::kPreparedStatement); - ASSERT_STREQ(drop->name, "stmt"); + // Prepare Statement #2 + ASSERT_STREQ(prep2->name, "stmt"); + ASSERT_EQ(prep2->placeholders.size(), 1); - delete result; + // Deallocate Statement + ASSERT_EQ(drop->type, DropStatement::kPreparedStatement); + ASSERT_STREQ(drop->name, "stmt"); + + delete result; } TEST(ExecuteStatementTest) { - TEST_PARSE_SINGLE_SQL("EXECUTE test(1, 2);", kStmtExecute, ExecuteStatement, result, stmt); + TEST_PARSE_SINGLE_SQL("EXECUTE test(1, 2);", kStmtExecute, ExecuteStatement, result, stmt); - ASSERT_STREQ(stmt->name, "test"); - ASSERT_EQ(stmt->parameters->size(), 2); + ASSERT_STREQ(stmt->name, "test"); + ASSERT_EQ(stmt->parameters->size(), 2); - delete result; + delete result; } TEST_MAIN(); \ No newline at end of file diff --git a/test/tpc_h_tests.cpp b/test/tpc_h_tests.cpp new file mode 100644 index 0000000..f85f644 --- /dev/null +++ b/test/tpc_h_tests.cpp @@ -0,0 +1,43 @@ +#include "thirdparty/microtest/microtest.h" +#include "sql_asserts.h" +#include "SQLParser.h" +#include "sqlhelper.h" + +#include +#include +#include +#include + +using namespace hsql; + +TEST(TPCHQueryTests) { + std::vector files = { + "test/queries/tpc-h-01.sql", + "test/queries/tpc-h-02.sql", + "test/queries/tpc-h-03.sql", + "test/queries/tpc-h-04.sql", + "test/queries/tpc-h-05.sql", + "test/queries/tpc-h-06.sql", + "test/queries/tpc-h-07.sql", + "test/queries/tpc-h-08.sql", + "test/queries/tpc-h-09.sql", + "test/queries/tpc-h-10.sql" + }; + + int testsFailed = 0; + for (const std::string& file_path : files) { + std::ifstream t(file_path.c_str()); + std::string query((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + SQLParserResult* result = SQLParser::parseSQLString(query.c_str()); + if (!result->isValid()) { + mt::printFailed(file_path.c_str()); + printf("%s %s (L%d:%d)%s\n", mt::red(), result->errorMsg(), result->errorLine(), result->errorColumn(), mt::def()); + ++testsFailed; + } else { + mt::printOk(file_path.c_str()); + } + } + ASSERT_EQ(testsFailed, 0); +} From f82504b3199686491c211c1960906e6ccf89f84c Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 02:30:44 +0100 Subject: [PATCH 02/12] Allow order by to define a list of expressions to order by --- src/parser/bison_parser.y | 39 ++++++++++++++++++++++++++++----------- src/sql/SelectStatement.h | 2 +- src/sqlhelper.cpp | 4 ++-- test/select_tests.cpp | 20 ++++++++++++++++++++ test/valid_queries.sql | 1 + 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index be3c72a..88d5e23 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -131,6 +131,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch std::vector* column_vec; std::vector* update_vec; std::vector* expr_vec; + std::vector* order_vec; } @@ -146,7 +147,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch } } delete ($$); -} +} %destructor { delete ($$); } <*> @@ -197,8 +198,8 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias placeholder_expr %type column_name literal int_literal num_literal string_literal %type comp_expr opt_where join_condition opt_having -%type opt_order -%type opt_limit +%type opt_limit opt_top +%type order_desc %type opt_order_type %type column_def %type update_clause @@ -207,6 +208,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type ident_commalist opt_column_list %type expr_list select_list literal_list %type table_ref_commalist +%type opt_order order_list %type update_clause_commalist %type column_def_commalist @@ -502,13 +504,14 @@ set_operator: ; select_clause: - SELECT opt_distinct select_list from_clause opt_where opt_group { + SELECT opt_top opt_distinct select_list from_clause opt_where opt_group { $$ = new SelectStatement(); - $$->selectDistinct = $2; - $$->selectList = $3; - $$->fromTable = $4; - $$->whereClause = $5; - $$->groupBy = $6; + $$->limit = $2; + $$->selectDistinct = $3; + $$->selectList = $4; + $$->fromTable = $5; + $$->whereClause = $6; + $$->groupBy = $7; } ; @@ -521,7 +524,6 @@ select_list: expr_list ; - from_clause: FROM table_ref { $$ = $2; } ; @@ -546,16 +548,31 @@ opt_having: | /* empty */ { $$ = NULL; } opt_order: - ORDER BY expr opt_order_type { $$ = new OrderDescription($4, $3); } + ORDER BY order_list { $$ = $3; } | /* empty */ { $$ = NULL; } ; +order_list: + order_desc { $$ = new std::vector(); $$->push_back($1); } + | order_list ',' order_desc { $1->push_back($3); $$ = $1; } + ; + +order_desc: + expr opt_order_type { $$ = new OrderDescription($2, $1); } + ; + opt_order_type: ASC { $$ = kOrderAsc; } | DESC { $$ = kOrderDesc; } | /* empty */ { $$ = kOrderAsc; } ; +// TODO: TOP and LIMIT can take more than just int literals. + +opt_top: + TOP int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; } + | /* empty */ { $$ = NULL; } + ; opt_limit: LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; } diff --git a/src/sql/SelectStatement.h b/src/sql/SelectStatement.h index a9d169d..bb60836 100644 --- a/src/sql/SelectStatement.h +++ b/src/sql/SelectStatement.h @@ -63,7 +63,7 @@ namespace hsql { GroupByDescription* groupBy; SelectStatement* unionSelect; - OrderDescription* order; + std::vector* order; LimitDescription* limit; }; diff --git a/src/sqlhelper.cpp b/src/sqlhelper.cpp index 5a47df8..529cead 100644 --- a/src/sqlhelper.cpp +++ b/src/sqlhelper.cpp @@ -139,8 +139,8 @@ namespace hsql { if (stmt->order != NULL) { inprint("OrderBy:", numIndent + 1); - printExpression(stmt->order->expr, numIndent + 2); - if (stmt->order->type == kOrderAsc) inprint("ascending", numIndent + 2); + printExpression(stmt->order->at(0)->expr, numIndent + 2); + if (stmt->order->at(0)->type == kOrderAsc) inprint("ascending", numIndent + 2); else inprint("descending", numIndent + 2); } diff --git a/test/select_tests.cpp b/test/select_tests.cpp index e302a84..dead654 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -73,3 +73,23 @@ TEST(SelectGroupDistinctTest) { } +TEST(OrderByTest) { + TEST_PARSE_SINGLE_SQL( + "SELECT grade, city FROM students ORDER BY grade, city DESC;", + kStmtSelect, + SelectStatement, + result, + stmt); + + ASSERT_NULL(stmt->whereClause); + ASSERT_NOTNULL(stmt->order); + + ASSERT_EQ(stmt->order->size(), 2); + ASSERT_EQ(stmt->order->at(0)->type, kOrderAsc); + ASSERT_STREQ(stmt->order->at(0)->expr->name, "grade"); + + ASSERT_EQ(stmt->order->at(1)->type, kOrderDesc); + ASSERT_STREQ(stmt->order->at(1)->expr->name, "city"); + + delete result; +} diff --git a/test/valid_queries.sql b/test/valid_queries.sql index b211cbf..dfece3d 100644 --- a/test/valid_queries.sql +++ b/test/valid_queries.sql @@ -8,6 +8,7 @@ SELECT * FROM "table" LIMIT 10 OFFSET 10; SELECT * FROM second; SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1; SELECT * FROM (SELECT * FROM t1); SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; +SELECT TOP 10 * FROM t1 ORDER BY col1, col2; # JOIN SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5 SELECT * FROM t1 JOIN t2 ON c1 = c2; From 9ecfa8e8f6fb2badba240d3355090a9eaa028025 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 02:49:29 +0100 Subject: [PATCH 03/12] Allow function expressions to have variable length of parameters --- src/parser/bison_parser.y | 2 +- src/sql/Expr.cpp | 4 ++-- src/sql/Expr.h | 4 +++- test/queries/tpc-h-02.sql | 2 +- test/queries/tpc-h-09.sql | 2 +- test/select_tests.cpp | 39 +++++++++++++++++++++++++++++++++++++++ test/valid_queries.sql | 1 + 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 88d5e23..27c12c0 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -644,7 +644,7 @@ comp_expr: ; function_expr: - IDENTIFIER '(' opt_distinct expr ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } + IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } ; column_name: diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index dab4cdf..9035884 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -79,10 +79,10 @@ namespace hsql { return e; } - Expr* Expr::makeFunctionRef(char* func_name, Expr* expr, bool distinct) { + Expr* Expr::makeFunctionRef(char* func_name, std::vector* exprList, bool distinct) { Expr* e = new Expr(kExprFunctionRef); e->name = func_name; - e->expr = expr; + e->exprList = exprList; e->distinct = distinct; return e; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index 9be9ed1..bd2b8d0 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -3,6 +3,7 @@ #include #include +#include namespace hsql { @@ -61,6 +62,7 @@ namespace hsql { Expr* expr; Expr* expr2; + std::vector* exprList; char* name; char* table; char* alias; @@ -107,7 +109,7 @@ namespace hsql { static Expr* makeColumnRef(char* table, char* name); - static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct); + static Expr* makeFunctionRef(char* func_name, std::vector* exprList, bool distinct); static Expr* makePlaceholder(int id); }; diff --git a/test/queries/tpc-h-02.sql b/test/queries/tpc-h-02.sql index c40be73..5fd5b50 100644 --- a/test/queries/tpc-h-02.sql +++ b/test/queries/tpc-h-02.sql @@ -1,6 +1,6 @@ -- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html SELECT TOP 100 S_ACCTBAL, S_NAME, N_NAME, P_PARTKEY, P_MFGR, S_ADDRESS, S_PHONE, S_COMMENT -FROM PART, SUPPLIER, PARTSUPP, NATION, REGION +FROM "PART", SUPPLIER, PARTSUPP, NATION, REGION WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY AND P_SIZE = 15 AND P_TYPE LIKE '%%BRASS' AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND R_NAME = 'EUROPE' AND diff --git a/test/queries/tpc-h-09.sql b/test/queries/tpc-h-09.sql index a5856e0..bb9fd6f 100644 --- a/test/queries/tpc-h-09.sql +++ b/test/queries/tpc-h-09.sql @@ -2,7 +2,7 @@ SELECT NATION, O_YEAR, SUM(AMOUNT) AS SUM_PROFIT FROM (SELECT N_NAME AS NATION, datepart(yy, O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY AS AMOUNT - FROM PART, SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION + FROM "PART", SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION WHERE S_SUPPKEY = L_SUPPKEY AND PS_SUPPKEY= L_SUPPKEY AND PS_PARTKEY = L_PARTKEY AND P_PARTKEY= L_PARTKEY AND O_ORDERKEY = L_ORDERKEY AND S_NATIONKEY = N_NATIONKEY AND P_NAME LIKE '%%green%%') AS PROFIT diff --git a/test/select_tests.cpp b/test/select_tests.cpp index dead654..62e5d55 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -20,6 +20,45 @@ TEST(SelectTest) { delete result; } +TEST(SelectExprTest) { + TEST_PARSE_SINGLE_SQL( + "SELECT a, MAX(b), CUSTOM(c, F(un)) FROM students;", + kStmtSelect, + SelectStatement, + result, + stmt); + + ASSERT_NULL(stmt->whereClause); + ASSERT_NULL(stmt->groupBy); + + ASSERT_EQ(stmt->selectList->size(), 3); + + ASSERT(stmt->selectList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(0)->getName(), "a"); + + ASSERT(stmt->selectList->at(1)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(1)->getName(), "MAX"); + ASSERT_NOTNULL(stmt->selectList->at(1)->exprList); + ASSERT_EQ(stmt->selectList->at(1)->exprList->size(), 1); + ASSERT(stmt->selectList->at(1)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(1)->exprList->at(0)->getName(), "b"); + + ASSERT(stmt->selectList->at(2)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(2)->getName(), "CUSTOM"); + ASSERT_NOTNULL(stmt->selectList->at(2)->exprList); + ASSERT_EQ(stmt->selectList->at(2)->exprList->size(), 2); + ASSERT(stmt->selectList->at(2)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(0)->getName(), "c"); + + ASSERT(stmt->selectList->at(2)->exprList->at(1)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(1)->getName(), "F"); + ASSERT_EQ(stmt->selectList->at(2)->exprList->at(1)->exprList->size(), 1); + ASSERT(stmt->selectList->at(2)->exprList->at(1)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(1)->exprList->at(0)->getName(), "un"); + + delete result; +} + TEST(SelectHavingTest) { TEST_PARSE_SINGLE_SQL( diff --git a/test/valid_queries.sql b/test/valid_queries.sql index dfece3d..cbd9584 100644 --- a/test/valid_queries.sql +++ b/test/valid_queries.sql @@ -9,6 +9,7 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1; SELECT * FROM (SELECT * FROM t1); SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; SELECT TOP 10 * FROM t1 ORDER BY col1, col2; +SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1; # JOIN SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5 SELECT * FROM t1 JOIN t2 ON c1 = c2; From 35b8b569eb61401dae38929b89b711d07fb43ff1 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 13:49:56 +0100 Subject: [PATCH 04/12] Implement BETWEEN operator --- src/parser/bison_parser.y | 50 ++++++++++++++++++++++++--------------- src/sql/Expr.cpp | 9 +++++++ src/sql/Expr.h | 7 +++++- test/select_tests.cpp | 29 +++++++++++++++++++++-- test/tpc_h_tests.cpp | 4 ++-- test/valid_queries.sql | 1 + 6 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 27c12c0..a176f40 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -195,7 +195,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type import_file_type opt_join_type column_type %type from_clause table_ref table_ref_atomic table_ref_name %type
join_clause join_table table_ref_name_no_alias -%type expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias placeholder_expr +%type expr operand scalar_expr unary_expr binary_expr logic_expr function_expr between_expr star_expr expr_alias placeholder_expr %type column_name literal int_literal num_literal string_literal %type comp_expr opt_where join_condition opt_having %type opt_limit opt_top @@ -601,6 +601,12 @@ expr_alias: ; expr: + operand + | between_expr + | logic_expr + ; + +operand: '(' expr ')' { $$ = $2; } | scalar_expr | unary_expr @@ -615,38 +621,44 @@ scalar_expr: ; unary_expr: - '-' expr { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); } - | NOT expr { $$ = Expr::makeOpUnary(Expr::NOT, $2); } + '-' operand { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); } + | NOT operand { $$ = Expr::makeOpUnary(Expr::NOT, $2); } ; binary_expr: comp_expr - | expr '-' expr { $$ = Expr::makeOpBinary($1, '-', $3); } - | expr '+' expr { $$ = Expr::makeOpBinary($1, '+', $3); } - | expr '/' expr { $$ = Expr::makeOpBinary($1, '/', $3); } - | expr '*' expr { $$ = Expr::makeOpBinary($1, '*', $3); } - | expr '%' expr { $$ = Expr::makeOpBinary($1, '%', $3); } - | expr '^' expr { $$ = Expr::makeOpBinary($1, '^', $3); } - | expr AND expr { $$ = Expr::makeOpBinary($1, Expr::AND, $3); } - | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } - | expr LIKE expr { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); } - | expr NOT LIKE expr { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); } + | operand '-' operand { $$ = Expr::makeOpBinary($1, '-', $3); } + | operand '+' operand { $$ = Expr::makeOpBinary($1, '+', $3); } + | operand '/' operand { $$ = Expr::makeOpBinary($1, '/', $3); } + | operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); } + | operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); } + | operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); } + | operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); } + | operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); } ; +logic_expr: + expr AND expr { $$ = Expr::makeOpBinary($1, Expr::AND, $3); } + | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } + ; comp_expr: - expr '=' expr { $$ = Expr::makeOpBinary($1, '=', $3); } - | expr NOTEQUALS expr { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); } - | expr '<' expr { $$ = Expr::makeOpBinary($1, '<', $3); } - | expr '>' expr { $$ = Expr::makeOpBinary($1, '>', $3); } - | expr LESSEQ expr { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); } - | expr GREATEREQ expr { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); } + operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); } + | operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); } + | operand '<' operand { $$ = Expr::makeOpBinary($1, '<', $3); } + | operand '>' operand { $$ = Expr::makeOpBinary($1, '>', $3); } + | operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); } + | operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); } ; function_expr: IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } ; +between_expr: + operand BETWEEN operand AND operand { $$ = Expr::makeBetween($1, $3, $5); } + ; + column_name: IDENTIFIER { $$ = Expr::makeColumnRef($1); } | IDENTIFIER '.' IDENTIFIER { $$ = Expr::makeColumnRef($1, $3); } diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index 9035884..cb89d67 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -47,6 +47,15 @@ namespace hsql { return e; } + Expr* Expr::makeBetween(Expr* expr, Expr* left, Expr* right) { + Expr* e = new Expr(kExprOperator); + e->expr = expr; + e->exprList = new std::vector(); + e->exprList->push_back(left); + e->exprList->push_back(right); + return e; + } + Expr* Expr::makeLiteral(int64_t val) { Expr* e = new Expr(kExprLiteralInt); e->ival = val; diff --git a/src/sql/Expr.h b/src/sql/Expr.h index bd2b8d0..eef1bf8 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -32,9 +32,11 @@ namespace hsql { // + - * / < > = % // Non-trivial are: <> <= >= LIKE ISNULL NOT enum OperatorType { - SIMPLE_OP, + // Ternary operators + BETWEEN, // Binary operators. + SIMPLE_OP, NOT_EQUALS, LESS_EQ, GREATER_EQ, @@ -60,6 +62,7 @@ namespace hsql { ExprType type; + // TODO: Replace expressions by list. Expr* expr; Expr* expr2; std::vector* exprList; @@ -99,6 +102,8 @@ namespace hsql { static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2); + static Expr* makeBetween(Expr* expr, Expr* left, Expr* right); + static Expr* makeLiteral(int64_t val); static Expr* makeLiteral(double val); diff --git a/test/select_tests.cpp b/test/select_tests.cpp index 62e5d55..c9cc78c 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -32,7 +32,7 @@ TEST(SelectExprTest) { ASSERT_NULL(stmt->groupBy); ASSERT_EQ(stmt->selectList->size(), 3); - + ASSERT(stmt->selectList->at(0)->isType(kExprColumnRef)); ASSERT_STREQ(stmt->selectList->at(0)->getName(), "a"); @@ -111,7 +111,6 @@ TEST(SelectGroupDistinctTest) { delete result; } - TEST(OrderByTest) { TEST_PARSE_SINGLE_SQL( "SELECT grade, city FROM students ORDER BY grade, city DESC;", @@ -132,3 +131,29 @@ TEST(OrderByTest) { delete result; } + +TEST(SelectBetweenTest) { + TEST_PARSE_SINGLE_SQL( + "SELECT grade, city FROM students WHERE grade BETWEEN 1 and c;", + kStmtSelect, + SelectStatement, + result, + stmt); + + + Expr* where = stmt->whereClause; + ASSERT_NOTNULL(where); + ASSERT(where->isType(kExprOperator)); + ASSERT_EQ(where->opType, Expr::BETWEEN); + + ASSERT_STREQ(where->expr->getName(), "grade"); + ASSERT(where->expr->isType(kExprColumnRef)); + + ASSERT_EQ(where->exprList->size(), 2); + ASSERT(where->exprList->at(0)->isType(kExprLiteralInt)); + ASSERT_EQ(where->exprList->at(0)->ival, 1); + ASSERT(where->exprList->at(1)->isType(kExprColumnRef)); + ASSERT_STREQ(where->exprList->at(1)->getName(), "c"); + + delete result; +} diff --git a/test/tpc_h_tests.cpp b/test/tpc_h_tests.cpp index f85f644..93c5659 100644 --- a/test/tpc_h_tests.cpp +++ b/test/tpc_h_tests.cpp @@ -28,8 +28,8 @@ TEST(TPCHQueryTests) { for (const std::string& file_path : files) { std::ifstream t(file_path.c_str()); std::string query((std::istreambuf_iterator(t)), - std::istreambuf_iterator()); - + std::istreambuf_iterator()); + SQLParserResult* result = SQLParser::parseSQLString(query.c_str()); if (!result->isValid()) { mt::printFailed(file_path.c_str()); diff --git a/test/valid_queries.sql b/test/valid_queries.sql index cbd9584..9e3d095 100644 --- a/test/valid_queries.sql +++ b/test/valid_queries.sql @@ -10,6 +10,7 @@ SELECT * FROM (SELECT * FROM t1); SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; SELECT TOP 10 * FROM t1 ORDER BY col1, col2; SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1; +SELECT * FROM t WHERE a BETWEEN 1 and c; # JOIN SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5 SELECT * FROM t1 JOIN t2 ON c1 = c2; From cf1c84d46d8e4ec786df5b8d51a81644c907072f Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 14:21:45 +0100 Subject: [PATCH 05/12] Add select statement as possible operand in expressions --- src/parser/bison_parser.y | 11 ++++++----- src/sql/Expr.cpp | 6 ++++++ src/sql/Expr.h | 8 +++++++- test/select_tests.cpp | 27 +++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index a176f40..9b180bc 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -612,6 +612,7 @@ operand: | unary_expr | binary_expr | function_expr + | '(' select_no_paren ')' { $$ = Expr::makeSelect($2); } ; scalar_expr: @@ -633,7 +634,7 @@ binary_expr: | operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); } | operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); } | operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); } - | operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); } + | operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); } | operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); } ; @@ -643,11 +644,11 @@ logic_expr: ; comp_expr: - operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); } + operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); } | operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); } - | operand '<' operand { $$ = Expr::makeOpBinary($1, '<', $3); } - | operand '>' operand { $$ = Expr::makeOpBinary($1, '>', $3); } - | operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); } + | operand '<' operand { $$ = Expr::makeOpBinary($1, '<', $3); } + | operand '>' operand { $$ = Expr::makeOpBinary($1, '>', $3); } + | operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); } | operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); } ; diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index cb89d67..9893384 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -102,6 +102,12 @@ namespace hsql { return e; } + Expr* Expr::makeSelect(SelectStatement* select) { + Expr* e = new Expr(kExprSelect); + e->select = select; + return e; + } + bool Expr::isType(ExprType e_type) { return e_type == type; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index eef1bf8..f8ef761 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -6,6 +6,7 @@ #include namespace hsql { + class SelectStatement; // Helper function used by the lexer. // TODO: move to more appropriate place. @@ -19,7 +20,8 @@ namespace hsql { kExprPlaceholder, kExprColumnRef, kExprFunctionRef, - kExprOperator + kExprOperator, + kExprSelect }; typedef struct Expr Expr; @@ -66,6 +68,7 @@ namespace hsql { Expr* expr; Expr* expr2; std::vector* exprList; + SelectStatement* select; char* name; char* table; char* alias; @@ -77,6 +80,7 @@ namespace hsql { char opChar; bool distinct; + // Convenience accessor methods. bool isType(ExprType e_type); @@ -117,6 +121,8 @@ namespace hsql { static Expr* makeFunctionRef(char* func_name, std::vector* exprList, bool distinct); static Expr* makePlaceholder(int id); + + static Expr* makeSelect(SelectStatement* select); }; // Zero initializes an Expr object and assigns it to a space in the heap diff --git a/test/select_tests.cpp b/test/select_tests.cpp index c9cc78c..9fcb0cc 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -157,3 +157,30 @@ TEST(SelectBetweenTest) { delete result; } + +TEST(SelectConditionalSelectTest) { + TEST_PARSE_SINGLE_SQL( + "SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt);", + kStmtSelect, + SelectStatement, + result, + stmt); + + Expr* where = stmt->whereClause; + ASSERT_NOTNULL(where); + ASSERT(where->isType(kExprOperator)); + ASSERT(where->isSimpleOp('=')); + + ASSERT_NOTNULL(where->expr); + ASSERT_STREQ(where->expr->getName(), "a"); + ASSERT(where->expr->isType(kExprColumnRef)); + + ASSERT_NOTNULL(where->expr2); + ASSERT(where->expr2->isType(kExprSelect)); + + SelectStatement* select2 = where->expr2->select; + ASSERT_NOTNULL(select2); + ASSERT_STREQ(select2->fromTable->getName(), "tt") + + delete result; +} From 5605dbab7e47997c2bc53f7523f600d355d2b5fa Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 14:37:05 +0100 Subject: [PATCH 06/12] implement EXISTS conditional --- src/parser/bison_parser.y | 8 +++++++- src/sql/Expr.cpp | 8 ++++++++ src/sql/Expr.h | 7 ++++++- test/select_tests.cpp | 29 +++++++++++++++++++++-------- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 9b180bc..edd8132 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -195,7 +195,8 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type import_file_type opt_join_type column_type %type
from_clause table_ref table_ref_atomic table_ref_name %type
join_clause join_table table_ref_name_no_alias -%type expr operand scalar_expr unary_expr binary_expr logic_expr function_expr between_expr star_expr expr_alias placeholder_expr +%type expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr +%type function_expr between_expr star_expr expr_alias placeholder_expr %type column_name literal int_literal num_literal string_literal %type comp_expr opt_where join_condition opt_having %type opt_limit opt_top @@ -604,6 +605,7 @@ expr: operand | between_expr | logic_expr + | exists_expr ; operand: @@ -643,6 +645,10 @@ logic_expr: | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } ; +exists_expr: + EXISTS '(' select_no_paren ')' { $$ = Expr::makeExists($3); } + ; + comp_expr: operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); } | operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); } diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index 9893384..bd2f265 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -50,6 +50,7 @@ namespace hsql { Expr* Expr::makeBetween(Expr* expr, Expr* left, Expr* right) { Expr* e = new Expr(kExprOperator); e->expr = expr; + e->opType = BETWEEN; e->exprList = new std::vector(); e->exprList->push_back(left); e->exprList->push_back(right); @@ -108,6 +109,13 @@ namespace hsql { return e; } + Expr* Expr::makeExists(SelectStatement* select) { + Expr* e = new Expr(kExprOperator); + e->opType = EXISTS; + e->select = select; + return e; + } + bool Expr::isType(ExprType e_type) { return e_type == type; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index f8ef761..d9dac70 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -34,6 +34,8 @@ namespace hsql { // + - * / < > = % // Non-trivial are: <> <= >= LIKE ISNULL NOT enum OperatorType { + NONE, + // Ternary operators BETWEEN, @@ -50,7 +52,8 @@ namespace hsql { // Unary operators. NOT, UMINUS, - ISNULL + ISNULL, + EXISTS }; @@ -123,6 +126,8 @@ namespace hsql { static Expr* makePlaceholder(int id); static Expr* makeSelect(SelectStatement* select); + + static Expr* makeExists(SelectStatement* select); }; // Zero initializes an Expr object and assigns it to a space in the heap diff --git a/test/select_tests.cpp b/test/select_tests.cpp index 9fcb0cc..f6a9e10 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -160,7 +160,7 @@ TEST(SelectBetweenTest) { TEST(SelectConditionalSelectTest) { TEST_PARSE_SINGLE_SQL( - "SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt);", + "SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt) AND EXISTS (SELECT * FROM test WHERE x < a);", kStmtSelect, SelectStatement, result, @@ -169,18 +169,31 @@ TEST(SelectConditionalSelectTest) { Expr* where = stmt->whereClause; ASSERT_NOTNULL(where); ASSERT(where->isType(kExprOperator)); - ASSERT(where->isSimpleOp('=')); + ASSERT_EQ(where->opType, Expr::AND); - ASSERT_NOTNULL(where->expr); - ASSERT_STREQ(where->expr->getName(), "a"); - ASSERT(where->expr->isType(kExprColumnRef)); + // a = (SELECT ...) + Expr* cond1 = where->expr; + ASSERT_NOTNULL(cond1); + ASSERT_NOTNULL(cond1->expr); + ASSERT(cond1->isSimpleOp('=')); + ASSERT_STREQ(cond1->expr->getName(), "a"); + ASSERT(cond1->expr->isType(kExprColumnRef)); - ASSERT_NOTNULL(where->expr2); - ASSERT(where->expr2->isType(kExprSelect)); + ASSERT_NOTNULL(cond1->expr2); + ASSERT(cond1->expr2->isType(kExprSelect)); - SelectStatement* select2 = where->expr2->select; + SelectStatement* select2 = cond1->expr2->select; ASSERT_NOTNULL(select2); ASSERT_STREQ(select2->fromTable->getName(), "tt") + + // EXISTS (SELECT ...) + Expr* cond2 = where->expr2; + ASSERT_EQ(cond2->opType, Expr::EXISTS); + ASSERT_NOTNULL(cond2->select); + + SelectStatement* ex_select = cond2->select; + ASSERT_STREQ(ex_select->fromTable->getName(), "test") + delete result; } From b7828e698e1db7a05bbf6d5e1eb04e7b7dd546de Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 14:55:51 +0100 Subject: [PATCH 07/12] implement CASE WHEN expressions --- src/parser/bison_parser.y | 19 ++++++++++++------- src/parser/flex_lexer.l | 12 +++++------- src/parser/sql_keywords.txt | 5 +++++ src/sql/Expr.cpp | 10 ++++++++++ src/sql/Expr.h | 3 +++ test/queries/tpc-h-08.sql | 2 +- test/select_tests.cpp | 30 ++++++++++++++++++++++++++++-- 7 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index edd8132..68bbedd 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -169,12 +169,11 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED %token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS %token DELTA GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER -%token OUTER RIGHT TABLE UNION USING WHERE CALL DATE DESC -%token DROP FILE FROM FULL HASH HINT INTO JOIN LEFT LIKE -%token LOAD NULL PART PLAN SHOW TEXT TIME VIEW WITH ADD ALL -%token AND ASC CSV FOR INT KEY NOT OFF SET TBL TOP AS BY IF -%token IN IS OF ON OR TO - +%token OUTER RIGHT TABLE UNION USING WHERE CALL CASE DATE +%token DESC DROP ELSE FILE FROM FULL HASH HINT INTO JOIN +%token LEFT LIKE LOAD NULL PART PLAN SHOW TEXT THEN TIME +%token VIEW WHEN WITH ADD ALL AND ASC CSV END FOR INT KEY +%token NOT OFF SET TBL TOP AS BY IF IN IS OF ON OR TO /********************************* ** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html) @@ -198,7 +197,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr %type function_expr between_expr star_expr expr_alias placeholder_expr %type column_name literal int_literal num_literal string_literal -%type comp_expr opt_where join_condition opt_having +%type comp_expr opt_where join_condition opt_having case_expr %type opt_limit opt_top %type order_desc %type opt_order_type @@ -606,6 +605,7 @@ expr: | between_expr | logic_expr | exists_expr + | case_expr ; operand: @@ -645,6 +645,11 @@ logic_expr: | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } ; +// TODO: allow no else specified +case_expr: + CASE WHEN operand THEN operand ELSE operand END { $$ = Expr::makeCase($3, $5, $7); } + ; + exists_expr: EXISTS '(' select_no_paren ')' { $$ = Expr::makeExists($3); } ; diff --git a/src/parser/flex_lexer.l b/src/parser/flex_lexer.l index 13e1054..cde49ac 100644 --- a/src/parser/flex_lexer.l +++ b/src/parser/flex_lexer.l @@ -54,11 +54,8 @@ [^\n]* /* skipping comment content until a end of line is read */; \n BEGIN(INITIAL); - [ \t\n]+ /* skip whitespace */; - - DEALLOCATE TOKEN(DEALLOCATE) PARAMETERS TOKEN(PARAMETERS) INTERSECT TOKEN(INTERSECT) @@ -127,9 +124,11 @@ UNION TOKEN(UNION) USING TOKEN(USING) WHERE TOKEN(WHERE) CALL TOKEN(CALL) +CASE TOKEN(CASE) DATE TOKEN(DATE) DESC TOKEN(DESC) DROP TOKEN(DROP) +ELSE TOKEN(ELSE) FILE TOKEN(FILE) FROM TOKEN(FROM) FULL TOKEN(FULL) @@ -145,14 +144,17 @@ PART TOKEN(PART) PLAN TOKEN(PLAN) SHOW TOKEN(SHOW) TEXT TOKEN(TEXT) +THEN TOKEN(THEN) TIME TOKEN(TIME) VIEW TOKEN(VIEW) +WHEN TOKEN(WHEN) WITH TOKEN(WITH) ADD TOKEN(ADD) ALL TOKEN(ALL) AND TOKEN(AND) ASC TOKEN(ASC) CSV TOKEN(CSV) +END TOKEN(END) FOR TOKEN(FOR) INT TOKEN(INT) KEY TOKEN(KEY) @@ -171,15 +173,12 @@ ON TOKEN(ON) OR TOKEN(OR) TO TOKEN(TO) - "<>" TOKEN(NOTEQUALS) "<=" TOKEN(LESSEQ) ">=" TOKEN(GREATEREQ) - [-+*/(){},.;<>=^%:?] { return yytext[0]; } - [0-9]+"."[0-9]* | "."[0-9]* { yylval->fval = atof(yytext); @@ -202,7 +201,6 @@ TO TOKEN(TO) return SQL_IDENTIFIER; } - '[^'\n]*' { // Crop the leading and trailing quote char yylval->sval = hsql::substr(yytext, 1, strlen(yytext)-1); diff --git a/src/parser/sql_keywords.txt b/src/parser/sql_keywords.txt index 2209fcf..092b4c2 100644 --- a/src/parser/sql_keywords.txt +++ b/src/parser/sql_keywords.txt @@ -140,6 +140,11 @@ IS ISNULL BETWEEN ESCAPE +CASE +WHEN +THEN +ELSE +END // With WITH diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index bd2f265..3557a61 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -57,6 +57,16 @@ namespace hsql { return e; } + Expr* Expr::makeCase(Expr* expr, Expr* then, Expr* other) { + Expr* e = new Expr(kExprOperator); + e->expr = expr; + e->opType = CASE; + e->exprList = new std::vector(); + e->exprList->push_back(then); + e->exprList->push_back(other); + return e; + } + Expr* Expr::makeLiteral(int64_t val) { Expr* e = new Expr(kExprLiteralInt); e->ival = val; diff --git a/src/sql/Expr.h b/src/sql/Expr.h index d9dac70..48cbdbd 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -38,6 +38,7 @@ namespace hsql { // Ternary operators BETWEEN, + CASE, // Binary operators. SIMPLE_OP, @@ -111,6 +112,8 @@ namespace hsql { static Expr* makeBetween(Expr* expr, Expr* left, Expr* right); + static Expr* makeCase(Expr* expr, Expr* then, Expr* other); + static Expr* makeLiteral(int64_t val); static Expr* makeLiteral(double val); diff --git a/test/queries/tpc-h-08.sql b/test/queries/tpc-h-08.sql index 7c0ff24..77f8c64 100644 --- a/test/queries/tpc-h-08.sql +++ b/test/queries/tpc-h-08.sql @@ -1,7 +1,7 @@ -- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html SELECT O_YEAR, SUM(CASE WHEN NATION = 'BRAZIL' THEN VOLUME ELSE 0 END)/SUM(VOLUME) AS MKT_SHARE FROM (SELECT datepart(yy,O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME, N2.N_NAME AS NATION - FROM PART, SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION + FROM "PART", SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION WHERE P_PARTKEY = L_PARTKEY AND S_SUPPKEY = L_SUPPKEY AND L_ORDERKEY = O_ORDERKEY AND O_CUSTKEY = C_CUSTKEY AND C_NATIONKEY = N1.N_NATIONKEY AND N1.N_REGIONKEY = R_REGIONKEY AND R_NAME = 'AMERICA' AND S_NATIONKEY = N2.N_NATIONKEY diff --git a/test/select_tests.cpp b/test/select_tests.cpp index f6a9e10..7a0ddd3 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -184,7 +184,7 @@ TEST(SelectConditionalSelectTest) { SelectStatement* select2 = cond1->expr2->select; ASSERT_NOTNULL(select2); - ASSERT_STREQ(select2->fromTable->getName(), "tt") + ASSERT_STREQ(select2->fromTable->getName(), "tt"); // EXISTS (SELECT ...) @@ -193,7 +193,33 @@ TEST(SelectConditionalSelectTest) { ASSERT_NOTNULL(cond2->select); SelectStatement* ex_select = cond2->select; - ASSERT_STREQ(ex_select->fromTable->getName(), "test") + ASSERT_STREQ(ex_select->fromTable->getName(), "test"); + + delete result; +} + +TEST(SelectCaseWhen) { + TEST_PARSE_SINGLE_SQL( + "SELECT MAX(CASE WHEN a = 'foo' THEN x ELSE 0 END) FROM test;", + kStmtSelect, + SelectStatement, + result, + stmt); + + ASSERT_EQ(stmt->selectList->size(), 1); + Expr* func = stmt->selectList->at(0); + + ASSERT_NOTNULL(func); + ASSERT(func->isType(kExprFunctionRef)); + ASSERT_EQ(func->exprList->size(), 1); + + Expr* caseExpr = func->exprList->at(0); + ASSERT_NOTNULL(caseExpr); + ASSERT(caseExpr->isType(kExprOperator)); + ASSERT_EQ(caseExpr->opType, Expr::CASE); + ASSERT(caseExpr->expr->isType(kExprOperator)); + ASSERT(caseExpr->expr->isSimpleOp('=')); + ASSERT_EQ(caseExpr->exprList->size(), 2); delete result; } From bf255c65acec54b6c89edb7780125f81805f4725 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 15:09:39 +0100 Subject: [PATCH 08/12] fix memory leaks --- src/parser/bison_parser.y | 21 ++++++++++++++++++--- src/sql/Expr.cpp | 11 +++++++++++ src/sql/statements.cpp | 8 +++++++- test/tpc_h_tests.cpp | 1 + 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 68bbedd..d7dafa5 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -478,7 +478,12 @@ select_no_paren: select_clause opt_order opt_limit { $$ = $1; $$->order = $2; - $$->limit = $3; + + // Limit could have been set by TOP. + if ($3 != NULL) { + delete $$->limit; + $$->limit = $3; + } } | select_clause set_operator select_clause opt_order opt_limit { // TODO: allow multiple unions (through linked list) @@ -487,13 +492,23 @@ select_no_paren: $$ = $1; $$->unionSelect = $3; $$->order = $4; - $$->limit = $5; + + // Limit could have been set by TOP. + if ($5 != NULL) { + delete $$->limit; + $$->limit = $5; + } } | select_clause set_operator select_with_paren opt_order opt_limit { $$ = $1; $$->unionSelect = $3; $$->order = $4; - $$->limit = $5; + + // Limit could have been set by TOP. + if ($5 != NULL) { + delete $$->limit; + $$->limit = $5; + } } ; diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index 3557a61..56d7eb2 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -2,6 +2,7 @@ #include "Expr.h" #include #include +#include "SelectStatement.h" namespace hsql { @@ -9,6 +10,8 @@ namespace hsql { type(type), expr(NULL), expr2(NULL), + exprList(NULL), + select(NULL), name(NULL), table(NULL), alias(NULL) {}; @@ -16,9 +19,17 @@ namespace hsql { Expr::~Expr() { delete expr; delete expr2; + delete select; free(name); free(table); free(alias); + + if (exprList != NULL) { + for (Expr* e : *exprList) { + delete e; + } + delete exprList; + } } Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) { diff --git a/src/sql/statements.cpp b/src/sql/statements.cpp index 089966d..8d9973b 100644 --- a/src/sql/statements.cpp +++ b/src/sql/statements.cpp @@ -193,7 +193,6 @@ namespace hsql { delete whereClause; delete groupBy; delete unionSelect; - delete order; delete limit; // Delete each element in the select list. @@ -203,6 +202,13 @@ namespace hsql { } delete selectList; } + + if (order != NULL) { + for (OrderDescription* desc : *order) { + delete desc; + } + delete order; + } } // UpdateStatement diff --git a/test/tpc_h_tests.cpp b/test/tpc_h_tests.cpp index 93c5659..bb65a65 100644 --- a/test/tpc_h_tests.cpp +++ b/test/tpc_h_tests.cpp @@ -38,6 +38,7 @@ TEST(TPCHQueryTests) { } else { mt::printOk(file_path.c_str()); } + delete result; } ASSERT_EQ(testsFailed, 0); } From 052f20ed1da177c947ae224f41296923d903bf92 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 15:30:54 +0100 Subject: [PATCH 09/12] add additonal TPC-H queries for testing --- test/queries/tpc-h-11-15.sql | 59 ++++++++++++++++++++++++++++++ test/queries/tpc-h-16-22.sql | 71 ++++++++++++++++++++++++++++++++++++ test/tpc_h_tests.cpp | 6 ++- 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 test/queries/tpc-h-11-15.sql create mode 100644 test/queries/tpc-h-16-22.sql diff --git a/test/queries/tpc-h-11-15.sql b/test/queries/tpc-h-11-15.sql new file mode 100644 index 0000000..9f5318d --- /dev/null +++ b/test/queries/tpc-h-11-15.sql @@ -0,0 +1,59 @@ +-- From: +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html + +-- TPC_H Query 11 - Important Stock Identification +SELECT PS_PARTKEY, SUM(PS_SUPPLYCOST*PS_AVAILQTY) AS VALUE +FROM PARTSUPP, SUPPLIER, NATION +WHERE PS_SUPPKEY = S_SUPPKEY AND S_NATIONKEY = N_NATIONKEY AND N_NAME = 'GERMANY' +GROUP BY PS_PARTKEY +HAVING SUM(PS_SUPPLYCOST*PS_AVAILQTY) > (SELECT SUM(PS_SUPPLYCOST*PS_AVAILQTY) * 0.0001000000 + FROM PARTSUPP, SUPPLIER, NATION + WHERE PS_SUPPKEY = S_SUPPKEY AND S_NATIONKEY = N_NATIONKEY AND N_NAME = 'GERMANY') +ORDER BY VALUE DESC; + + +-- TPC_H Query 12 - Shipping Modes and Order Priority +SELECT L_SHIPMODE, +SUM(CASE WHEN O_ORDERPRIORITY = '1-URGENT' OR O_ORDERPRIORITY = '2-HIGH' THEN 1 ELSE 0 END) AS HIGH_LINE_COUNT, +SUM(CASE WHEN O_ORDERPRIORITY <> '1-URGENT' AND O_ORDERPRIORITY <> '2-HIGH' THEN 1 ELSE 0 END ) AS LOW_LINE_COUNT +FROM ORDERS, LINEITEM +WHERE O_ORDERKEY = L_ORDERKEY AND L_SHIPMODE IN ('MAIL','SHIP') +AND L_COMMITDATE < L_RECEIPTDATE AND L_SHIPDATE < L_COMMITDATE AND L_RECEIPTDATE >= '1994-01-01' +AND L_RECEIPTDATE < dateadd(mm, 1, cast('1995-09-01' as datetime)) +GROUP BY L_SHIPMODE +ORDER BY L_SHIPMODE; + + +-- TPC_H Query 13 - Customer Distribution +SELECT C_COUNT, COUNT(*) AS CUSTDIST +FROM (SELECT C_CUSTKEY, COUNT(O_ORDERKEY) + FROM CUSTOMER left outer join ORDERS on C_CUSTKEY = O_CUSTKEY + AND O_COMMENT not like '%%special%%requests%%' + GROUP BY C_CUSTKEY) AS C_ORDERS +GROUP BY C_COUNT +ORDER BY CUSTDIST DESC, C_COUNT DESC; + + +-- TPC_H Query 14 - Promotion Effect +SELECT 100.00* SUM(CASE WHEN P_TYPE LIKE 'PROMO%%' THEN L_EXTENDEDPRICE*(1-L_DISCOUNT) +ELSE 0 END) / SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS PROMO_REVENUE +FROM LINEITEM, "PART" +WHERE L_PARTKEY = P_PARTKEY AND L_SHIPDATE >= '1995-09-01' AND L_SHIPDATE < dateadd(mm, 1, '1995-09-01'); + + +-- TPC_H Query 15.1 - Create View for Top Supplier Query +-- CREATE VIEW REVENUE0 (SUPPLIER_NO, TOTAL_REVENUE) AS +-- SELECT L_SUPPKEY, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) FROM LINEITEM +-- WHERE L_SHIPDATE >= '1996-01-01' AND L_SHIPDATE < dateadd(mm, 3, cast('1996-01-01' as datetime)) +-- GROUP BY L_SUPPKEY; + + +-- TPC_H Query 15.2 - Top Supplier +SELECT S_SUPPKEY, S_NAME, S_ADDRESS, S_PHONE, TOTAL_REVENUE +FROM SUPPLIER, REVENUE0 +WHERE S_SUPPKEY = SUPPLIER_NO AND TOTAL_REVENUE = (SELECT MAX(TOTAL_REVENUE) FROM REVENUE0) +ORDER BY S_SUPPKEY; + +-- TPC_H Query 15.3 - Drop View +-- DROP VIEW REVENUE0; + diff --git a/test/queries/tpc-h-16-22.sql b/test/queries/tpc-h-16-22.sql new file mode 100644 index 0000000..dd5f4cd --- /dev/null +++ b/test/queries/tpc-h-16-22.sql @@ -0,0 +1,71 @@ +-- From: +-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html + +-- TPC_H Query 16 - Parts/Supplier Relationship +SELECT P_BRAND, P_TYPE, P_SIZE, COUNT(DISTINCT PS_SUPPKEY) AS SUPPLIER_CNT +FROM PARTSUPP, "PART" +WHERE P_PARTKEY = PS_PARTKEY AND P_BRAND <> 'Brand#45' AND P_TYPE NOT LIKE 'MEDIUM POLISHED%%' +AND P_SIZE IN (49, 14, 23, 45, 19, 3, 36, 9) AND PS_SUPPKEY NOT IN (SELECT S_SUPPKEY FROM SUPPLIER + WHERE S_COMMENT LIKE '%%Customer%%Complaints%%') +GROUP BY P_BRAND, P_TYPE, P_SIZE +ORDER BY SUPPLIER_CNT DESC, P_BRAND, P_TYPE, P_SIZE; + + +-- TPC_H Query 17 - Small-Quantity-Order Revenue +SELECT SUM(L_EXTENDEDPRICE)/7.0 AS AVG_YEARLY FROM LINEITEM, "PART" +WHERE P_PARTKEY = L_PARTKEY AND P_BRAND = 'Brand#23' AND P_CONTAINER = 'MED BOX' +AND L_QUANTITY < (SELECT 0.2*AVG(L_QUANTITY) FROM LINEITEM WHERE L_PARTKEY = P_PARTKEY); + + +-- TPC_H Query 18 - Large Volume Customer +SELECT TOP 100 C_NAME, C_CUSTKEY, O_ORDERKEY, O_ORDERDATE, O_TOTALPRICE, SUM(L_QUANTITY) +FROM CUSTOMER, ORDERS, LINEITEM +WHERE O_ORDERKEY IN (SELECT L_ORDERKEY FROM LINEITEM GROUP BY L_ORDERKEY HAVING + SUM(L_QUANTITY) > 300) AND C_CUSTKEY = O_CUSTKEY AND O_ORDERKEY = L_ORDERKEY +GROUP BY C_NAME, C_CUSTKEY, O_ORDERKEY, O_ORDERDATE, O_TOTALPRICE +ORDER BY O_TOTALPRICE DESC, O_ORDERDATE; + + +-- TPC_H Query 19 - Discounted Revenue +SELECT SUM(L_EXTENDEDPRICE* (1 - L_DISCOUNT)) AS REVENUE +FROM LINEITEM, "PART" +WHERE (P_PARTKEY = L_PARTKEY AND P_BRAND = 'Brand#12' AND P_CONTAINER IN ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') AND L_QUANTITY >= 1 AND L_QUANTITY <= 1 + 10 AND P_SIZE BETWEEN 1 AND 5 +AND L_SHIPMODE IN ('AIR', 'AIR REG') AND L_SHIPINSTRUCT = 'DELIVER IN PERSON') +OR (P_PARTKEY = L_PARTKEY AND P_BRAND ='Brand#23' AND P_CONTAINER IN ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') AND L_QUANTITY >=10 AND L_QUANTITY <=10 + 10 AND P_SIZE BETWEEN 1 AND 10 +AND L_SHIPMODE IN ('AIR', 'AIR REG') AND L_SHIPINSTRUCT = 'DELIVER IN PERSON') +OR (P_PARTKEY = L_PARTKEY AND P_BRAND = 'Brand#34' AND P_CONTAINER IN ( 'LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') AND L_QUANTITY >=20 AND L_QUANTITY <= 20 + 10 AND P_SIZE BETWEEN 1 AND 15 +AND L_SHIPMODE IN ('AIR', 'AIR REG') AND L_SHIPINSTRUCT = 'DELIVER IN PERSON'); + + +-- TPC_H Query 20 - Potential Part Promotion +SELECT S_NAME, S_ADDRESS FROM SUPPLIER, NATION +WHERE S_SUPPKEY IN (SELECT PS_SUPPKEY FROM PARTSUPP + WHERE PS_PARTKEY in (SELECT P_PARTKEY FROM "PART" WHERE P_NAME like 'forest%%') AND + PS_AVAILQTY > (SELECT 0.5*sum(L_QUANTITY) FROM LINEITEM WHERE L_PARTKEY = PS_PARTKEY AND + L_SUPPKEY = PS_SUPPKEY AND L_SHIPDATE >= '1994-01-01' AND + L_SHIPDATE < dateadd(yy,1,'1994-01-01'))) AND S_NATIONKEY = N_NATIONKEY AND N_NAME = 'CANADA' +ORDER BY S_NAME; + + +-- TPC_H Query 21 - Suppliers Who Kept Orders Waiting +SELECT TOP 100 S_NAME, COUNT(*) AS NUMWAIT +FROM SUPPLIER, LINEITEM L1, ORDERS, NATION WHERE S_SUPPKEY = L1.L_SUPPKEY AND +O_ORDERKEY = L1.L_ORDERKEY AND O_ORDERSTATUS = 'F' AND L1.L_RECEIPTDATE> L1.L_COMMITDATE +AND EXISTS (SELECT * FROM LINEITEM L2 WHERE L2.L_ORDERKEY = L1.L_ORDERKEY + AND L2.L_SUPPKEY <> L1.L_SUPPKEY) AND +NOT EXISTS (SELECT * FROM LINEITEM L3 WHERE L3.L_ORDERKEY = L1.L_ORDERKEY AND + L3.L_SUPPKEY <> L1.L_SUPPKEY AND L3.L_RECEIPTDATE > L3.L_COMMITDATE) AND +S_NATIONKEY = N_NATIONKEY AND N_NAME = 'SAUDI ARABIA' +GROUP BY S_NAME +ORDER BY NUMWAIT DESC, S_NAME; + + +-- TPC_H Query 22 - Global Sales Opportunity */ +SELECT CNTRYCODE, COUNT(*) AS NUMCUST, SUM(C_ACCTBAL) AS TOTACCTBAL +FROM (SELECT SUBSTRING(C_PHONE,1,2) AS CNTRYCODE, C_ACCTBAL + FROM CUSTOMER WHERE SUBSTRING(C_PHONE,1,2) IN ('13', '31', '23', '29', '30', '18', '17') AND + C_ACCTBAL > (SELECT AVG(C_ACCTBAL) FROM CUSTOMER WHERE C_ACCTBAL > 0.00 AND + SUBSTRING(C_PHONE,1,2) IN ('13', '31', '23', '29', '30', '18', '17')) AND + NOT EXISTS ( SELECT * FROM ORDERS WHERE O_CUSTKEY = C_CUSTKEY)) AS CUSTSALE +GROUP BY CNTRYCODE +ORDER BY CNTRYCODE; \ No newline at end of file diff --git a/test/tpc_h_tests.cpp b/test/tpc_h_tests.cpp index bb65a65..614d18f 100644 --- a/test/tpc_h_tests.cpp +++ b/test/tpc_h_tests.cpp @@ -10,7 +10,7 @@ using namespace hsql; -TEST(TPCHQueryTests) { +TEST(TPCHQueryGrammarTests) { std::vector files = { "test/queries/tpc-h-01.sql", "test/queries/tpc-h-02.sql", @@ -21,7 +21,9 @@ TEST(TPCHQueryTests) { "test/queries/tpc-h-07.sql", "test/queries/tpc-h-08.sql", "test/queries/tpc-h-09.sql", - "test/queries/tpc-h-10.sql" + "test/queries/tpc-h-10.sql", + "test/queries/tpc-h-11-15.sql", + "test/queries/tpc-h-16-22.sql" }; int testsFailed = 0; From b4adfa5b7468ad3e9b993f704ff083d927cf9dce Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 15:44:44 +0100 Subject: [PATCH 10/12] implement IN operator --- src/parser/bison_parser.y | 26 +++++++++++++++++--------- src/sql/Expr.cpp | 34 ++++++++++++++++++++++++++++++++++ src/sql/Expr.h | 5 +++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index d7dafa5..e98a4ef 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -197,7 +197,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch %type expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr %type function_expr between_expr star_expr expr_alias placeholder_expr %type column_name literal int_literal num_literal string_literal -%type comp_expr opt_where join_condition opt_having case_expr +%type comp_expr opt_where join_condition opt_having case_expr in_expr %type opt_limit opt_top %type order_desc %type opt_order_type @@ -621,6 +621,7 @@ expr: | logic_expr | exists_expr | case_expr + | in_expr ; operand: @@ -645,12 +646,12 @@ unary_expr: binary_expr: comp_expr - | operand '-' operand { $$ = Expr::makeOpBinary($1, '-', $3); } - | operand '+' operand { $$ = Expr::makeOpBinary($1, '+', $3); } - | operand '/' operand { $$ = Expr::makeOpBinary($1, '/', $3); } - | operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); } - | operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); } - | operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); } + | operand '-' operand { $$ = Expr::makeOpBinary($1, '-', $3); } + | operand '+' operand { $$ = Expr::makeOpBinary($1, '+', $3); } + | operand '/' operand { $$ = Expr::makeOpBinary($1, '/', $3); } + | operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); } + | operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); } + | operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); } | operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); } | operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); } ; @@ -660,9 +661,17 @@ logic_expr: | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } ; +// TODO: +in_expr: + operand IN '(' expr_list ')' { $$ = Expr::makeInOperator($1, $4, false); } + | operand NOT IN '(' expr_list ')' { $$ = Expr::makeInOperator($1, $5, true); } + | operand IN '(' select_no_paren ')' { $$ = Expr::makeInOperator($1, $4, false); } + | operand NOT IN '(' select_no_paren ')' { $$ = Expr::makeInOperator($1, $5, true); } + ; + // TODO: allow no else specified case_expr: - CASE WHEN operand THEN operand ELSE operand END { $$ = Expr::makeCase($3, $5, $7); } + CASE WHEN expr THEN operand ELSE operand END { $$ = Expr::makeCase($3, $5, $7); } ; exists_expr: @@ -715,7 +724,6 @@ star_expr: '*' { $$ = new Expr(kExprStar); } ; - placeholder_expr: '?' { $$ = Expr::makePlaceholder(yylloc.total_column); diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index 56d7eb2..2deb8c6 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -137,6 +137,40 @@ namespace hsql { return e; } + Expr* Expr::makeInOperator(Expr* expr, std::vector* exprList, bool notIn) { + Expr* e = new Expr(kExprOperator); + e->opType = IN; + e->expr = expr; + e->exprList = exprList; + + // If it is NOT IN, wrap the IN in a NOT operator. + if (notIn) { + Expr* neg = new Expr(kExprOperator); + neg->opType = NOT; + neg->expr = e; + return neg; + } + + return e; + } + + Expr* Expr::makeInOperator(Expr* expr, SelectStatement* select, bool notIn) { + Expr* e = new Expr(kExprOperator); + e->opType = IN; + e->expr = expr; + e->select = select; + + // If it is NOT IN, wrap the IN in a NOT operator. + if (notIn) { + Expr* neg = new Expr(kExprOperator); + neg->opType = NOT; + neg->expr = e; + return neg; + } + + return e; + } + bool Expr::isType(ExprType e_type) { return e_type == type; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index 48cbdbd..4bbd435 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -49,6 +49,7 @@ namespace hsql { NOT_LIKE, AND, OR, + IN, // Unary operators. NOT, @@ -131,6 +132,10 @@ namespace hsql { static Expr* makeSelect(SelectStatement* select); static Expr* makeExists(SelectStatement* select); + + static Expr* makeInOperator(Expr* expr, std::vector* exprList, bool notIn); + + static Expr* makeInOperator(Expr* expr, SelectStatement* select, bool notIn); }; // Zero initializes an Expr object and assigns it to a space in the heap From 177901816fbc6391531b80724b4fd806ba66361d Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 15:49:49 +0100 Subject: [PATCH 11/12] add more join types --- src/parser/bison_parser.y | 14 +++++++++----- src/sql/Table.h | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index e98a4ef..08ebaf9 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -815,11 +815,15 @@ join_clause: ; opt_join_type: - INNER { $$ = kJoinInner; } - | OUTER { $$ = kJoinOuter; } - | LEFT { $$ = kJoinLeft; } - | RIGHT { $$ = kJoinRight; } - | /* empty, default */ { $$ = kJoinInner; } + INNER { $$ = kJoinInner; } + | OUTER { $$ = kJoinOuter; } + | LEFT OUTER { $$ = kJoinLeftOuter; } + | RIGHT OUTER { $$ = kJoinRightOuter; } + | LEFT { $$ = kJoinLeft; } + | RIGHT { $$ = kJoinRight; } + | CROSS { $$ = kJoinCross; } + | NATURAL { $$ = kJoinNatural; } + | /* empty, default */ { $$ = kJoinInner; } ; diff --git a/src/sql/Table.h b/src/sql/Table.h index 83e1cb1..58ecca4 100644 --- a/src/sql/Table.h +++ b/src/sql/Table.h @@ -47,6 +47,10 @@ namespace hsql { kJoinOuter, kJoinLeft, kJoinRight, + kJoinLeftOuter, + kJoinRightOuter, + kJoinCross, + kJoinNatural }; // Definition of a join construct. From a0e55035fd7cf87ff7850b3f7fc06f30df3e3c33 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 15:53:22 +0100 Subject: [PATCH 12/12] Implement NOT EXISTS --- src/parser/bison_parser.y | 10 +++++----- src/sql/Expr.cpp | 22 +++------------------- src/sql/Expr.h | 4 ++-- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 08ebaf9..2e32ca4 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -661,12 +661,11 @@ logic_expr: | expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); } ; -// TODO: in_expr: - operand IN '(' expr_list ')' { $$ = Expr::makeInOperator($1, $4, false); } - | operand NOT IN '(' expr_list ')' { $$ = Expr::makeInOperator($1, $5, true); } - | operand IN '(' select_no_paren ')' { $$ = Expr::makeInOperator($1, $4, false); } - | operand NOT IN '(' select_no_paren ')' { $$ = Expr::makeInOperator($1, $5, true); } + operand IN '(' expr_list ')' { $$ = Expr::makeInOperator($1, $4); } + | operand NOT IN '(' expr_list ')' { $$ = Expr::makeOpUnary(Expr::NOT, Expr::makeInOperator($1, $5)); } + | operand IN '(' select_no_paren ')' { $$ = Expr::makeInOperator($1, $4); } + | operand NOT IN '(' select_no_paren ')' { $$ = Expr::makeOpUnary(Expr::NOT, Expr::makeInOperator($1, $5)); } ; // TODO: allow no else specified @@ -676,6 +675,7 @@ case_expr: exists_expr: EXISTS '(' select_no_paren ')' { $$ = Expr::makeExists($3); } + | NOT EXISTS '(' select_no_paren ')' { $$ = Expr::makeOpUnary(Expr::NOT, Expr::makeExists($4)); } ; comp_expr: diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index 2deb8c6..a4d4c80 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -137,37 +137,21 @@ namespace hsql { return e; } - Expr* Expr::makeInOperator(Expr* expr, std::vector* exprList, bool notIn) { + Expr* Expr::makeInOperator(Expr* expr, std::vector* exprList) { Expr* e = new Expr(kExprOperator); e->opType = IN; e->expr = expr; e->exprList = exprList; - // If it is NOT IN, wrap the IN in a NOT operator. - if (notIn) { - Expr* neg = new Expr(kExprOperator); - neg->opType = NOT; - neg->expr = e; - return neg; - } - return e; } - Expr* Expr::makeInOperator(Expr* expr, SelectStatement* select, bool notIn) { + Expr* Expr::makeInOperator(Expr* expr, SelectStatement* select) { Expr* e = new Expr(kExprOperator); e->opType = IN; e->expr = expr; e->select = select; - - // If it is NOT IN, wrap the IN in a NOT operator. - if (notIn) { - Expr* neg = new Expr(kExprOperator); - neg->opType = NOT; - neg->expr = e; - return neg; - } - + return e; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index 4bbd435..3284802 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -133,9 +133,9 @@ namespace hsql { static Expr* makeExists(SelectStatement* select); - static Expr* makeInOperator(Expr* expr, std::vector* exprList, bool notIn); + static Expr* makeInOperator(Expr* expr, std::vector* exprList); - static Expr* makeInOperator(Expr* expr, SelectStatement* select, bool notIn); + static Expr* makeInOperator(Expr* expr, SelectStatement* select); }; // Zero initializes an Expr object and assigns it to a space in the heap