diff options
Diffstat (limited to 'src/s3select/test/s3select_test.cpp')
-rw-r--r-- | src/s3select/test/s3select_test.cpp | 3446 |
1 files changed, 3446 insertions, 0 deletions
diff --git a/src/s3select/test/s3select_test.cpp b/src/s3select/test/s3select_test.cpp new file mode 100644 index 000000000..7c372551c --- /dev/null +++ b/src/s3select/test/s3select_test.cpp @@ -0,0 +1,3446 @@ +#include "s3select_test.h" + +TEST(TestS3SElect, s3select_vs_C) +{ +//purpose: validate correct processing of arithmetical expression, it is done by running the same expression +// in C program. +// the test validate that syntax and execution-tree (including precedence rules) are done correctly + + for(int y=0; y<10; y++) + { + gen_expr g; + std::string exp = g.generate(); + std::string c_result = run_expression_in_C_prog( exp.c_str() ); + + char* err=0; + double c_dbl_res = strtod(c_result.c_str(), &err); + + std::string input_query = "select " + exp + " from stdin;" ; + std::string s3select_res = run_s3select(input_query); + + double s3select_dbl_res = strtod(s3select_res.c_str(), &err); + + //std::cout << exp << " " << s3select_dbl_res << " " << s3select_res << " " << c_dbl_res/s3select_dbl_res << std::endl; + //std::cout << exp << std::endl; + + ASSERT_EQ(c_dbl_res, s3select_dbl_res); + } +} + +TEST(TestS3SElect, ParseQuery) +{ + //TODO syntax issues ? + //TODO error messeges ? + + s3select s3select_syntax; + + run_s3select(std::string("select (1+1) from stdin;")); + + ASSERT_EQ(0, 0); +} + +TEST(TestS3SElect, int_compare_operator) +{ + value a10(10), b11(11), c10(10); + + ASSERT_EQ( a10 < b11, true ); + ASSERT_EQ( a10 > b11, false ); + ASSERT_EQ( a10 >= c10, true ); + ASSERT_EQ( a10 <= c10, true ); + ASSERT_EQ( a10 != b11, true ); + ASSERT_EQ( a10 == b11, false ); + ASSERT_EQ( a10 == c10, true ); +} + +TEST(TestS3SElect, float_compare_operator) +{ + value a10(10.1), b11(11.2), c10(10.1); + + ASSERT_EQ( a10 < b11, true ); + ASSERT_EQ( a10 > b11, false ); + ASSERT_EQ( a10 >= c10, true ); + ASSERT_EQ( a10 <= c10, true ); + ASSERT_EQ( a10 != b11, true ); + ASSERT_EQ( a10 == b11, false ); + ASSERT_EQ( a10 == c10, true ); + +} + +TEST(TestS3SElect, string_compare_operator) +{ + value s1("abc"), s2("def"), s3("abc"); + + ASSERT_EQ( s1 < s2, true ); + ASSERT_EQ( s1 > s2, false ); + ASSERT_EQ( s1 <= s3, true ); + ASSERT_EQ( s1 >= s3, true ); + ASSERT_EQ( s1 != s2, true ); + ASSERT_EQ( s1 == s3, true ); + ASSERT_EQ( s1 == s2, false ); +} + +TEST(TestS3SElect, arithmetic_operator) +{ + value a(1), b(2), c(3), d(4); + + ASSERT_EQ( (a+b).i64(), 3 ); + + ASSERT_EQ( (value(0)-value(2)*value(4)).i64(), -8 ); + ASSERT_EQ( (value(1.23)-value(0.1)*value(2)).dbl(), 1.03 ); + + a=int64_t(1); //a+b modify a + ASSERT_EQ( ( (a+b) * (c+d) ).i64(), 21 ); +} + +TEST(TestS3SElect, intnan_compare_operator) +{ + value a10(10), b11(11), c10(10), d, e; + d.set_nan(); + e.set_nan(); + ASSERT_EQ( d > b11, false ); + ASSERT_EQ( d >= c10, false ); + ASSERT_EQ( d < a10, false ); + ASSERT_EQ( d <= b11, false ); + ASSERT_EQ( d != a10, true ); + ASSERT_EQ( d != e, true ); + ASSERT_EQ( d == a10, false ); +} + +TEST(TestS3SElect, floatnan_compare_operator) +{ + value a10(10.1), b11(11.2), c10(10.1), d, e; + d.set_nan(); + e.set_nan(); + ASSERT_EQ( d > b11, false ); + ASSERT_EQ( d >= c10, false ); + ASSERT_EQ( d < a10, false ); + ASSERT_EQ( d <= b11, false ); + ASSERT_EQ( d != a10, true ); + ASSERT_EQ( d != e, true ); + ASSERT_EQ( d == a10, false ); +} + +TEST(TestS3SElect, null_arithmetic_operator) +{ + const char *cnull = "null"; + value a(7), d, e(0); + d.setnull(); + + ASSERT_EQ(*(a - d).to_string(), *cnull ); + ASSERT_EQ(*(a * d).to_string(), *cnull ); + ASSERT_EQ(*(a / d).to_string(), *cnull ); + ASSERT_EQ(*(a / e).to_string(), *cnull ); + ASSERT_EQ(*(d + a).to_string(), *cnull ); + ASSERT_EQ(*(d - a).to_string(), *cnull ); + ASSERT_EQ(*(d * a).to_string(), *cnull ); + ASSERT_EQ(*(d / a).to_string(), *cnull ); + ASSERT_EQ(*(e / a).to_string(), *cnull ); +} + +TEST(TestS3SElect, nan_arithmetic_operator) +{ + value a(7), d, y(0); + d.set_nan(); + float b = ((a + d).dbl() ); + float c = ((a - d).dbl() ); + float v = ((a * d).dbl() ); + float w = ((a / d).dbl() ); + float x = ((d / y).dbl() ); + float r = ((d + a).dbl() ); + float z = ((d - a).dbl() ); + float u = ((d * a).dbl() ); + float t = ((d / a).dbl() ); + EXPECT_FALSE(b <= b); + EXPECT_FALSE(c <= c); + EXPECT_FALSE(v <= v); + EXPECT_FALSE(w <= w); + EXPECT_FALSE(x <= x); + EXPECT_FALSE(r <= r); + EXPECT_FALSE(z <= z); + EXPECT_FALSE(u <= u); + EXPECT_FALSE(t <= t); +} + +TEST(TestS3selectFunctions, to_timestamp) +{ + std::string timestamp = "2007T"; + std::string out_timestamp = "2007-01-01T00:00:00+00:00"; + std::string input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T"; + out_timestamp = "2007-09-17T00:00:00+00:00"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56Z"; + out_timestamp = "2007-09-17T17:56:00Z"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56:05Z"; + out_timestamp = "2007-09-17T17:56:05Z"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56:05.234Z"; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + out_timestamp = "2007-09-17T17:56:05.234000000Z"; + #else + out_timestamp = "2007-09-17T17:56:05.234000Z"; + #endif + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56+12:08"; + out_timestamp = "2007-09-17T17:56:00+12:08"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56:05-05:30"; + out_timestamp = "2007-09-17T17:56:05-05:30"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56:05.234+02:44"; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + out_timestamp = "2007-09-17T17:56:05.234000000+02:44"; + #else + out_timestamp = "2007-09-17T17:56:05.234000+02:44"; + #endif + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + timestamp = "2007-09-17T17:56:05.00234+02:44"; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + out_timestamp = "2007-09-17T17:56:05.002340000+02:44"; + #else + out_timestamp = "2007-09-17T17:56:05.002340+02:44"; + #endif + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + timestamp = "2007-09-17T17:56:05.012345678-00:45"; + out_timestamp = "2007-09-17T17:56:05.012345678-00:45"; + input_query = "select to_timestamp(\'" + timestamp + "\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, out_timestamp); + #endif + +} + +TEST(TestS3selectFunctions, date_diff) +{ + std::string input_query = "select date_diff(year, to_timestamp(\'2009-09-17T17:56:06.234Z\'), to_timestamp(\'2007-09-17T19:30:05.234Z\')) from stdin;" ; + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-1"); + + input_query = "select date_diff(month, to_timestamp(\'2009-09-17T17:56:06.234Z\'), to_timestamp(\'2007-09-17T19:30:05.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-23"); + + input_query = "select date_diff(day, to_timestamp(\'2009-09-17T17:56:06.234Z\'), to_timestamp(\'2007-09-17T19:30:05.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-730"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234Z\'), to_timestamp(\'2009-09-17T19:30:05.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "17545"); + + input_query = "select date_diff(hour, to_timestamp(\'2009-09-17T19:30:05.234Z\'), to_timestamp(\'2007-09-17T17:56:06.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-17545"); + + input_query = "select date_diff(minute, to_timestamp(\'2007-09-17T17:56:06.234Z\'), to_timestamp(\'2009-09-17T19:30:05.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "1052733"); + + input_query = "select date_diff(minute, to_timestamp(\'2009-09-17T19:30:05.234Z\'), to_timestamp(\'2007-09-17T17:56:06.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-1052733"); + + input_query = "select date_diff(second, to_timestamp(\'2009-09-17T17:56:06.234Z\'), to_timestamp(\'2009-09-17T19:30:05.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "5639"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234-03:45\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-17"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234+03:45\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-9"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234Z\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-13"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234+14:00\'), to_timestamp(\'2007-09-17T17:56:06.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "14"); + + input_query = "select date_diff(minute, to_timestamp(\'2007-09-17T17:56:06.234-03:45\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-1035"); + + input_query = "select date_diff(minute, to_timestamp(\'2007-09-17T17:56:06.234+03:45\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-585"); + + input_query = "select date_diff(minute, to_timestamp(\'2007-09-17T17:56:06.234Z\'), to_timestamp(\'2007-09-17T17:56:06.234+13:30\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-810"); + + input_query = "select date_diff(minute, to_timestamp(\'2007-09-17T17:56:06.234+14:00\'), to_timestamp(\'2007-09-17T17:56:06.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "840"); + + input_query = "select date_diff(hour, to_timestamp(\'2007-09-17T17:56:06.234+14:00\'), to_timestamp(\'2007-09-17T03:56:06.234Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "0"); +} + +TEST(TestS3selectFunctions, date_add) +{ + std::string input_query = "select date_add(year, 2, to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + std::string expected_res = "2011-09-17T17:56:06.234567000Z"; + #else + std::string expected_res = "2011-09-17T17:56:06.234567Z"; + #endif + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -5, to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2009-04-17T17:56:06.234567000Z"; + #else + expected_res = "2009-04-17T17:56:06.234567Z"; + #endif + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(day, 3, to_timestamp(\'2009-09-17T17:56:06.234567-09:15\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2009-09-20T17:56:06.234567000-09:15"; + #else + expected_res = "2009-09-20T17:56:06.234567-09:15"; + #endif + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(hour, 1, to_timestamp(\'2007-09-17T17:56:06.234567Z\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2007-09-17T18:56:06.234567000Z"; + #else + expected_res = "2007-09-17T18:56:06.234567Z"; + #endif + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(minute, 14, to_timestamp(\'2007-09-17T17:56:06.234567+11:00\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2007-09-17T18:10:06.234567000+11:00"; + #else + expected_res = "2007-09-17T18:10:06.234567+11:00"; + #endif + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(second, -26, to_timestamp(\'2009-09-17T17:56:06.234567-00:30\')) from stdin;" ; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2009-09-17T17:55:40.234567000-00:30"; + #else + expected_res = "2009-09-17T17:55:40.234567-00:30"; + #endif + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, 1,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2007-10-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, 3,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2007-12-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, 4,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2008-01-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, 15,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2008-12-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -1,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2007-08-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -8,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2007-01-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -9,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2006-12-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -10,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2006-11-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select date_add(month, -15,to_timestamp(\'2007-09-17T17:57:06Z\')) from stdin;" ; + expected_res = "2006-06-17T17:57:06Z"; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); +} + +TEST(TestS3selectFunctions, extract) +{ + std::string input_query = "select extract(year from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "2009"); + + input_query = "select extract(month from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "9"); + + input_query = "select extract(day from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "17"); + + input_query = "select extract(week from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "38"); + + input_query = "select extract(hour from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "17"); + + input_query = "select extract(minute from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "56"); + + input_query = "select extract(second from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "6"); + + input_query = "select extract(timezone_hour from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "0"); + + input_query = "select extract(timezone_hour from to_timestamp(\'2009-09-17T17:56:06.234567-07:45\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-7"); + + input_query = "select extract(timezone_hour from to_timestamp(\'2009-09-17T17:56:06.234567+07:45\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "7"); + + input_query = "select extract(timezone_minute from to_timestamp(\'2009-09-17T17:56:06.234567Z\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "0"); + + input_query = "select extract(timezone_minute from to_timestamp(\'2009-09-17T17:56:06.234567-07:45\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-45"); + + input_query = "select extract(timezone_minute from to_timestamp(\'2009-09-17T17:56:06.234567+07:45\')) from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "45"); +} + +TEST(TestS3selectFunctions, to_string) +{ + std::string input_query = "select to_string(to_timestamp(\'2009-09-17T17:56:06.234567Z\'), \'yyyyMMdd-H:m:s\') from stdin;" ; + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "20090917-17:56:6"); + + input_query = "select to_string(to_timestamp(\'2009-03-17T17:56:06.234567Z\'), \'yydaMMMM h m s.n\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "0917PMMarch 5 56 6.234567000"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06.234567Z\'), \'yyyyyy yyyy yyy yy y MMMMM MMMM MMM MM M dd dTHH H hh h : mm m ss s SSSSSSSSSS SSSSSS SSS SS S n - a X XX XXX XXXX XXXXX x xx xxx xxxx xxxxx\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "002009 2009 2009 09 2009 M March Mar 03 3 07 7T01 1 01 1 : 08 8 06 6 2345670000 234567 234 23 2 234567000 - AM Z Z Z Z Z +00 +0000 +00:00 +0000 +00:00"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06.234567-04:25\'), \'X XX XXX XXXX XXXXX x xx xxx xxxx xxxxx\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "-0425 -0425 -04:25 -0425 -04:25 -0425 -0425 -04:25 -0425 -04:25"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06.234567+12:05\'), \'X XX XXX XXXX XXXXX x xx xxx xxxx xxxxx\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "+1205 +1205 +12:05 +1205 +12:05 +1205 +1205 +12:05 +1205 +12:05"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06.2345+00:00\'), \'n SSS SSSSSS SSSSSSSSS SSSSSSSSSSS\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "234500000 234 234500 234500000 23450000000"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06.002345Z\'), \'n SSS SSSSSS SSSSSSSSS SSSSSSSSSSS\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "2345000 002 002345 002345000 00234500000"); + + input_query = "select to_string(to_timestamp(\'2009-03-07T01:08:06Z\'), \'n SSS SSSSSS SSSSSSSSS SSSSSSSSSSS\') from stdin;" ; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, "0 000 000000 000000000 00000000000"); +} + +TEST(TestS3selectFunctions, utcnow) +{ + const boost::posix_time::ptime now(boost::posix_time::second_clock::universal_time()); + const std::string input_query = "select utcnow() from stdin;" ; + auto s3select_res = run_s3select(input_query); + const boost::posix_time::ptime res_now; + ASSERT_EQ(s3select_res, boost::posix_time::to_iso_extended_string(now) + "+00:00"); +} + +TEST(TestS3selectFunctions, add) +{ + const std::string input_query = "select add(-5, 0.5) from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("-4.5")); +} + +void generate_fix_columns_csv(std::string& out, size_t size) { + std::stringstream ss; + for (auto i = 0U; i < size; ++i) { + ss << 1 << "," << 2 << "," << 3 << "," << 4 << "," << 5 << std::endl; + } + out = ss.str(); +} + +void generate_rand_csv(std::string& out, size_t size) { + // schema is: int, float, string, string + std::stringstream ss; + for (auto i = 0U; i < size; ++i) { + ss << rand()%1000 << "," << rand()%1000 << "," << rand()%1000 << "," << "foo"+std::to_string(i) << "," << std::to_string(i)+"bar" << std::endl; + } + out = ss.str(); +} + +void generate_csv(std::string& out, size_t size) { + // schema is: int, float, string, string + std::stringstream ss; + for (auto i = 0U; i < size; ++i) { + ss << i << "," << i/10.0 << "," << "foo"+std::to_string(i) << "," << std::to_string(i)+"bar" << std::endl; + } + out = ss.str(); +} + +void generate_csv_escape(std::string& out, size_t size) { + // schema is: int, float, string, string + std::stringstream ss; + for (auto i = 0U; i < size; ++i) { + ss << "_ar" << "," << "aeio_" << "," << "foo"+std::to_string(i) << "," << std::to_string(i)+"bar" << std::endl; + } + out = ss.str(); +} + +void generate_columns_csv(std::string& out, size_t size) { + std::stringstream ss; + + for (auto i = 0U; i < size; ++i) { + ss << i << "," << i+1 << "," << i << "," << i << "," << i << "," << i << "," << i << "," << i << "," << i << "," << i << std::endl; + } + out = ss.str(); +} + +void generate_rand_columns_csv(std::string& out, size_t size) { + std::stringstream ss; + auto r = [](){return rand()%1000;}; + + for (auto i = 0U; i < size; ++i) { + ss << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << std::endl; + } + out = ss.str(); +} + +void generate_rand_columns_csv_with_null(std::string& out, size_t size) { + std::stringstream ss; + auto r = [](){ int x=rand()%1000;if (x<100) return std::string(""); else return std::to_string(x);}; + + for (auto i = 0U; i < size; ++i) { + ss << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << "," << r() << std::endl; + } + out = ss.str(); +} + +void generate_csv_trim(std::string& out, size_t size) { + // schema is: int, float, string, string + std::stringstream ss; + for (auto i = 0U; i < size; ++i) { + ss << " aeiou " << "," << std::endl; + } + out = ss.str(); +} + +void generate_csv_like(std::string& out, size_t size) { + // schema is: int, float, string, string + std::stringstream ss; + auto r = [](){ int x=rand()%1000;if (x<500) return std::string("hai"); else return std::string("fooaeioubrs");}; + for (auto i = 0U; i < size; ++i) { + ss << r() << "," << std::endl; + } + out = ss.str(); +} + +void generate_rand_columns_csv_datetime(std::string& out, size_t size) { + std::stringstream ss; + auto year = [](){return rand()%100 + 1900;}; + auto month = [](){return 1 + rand()%12;}; + auto day = [](){return 1 + rand()%28;}; + auto hours = [](){return rand()%24;}; + auto minutes = [](){return rand()%60;}; + auto seconds = [](){return rand()%60;}; + + for (auto i = 0U; i < size; ++i) { + ss << year() << "-" << std::setw(2) << std::setfill('0')<< month() << "-" << std::setw(2) << std::setfill('0')<< day() << "T" <<std::setw(2) << std::setfill('0')<< hours() << ":" << std::setw(2) << std::setfill('0')<< minutes() << ":" << std::setw(2) << std::setfill('0')<<seconds() << "Z" << "," << std::endl; + } + out = ss.str(); +} + +void generate_rand_csv_datetime_to_string(std::string& out, std::string& result, size_t size, bool const_frmt = true) { + std::stringstream ss_out, ss_res; + std::string format = "yyyysMMMMMdddSSSSSSSSSSSMMMM HHa:m -:-"; + std::string months[12] = {"January", "February", "March","April", "May", "June", "July", "August", "September", "October", "November", "December"}; + auto year = [](){return rand()%100 + 1900;}; + auto month = [](){return 1 + rand()%12;}; + auto day = [](){return 1 + rand()%28;}; + auto hours = [](){return rand()%24;}; + auto minutes = [](){return rand()%60;}; + auto seconds = [](){return rand()%60;}; + auto fracation_sec = [](){return rand()%1000000;}; + + for (auto i = 0U; i < size; ++i) + { + auto yr = year(); + auto mnth = month(); + auto dy = day(); + auto hr = hours(); + auto mint = minutes(); + auto sec = seconds(); + auto frac_sec = fracation_sec(); + + if (const_frmt) + { + ss_out << yr << "-" << std::setw(2) << std::setfill('0') << mnth << "-" << std::setw(2) << std::setfill('0') << dy << "T" <<std::setw(2) << std::setfill('0') << hr << ":" << std::setw(2) << std::setfill('0') << mint << ":" << std::setw(2) << std::setfill('0') <<sec << "." << frac_sec << "Z" << std::endl; + + ss_res << yr << sec << months[mnth-1].substr(0, 1) << std::setw(2) << std::setfill('0') << dy << dy << frac_sec << std::string(11 - std::to_string(frac_sec).length(), '0') << months[mnth-1] << " " << std::setw(2) << std::setfill('0') << hr << (hr < 12 ? "AM" : "PM") << ":" << mint << " -:-" << std::endl; + } + else + { + switch(rand()%5) + { + case 0: + format = "yyyysMMMMMdddSSSSSSSSSSSMMMM HHa:m -:-"; + ss_res << yr << sec << months[mnth-1].substr(0, 1) << std::setw(2) << std::setfill('0') << dy << dy << frac_sec << std::string(11 - std::to_string(frac_sec).length(), '0') << months[mnth-1] << " " << std::setw(2) << std::setfill('0') << hr << (hr < 12 ? "AM" : "PM") << ":" << mint << " -:-" << std::endl; + break; + case 1: + format = "aMMhh"; + ss_res << (hr < 12 ? "AM" : "PM") << std::setw(2) << std::setfill('0') << mnth << std::setw(2) << std::setfill('0') << (hr%12 == 0 ? 12 : hr%12) << std::endl; + break; + case 2: + format = "y M d ABCDEF"; + ss_res << yr << " " << mnth << " " << dy << " ABCDEF" << std::endl; + break; + case 3: + format = "W h:MMMM"; + ss_res << "W " << (hr%12 == 0 ? 12 : hr%12) << ":" << months[mnth-1] << std::endl; + break; + case 4: + format = "H:m:s"; + ss_res << hr << ":" << mint << ":" << sec << std::endl; + break; + } + + ss_out << yr << "-" << std::setw(2) << std::setfill('0') << mnth << "-" << std::setw(2) << std::setfill('0') << dy << "T" <<std::setw(2) << std::setfill('0') << hr << ":" << std::setw(2) << std::setfill('0') << mint << ":" << std::setw(2) << std::setfill('0') <<sec << "." << frac_sec << "Z" << "," << format << std::endl; + } + } + out = ss_out.str(); + result = ss_res.str(); +} + +TEST(TestS3selectFunctions, sum) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + const std::string input_query_1 = "select sum(int(_1)), sum(float(_2)) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"8128,8256"); +} + +TEST(TestS3selectFunctions, between) +{ + std::string input; + size_t size = 128; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from stdin where int(_1) between int(_2) and int(_3);"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + const std::string input_query_2 = "select count(0) from stdin where int(_1) >= int(_2) and int(_1) <= int(_3);"; + + std::string s3select_result_2 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,s3select_result_2); +} + + +TEST(TestS3selectFunctions, not_between) +{ + std::string input; + size_t size = 128; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from stdin where int(_1) not between int(_2) and int(_3);"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + const std::string input_query_2 = "select count(0) from stdin where int(_1) < int(_2) or int(_1) > int(_3);"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1,s3select_result_2); +} + +TEST(TestS3selectFunctions, count) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"128"); +} + +TEST(TestS3selectFunctions, no_args) +{//note: engine throw an exception(and description), currently it is not catch in this test-app +#if 0 + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + std::string input_query_1 = "select min() from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,""); + + input_query_1 = "select max() from stdin;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,""); + + input_query_1 = "select avg() from stdin;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,""); + + input_query_1 = "select sum() from stdin;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,""); +#endif +} + +TEST(TestS3selectFunctions, empty_group_upon_aggtegation) +{ + + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + std::string input_query_1 = "select min(cast(_1 as int)) from stdin where 1 = 0;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"null"); + + input_query_1 = "select max(cast(_1 as int)) from stdin where 1 = 0;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"null"); + + input_query_1 = "select sum(cast(_1 as int)) from stdin where 1 = 0;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"null"); + + input_query_1 = "select avg(cast(_1 as int)) from stdin where 1 = 0;"; + + s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"null"); +} + +TEST(TestS3selectFunctions, min) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + const std::string input_query_1 = "select min(int(_1)), min(float(_2)) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"0,1"); +} + +TEST(TestS3selectFunctions, max) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + const std::string input_query_1 = "select max(int(_1)), max(float(_2)) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"127,128"); +} + +int count_string(std::string in,std::string substr) +{ + int count = 0; + size_t nPos = in.find(substr, 0); // first occurrence + while(nPos != std::string::npos) + { + count++; + nPos = in.find(substr, nPos + 1); + } + + return count; +} + +void test_single_column_single_row(const char* input_query,const char* expected_result,const char * error_description = 0) +{ + s3select s3select_syntax; + auto status = s3select_syntax.parse_query(input_query); + if(strcmp(expected_result,"#failure#") == 0 && status != 0) + { + ASSERT_TRUE(true); + return; + } + else if (status != 0) + { + EXPECT_TRUE(false) << "fail to parse query: " << input_query; + return; + } + + s3selectEngine::csv_object s3_csv_object(&s3select_syntax); + std::string s3select_result; + std::string json_result; + std::string input; + size_t size = 1; + generate_csv(input, size); + + std::string js = convert_to_json(input.c_str(), input.size()); + std::string query = input_query; + const char* json_query = convert_query(query); + run_json_query(json_query, js, json_result); + +#ifdef _ARROW_EXIST + csv_to_parquet(input); + std::string parquet_result; + run_query_on_parquet_file(input_query,PARQUET_FILENAME,parquet_result); +#endif + + s3_csv_object.m_csv_defintion.redundant_column = false; + status = s3_csv_object.run_s3select_on_object(s3select_result, input.c_str(), input.size(), + false, // dont skip first line + false, // dont skip last line + true // aggregate call + ); + + if(strcmp(expected_result,"#failure#") == 0) + { + if (status==0 && s3select_result.compare("#failure#")==0) + { + ASSERT_TRUE(false); + } + ASSERT_EQ(s3_csv_object.get_error_description(),error_description); + return; + } + + ASSERT_EQ(status, 0); +#ifdef _ARROW_EXIST + parquet_csv_report_error(parquet_result,s3select_result); +#endif + json_csv_report_error(json_result, s3select_result); + ASSERT_EQ(s3select_result, std::string(expected_result)); +} + +TEST(TestS3selectFunctions, syntax_1) +{ + //where not not (1<11) is not null; syntax failure ; with parentheses it pass syntax i.e. /not (not (1<11)) is not null;/ + //where not 1<11 is null; syntax failure ; with parentheses it pass syntax i.e. not (1<11) is null; + //where not (1); AST failure , expression result,any result implictly define true/false result + //where not (1+1); AST failure + //where not(not (1<11)) ; OK + //where (not (1<11)) ; OK + //where not (1<11) ; OK + test_single_column_single_row("select count(0) from stdin where not (not (1<11)) is not null;","0"); + test_single_column_single_row("select count(0) from stdin where ((not (1<11)) is not null);","1"); + test_single_column_single_row("select count(0) from stdin where not(not (1<11));","1"); + test_single_column_single_row("select count(0) from stdin where not (1<11);","0"); + test_single_column_single_row("select count(0) from stdin where 1=1 or 2=2 and 4=4 and 2=4;","1"); + test_single_column_single_row("select count(0) from stdin where 2=2 and 4=4 and 2=4 or 1=1;","1"); +} + +TEST(TestS3selectFunctions, binop_constant) +{ + //bug-fix for expresion with constant value on the left side(the bug change the constant values between rows) + s3select s3select_syntax; + const std::string input_query = "select 10+1,20-12,2*3,128/2,29%5,2^10 from stdin;"; + auto status = s3select_syntax.parse_query(input_query.c_str()); + ASSERT_EQ(status, 0); + s3selectEngine::csv_object s3_csv_object(&s3select_syntax); + std::string s3select_result; + std::string input; + size_t size = 128; + generate_csv(input, size); + status = s3_csv_object.run_s3select_on_object(s3select_result, input.c_str(), input.size(), + false, // dont skip first line + false, // dont skip last line + true // aggregate call + ); + ASSERT_EQ(status, 0); + + int count = count_string(s3select_result,"11,8,6,64,4,1024"); + ASSERT_EQ(count,size); +} + +TEST(TestS3selectOperator, add) +{ + const std::string input_query = "select -5 + 0.5 + -0.25 from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("-4.75")); +} + +TEST(TestS3selectOperator, sub) +{ + const std::string input_query = "select -5 - 0.5 - -0.25 from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("-5.25")); +} + +TEST(TestS3selectOperator, mul) +{ + const std::string input_query = "select -5 * (0.5 - -0.25) from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("-3.75")); +} + +TEST(TestS3selectOperator, div) +{ + const std::string input_query = "select -5 / (0.5 - -0.25) from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("-6.666666666666667")); +} + +TEST(TestS3selectOperator, pow) +{ + const std::string input_query = "select 5 ^ (0.5 - -0.25) from stdin;" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("3.34370152488211")); +} + +TEST(TestS3selectOperator, not_operator) +{ + const std::string input_query = "select \"true\" from stdin where not ( (1+4) = 2 ) and (not(1 > (5*6)));" ; + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res, std::string("true")); +} + +TEST(TestS3SElect, from_stdin) +{ + s3select s3select_syntax; + const std::string input_query = "select * from stdin;"; + auto status = s3select_syntax.parse_query(input_query.c_str()); + ASSERT_EQ(status, 0); + s3selectEngine::csv_object s3_csv_object(&s3select_syntax); + std::string s3select_result; + std::string input; + size_t size = 128; + generate_csv(input, size); + std::string input_copy = input; + status = s3_csv_object.run_s3select_on_object(s3select_result, input.c_str(), input.size(), + false, // dont skip first line + false, // dont skip last line + true // aggregate call + ); + ASSERT_EQ(status, 0); +} + +TEST(TestS3SElect, from_valid_object) +{ + s3select s3select_syntax; + const std::string input_query = "select * from /objectname;"; + auto status = s3select_syntax.parse_query(input_query.c_str()); + ASSERT_EQ(status, 0); + s3selectEngine::csv_object s3_csv_object(&s3select_syntax); + std::string s3select_result; + std::string input; + size_t size = 128; + generate_csv(input, size); + status = s3_csv_object.run_s3select_on_object(s3select_result, input.c_str(), input.size(), + false, // dont skip first line + false, // dont skip last line + true // aggregate call + ); + ASSERT_EQ(status, 0); +} + +TEST(TestS3SElect, from_invalid_object) +{ + s3select s3select_syntax; + const std::string input_query = "select sum(1) from file.txt;"; + auto status = s3select_syntax.parse_query(input_query.c_str()); + ASSERT_EQ(status, -1); + auto s3select_res = run_s3select(input_query); + ASSERT_EQ(s3select_res,failure_sign); +} + +TEST(TestS3selectFunctions, avg) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + const std::string input_query_1 = "select avg(int(_1)) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"63.5"); +} + +TEST(TestS3selectFunctions, avgzero) +{ + s3select s3select_syntax; + const std::string input_query = "select avg(int(_1)) from stdin;"; + auto status = s3select_syntax.parse_query(input_query.c_str()); + ASSERT_EQ(status, 0); + s3selectEngine::csv_object s3_csv_object(&s3select_syntax); + std::string s3select_result; + std::string input; + size_t size = 0; + generate_csv(input, size); + status = s3_csv_object.run_s3select_on_object(s3select_result, input.c_str(), input.size(), + false, // dont skip first line + false, // dont skip last line + true // aggregate call + ); + ASSERT_EQ(status, 0); + ASSERT_EQ(s3select_result, std::string("null")); +} + +TEST(TestS3selectFunctions, floatavg) +{ + std::string input; + size_t size = 128; + generate_columns_csv(input, size); + + const std::string input_query_1 = "select avg(float(_1)) from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_EQ(s3select_result_1,"63.5"); +} + +TEST(TestS3selectFunctions, case_when_condition_multiplerows) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query = "select case when cast(_3 as int)>99 and cast(_3 as int)<1000 then \"case-1-1\" else \"case-2-2\" end from s3object;"; + + std::string s3select_result = run_s3select(input_query,input); + + const std::string input_query_2 = "select case when char_length(_3)=3 then \"case-1-1\" else \"case-2-2\" end from s3object;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result,s3select_result_2); +} + +TEST(TestS3selectFunctions, case_value_multiplerows) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + std::string input_query = "select case cast(_1 as int) when cast(_2 as int) then \"case-1-1\" else \"case-2-2\" end from s3object;"; + + std::string s3select_result = run_s3select(input_query,input); + + const std::string input_query_2 = "select case when cast(_1 as int) = cast(_2 as int) then \"case-1-1\" else \"case-2-2\" end from s3object;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result,s3select_result_2); + + //the following test query, validates correct build of the AST. + //the query contain various combinations, such as nested case-when-else, aggregation for case-when + //binary-operation with aggregation function. + input_query.assign("select 2+ sum(case when int(_1)>100 then (case when int(_1)>100 then 1 else 0 end) else 0 end) + \ + sum(case when int(_1)<=100 then (case when int(_1)<=100 then 1 else 0 end) else 0 end) , \ + count(0) , \ + sum(case when int(_2)>100 then (case when int(_2)>100 then 1 else 0 end) else 0 end) + \ + sum(case when int(_2)<=100 then (case when int(_2)<=100 then 1 else 0 end) else 0 end) + 1 from s3object;"); + + s3select_result = run_s3select(input_query,input); + + std::string expected_result = std::to_string(size+2) + "," + std::to_string(size) + "," + std::to_string(size+1); + ASSERT_EQ(s3select_result,expected_result); + + + //aggregation function on top of nested case-when, case-when statement contains binary operation. + input_query.assign("select sum(case when int(_2)>100 then (case when int(_2)>100 then 1 else 0 end)*2 else 0 end+1) + \ + sum(case when int(_2)<=100 then (case when int(_2)<=100 then 1 else 0 end)*2 else 0 end) from s3object;"); + + s3select_result = run_s3select(input_query,input); + + expected_result = std::to_string(size*3); + ASSERT_EQ(s3select_result,expected_result); +} + +TEST(TestS3selectFunctions, nested_call_aggregate_with_non_aggregate ) +{ + std::string input; + size_t size = 128; + + generate_fix_columns_csv(input, size); + + const std::string input_query = "select sum(cast(_1 as int)),max(cast(_3 as int)),substring('abcdefghijklm',(2-1)*3+sum(cast(_1 as int))/sum(cast(_1 as int))+1,(count(0) + count(0))/count(0)) from stdin;"; + + std::string s3select_result = run_s3select(input_query,input); + + ASSERT_EQ(s3select_result,"128,3,ef"); +} + +TEST(TestS3selectFunctions, cast_1 ) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query = "select count(0) from s3object where cast(_3 as int)>99 and cast(_3 as int)<1000;"; + + std::string s3select_result = run_s3select(input_query,input); + + const std::string input_query_2 = "select count(0) from s3object where char_length(_3)=3;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result,s3select_result_2); +} + +TEST(TestS3selectFunctions, null_column ) +{ + std::string input; + size_t size = 10000; + + generate_rand_columns_csv_with_null(input, size); + + const std::string input_query = "select count(0) from s3object where _3 is null;"; + + std::string s3select_result = run_s3select(input_query,input); + + ASSERT_NE(s3select_result,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where nullif(_3,null) is null;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_NE(s3select_result_2,failure_sign); + + ASSERT_EQ(s3select_result,s3select_result_2); +} + +TEST(TestS3selectFunctions, count_operation) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query = "select count(0) from s3object;"; + + std::string s3select_result = run_s3select(input_query,input); + + ASSERT_NE(s3select_result,failure_sign); + + ASSERT_EQ(s3select_result,"10000"); +} + +TEST(TestS3selectFunctions, nullif_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from s3object where nullif(_1,_2) is null;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where _1 = _2;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from s3object where not nullif(_1,_2) is null;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from s3object where _1 != _2;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + const std::string input_query_5 = "select count(0) from s3object where nullif(_1,_2) = _1 ;"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + ASSERT_NE(s3select_result_5,failure_sign); + + const std::string input_query_6 = "select count(0) from s3object where _1 != _2;"; + + std::string s3select_result_6 = run_s3select(input_query_6,input); + + ASSERT_EQ(s3select_result_5, s3select_result_6); +} + +TEST(TestS3selectFunctions, lower_upper_expressions) +{ + std::string input; + size_t size = 1; + generate_csv(input, size); + const std::string input_query_1 = "select lower(\"AB12cd$$\") from s3object;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + ASSERT_EQ(s3select_result_1, "ab12cd$$\n"); + + const std::string input_query_2 = "select upper(\"ab12CD$$\") from s3object;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_NE(s3select_result_2,failure_sign); + + ASSERT_EQ(s3select_result_2, "AB12CD$$\n"); +} + +TEST(TestS3selectFunctions, in_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select int(_1) from s3object where int(_1) in(1);"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select int(_1) from s3object where int(_1) = 1;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select int(_1) from s3object where int(_1) in(1,0);"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select int(_1) from s3object where int(_1) = 1 or int(_1) = 0;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + const std::string input_query_5 = "select int(_2) from s3object where int(_2) in(1,0,2);"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + ASSERT_NE(s3select_result_5,failure_sign); + + const std::string input_query_6 = "select int(_2) from s3object where int(_2) = 1 or int(_2) = 0 or int(_2) = 2;"; + + std::string s3select_result_6 = run_s3select(input_query_6,input); + + ASSERT_EQ(s3select_result_5, s3select_result_6); + + const std::string input_query_7 = "select int(_2) from s3object where int(_2)*2 in(int(_3)*2,int(_4)*3,int(_5)*5);"; + + std::string s3select_result_7 = run_s3select(input_query_7,input); + + ASSERT_NE(s3select_result_7,failure_sign); + + const std::string input_query_8 = "select int(_2) from s3object where int(_2)*2 = int(_3)*2 or int(_2)*2 = int(_4)*3 or int(_2)*2 = int(_5)*5;"; + + std::string s3select_result_8 = run_s3select(input_query_8,input); + + ASSERT_EQ(s3select_result_7, s3select_result_8); + + const std::string input_query_9 = "select int(_1) from s3object where character_length(_1) = 2 and substring(_1,2,1) in (\"3\");"; + + std::string s3select_result_9 = run_s3select(input_query_9,input); + + ASSERT_NE(s3select_result_9,failure_sign); + + const std::string input_query_10 = "select int(_1) from s3object where _1 like \"_3\";"; + + const char* json_query_10 = "select int(_1.c1) from s3object[*].root where _1.c1 like \"_3\";"; + + std::string s3select_result_10 = run_s3select(input_query_10,input,json_query_10); + + ASSERT_EQ(s3select_result_9, s3select_result_10); +} + +TEST(TestS3selectFunctions, test_coalesce_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + + const std::string input_query_1 = "select count(0) from s3object where char_length(_3)>2 and char_length(_4)>2 and cast(substring(_3,1,2) as int) = cast(substring(_4,1,2) as int);"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where cast(_3 as int)>99 and cast(_4 as int)>99 and coalesce(nullif(cast(substring(_3,1,2) as int),cast(substring(_4,1,2) as int)),7) = 7;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select coalesce(nullif(_5,_5),nullif(_1,_1),_2) from s3object;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select coalesce(_2) from s3object;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); +} + +TEST(TestS3selectFunctions, test_cast_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from s3object where cast(_3 as int)>999;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where char_length(_3)>3;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from s3object where char_length(_3)=3;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from s3object where cast(_3 as int)>99 and cast(_3 as int)<1000;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + //testing the decimal operator for precision setting + const std::string input_query_5 = "select cast(1.123456789 as decimal(9,1)) from s3object limit 1;"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + ASSERT_EQ(s3select_result_5, "1.123456789\n"); +} + +TEST(TestS3selectFunctions, test_version) +{ + std::string input; + size_t size = 1; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select version() from stdin;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + ASSERT_EQ(s3select_result_1, "41.a\n"); +} + +TEST(TestS3selectFunctions, multirow_datetime_to_string_constant) +{ + std::string input, expected_res; + std::string format = "yyyysMMMMMdddSSSSSSSSSSSMMMM HHa:m -:-"; + size_t size = 100; + + generate_rand_csv_datetime_to_string(input, expected_res, size); + + const std::string input_query = "select to_string(to_timestamp(_1), \'" + format + "\') from s3object;"; + std::string s3select_result = run_s3select(input_query, input); + EXPECT_EQ(s3select_result, expected_res); +} + +TEST(TestS3selectFunctions, multirow_datetime_to_string_dynamic) +{ + std::string input, expected_res; + size_t size = 100; + + generate_rand_csv_datetime_to_string(input, expected_res, size, false); + + const std::string input_query = "select to_string(to_timestamp(_1), _2) from s3object;"; + std::string s3select_result = run_s3select(input_query, input); + EXPECT_EQ(s3select_result, expected_res); +} + +TEST(TestS3selectFunctions, backtick_on_timestamp) +{ + const std::string input = "1994-11-21T11:49:23Z\n"; + const std::string input_query = "select count(0) from s3object where cast(_1 as timestamp) = `1994-11-21T11:49:23Z`;"; + std::string s3select_result = run_s3select(input_query, input); + EXPECT_EQ(s3select_result, "1"); +} + +TEST(TestS3selectFunctions, test_date_time_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv_datetime(input, size); + const std::string input_query_1 = "select count(0) from s3object where extract(year from to_timestamp(_1)) > 1950 and extract(year from to_timestamp(_1)) < 1960;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where int(substring(_1,1,4))>1950 and int(substring(_1,1,4))<1960;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from s3object where date_diff(month,to_timestamp(_1),date_add(month,2,to_timestamp(_1)) ) = 2;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from s3object;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_NE(s3select_result_4,failure_sign); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + const std::string input_query_5 = "select count(0) from stdin where date_diff(year,to_timestamp(_1),date_add(day, 366 ,to_timestamp(_1))) = 1;"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + ASSERT_EQ(s3select_result_5, s3select_result_4); + + const std::string input_query_6 = "select count(0) from stdin where date_diff(hour,utcnow(),date_add(day,1,utcnow())) = 24;"; + + std::string s3select_result_6 = run_s3select(input_query_6,input); + + ASSERT_EQ(s3select_result_6, s3select_result_4); + + std::string input_query_7 = "select extract(year from to_timestamp(_1)) from stdin;"; + std::string s3select_result_7 = run_s3select(input_query_7, input); + ASSERT_NE(s3select_result_7, failure_sign); + std::string input_query_8 = "select substring(_1, 1, 4) from stdin;"; + std::string s3select_result_8 = run_s3select(input_query_8, input); + ASSERT_NE(s3select_result_8, failure_sign); + EXPECT_EQ(s3select_result_7, s3select_result_8); + + std::string input_query_9 = "select to_timestamp(_1) from stdin where extract(month from to_timestamp(_1)) = 5;"; + std::string s3select_result_9 = run_s3select(input_query_9, input); + ASSERT_NE(s3select_result_9, failure_sign); + std::string input_query_10 = "select substring(_1, 1, char_length(_1)) from stdin where _1 like \'____-05%\';"; + std::string s3select_result_10 = run_s3select(input_query_10, input); + ASSERT_NE(s3select_result_10, failure_sign); + EXPECT_EQ(s3select_result_9, s3select_result_10); + + std::string input_query_11 = "select _1 from stdin where extract(month from to_timestamp(_1)) = 5 or extract(month from to_timestamp(_1)) = 6;"; + std::string s3select_result_11 = run_s3select(input_query_11,input); + ASSERT_NE(s3select_result_11, failure_sign); + std::string input_query_12 = "select _1 from stdin where to_string(to_timestamp(_1), 'MMMM') in ('May', 'June');"; + std::string s3select_result_12 = run_s3select(input_query_12,input); + ASSERT_NE(s3select_result_12, failure_sign); + EXPECT_EQ(s3select_result_11, s3select_result_12); + + std::string input_query_13 = "select to_string(to_timestamp(_1), 'y,M,H,m') from stdin where cast(to_string(to_timestamp(_1), 'd') as int) >= 1 and cast(to_string(to_timestamp(_1), 'd') as int) <= 10;"; + std::string s3select_result_13 = run_s3select(input_query_13, input); + ASSERT_NE(s3select_result_13, failure_sign); + std::string input_query_14 = "select extract(year from to_timestamp(_1)), extract(month from to_timestamp(_1)), extract(hour from to_timestamp(_1)), extract(minute from to_timestamp(_1)) from stdin where int(substring(_1, 9, 2)) between 1 and 10;"; + std::string s3select_result_14 = run_s3select(input_query_14, input); + ASSERT_NE(s3select_result_14, failure_sign); + EXPECT_EQ(s3select_result_13, s3select_result_14); + + std::string input_query_15 = "select to_string(to_timestamp(_1), 'y,M,H,m') from stdin where cast(to_string(to_timestamp(_1), 'd') as int) < 1 or cast(to_string(to_timestamp(_1), 'd') as int) > 10;"; + std::string s3select_result_15 = run_s3select(input_query_15, input); + ASSERT_NE(s3select_result_15, failure_sign); + std::string input_query_16 = "select extract(year from to_timestamp(_1)), extract(month from to_timestamp(_1)), extract(hour from to_timestamp(_1)), extract(minute from to_timestamp(_1)) from stdin where int(substring(_1, 9, 2)) not between 1 and 10;"; + std::string s3select_result_16 = run_s3select(input_query_16, input); + ASSERT_NE(s3select_result_16, failure_sign); + EXPECT_EQ(s3select_result_15, s3select_result_16); +} + +TEST(TestS3selectFunctions, test_like_expressions) +{ + std::string input, input1; + size_t size = 10000; + generate_csv(input, size); + const std::string input_query_1 = "select count(0) from stdin where _4 like \"%ar\";"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from stdin where substring(_4,char_length(_4),1) = \"r\" and substring(_4,char_length(_4)-1,1) = \"a\";"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + generate_csv_like(input1, size); + + const std::string input_query_3 = "select count(0) from stdin where _1 like \"%aeio%\";"; + + std::string s3select_result_3 = run_s3select(input_query_3,input1); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from stdin where substring(_1,4,4) = \"aeio\";"; + + std::string s3select_result_4 = run_s3select(input_query_4,input1); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + const std::string input_query_5 = "select count(0) from stdin where _1 like \"%r[r-s]\";"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + ASSERT_NE(s3select_result_5,failure_sign); + + const std::string input_query_6 = "select count(0) from stdin where substring(_1,char_length(_1),1) between \"r\" and \"s\" and substring(_1,char_length(_1)-1,1) = \"r\";"; + + std::string s3select_result_6 = run_s3select(input_query_6,input); + + ASSERT_EQ(s3select_result_5, s3select_result_6); + + const std::string input_query_7 = "select count(0) from stdin where _1 like \"%br_\";"; + + std::string s3select_result_7 = run_s3select(input_query_7,input); + + ASSERT_NE(s3select_result_7,failure_sign); + + const std::string input_query_8 = "select count(0) from stdin where substring(_1,char_length(_1)-1,1) = \"r\" and substring(_1,char_length(_1)-2,1) = \"b\";"; + + std::string s3select_result_8 = run_s3select(input_query_8,input); + + ASSERT_EQ(s3select_result_7, s3select_result_8); + + const std::string input_query_9 = "select count(0) from stdin where _1 like \"f%s\";"; + + std::string s3select_result_9 = run_s3select(input_query_9,input); + + ASSERT_NE(s3select_result_9,failure_sign); + + const std::string input_query_10 = "select count(0) from stdin where substring(_1,char_length(_1),1) = \"s\" and substring(_1,1,1) = \"f\";"; + + std::string s3select_result_10 = run_s3select(input_query_10,input); + + ASSERT_EQ(s3select_result_9, s3select_result_10); +} + +TEST(TestS3selectFunctions, test_when_then_else_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select case when cast(_1 as int)>100 and cast(_1 as int)<200 then \"a\" when cast(_1 as int)>200 and cast(_1 as int)<300 then \"b\" else \"c\" end from s3object;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + int count1 = std::count(s3select_result_1.begin(), s3select_result_1.end(),'a') ; + int count2 = std::count(s3select_result_1.begin(), s3select_result_1.end(), 'b'); + int count3 = std::count(s3select_result_1.begin(), s3select_result_1.end(), 'c'); + + const std::string input_query_2 = "select count(0) from s3object where cast(_1 as int)>100 and cast(_1 as int)<200;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_NE(s3select_result_2,failure_sign); + + ASSERT_EQ(stoi(s3select_result_2), count1); + + const std::string input_query_3 = "select count(0) from s3object where cast(_1 as int)>200 and cast(_1 as int)<300;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + ASSERT_EQ(stoi(s3select_result_3), count2); + + const std::string input_query_4 = "select count(0) from s3object where cast(_1 as int)<=100 or cast(_1 as int)>=300 or cast(_1 as int)=200;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_NE(s3select_result_4,failure_sign); + + ASSERT_EQ(stoi(s3select_result_4), count3); +} + +TEST(TestS3selectFunctions, test_case_value_when_then_else_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select case cast(_1 as int) + 1 when 2 then \"a\" when 3 then \"b\" else \"c\" end from s3object;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + int count1 = std::count(s3select_result_1.begin(), s3select_result_1.end(),'a') ; + int count2 = std::count(s3select_result_1.begin(), s3select_result_1.end(), 'b'); + int count3 = std::count(s3select_result_1.begin(), s3select_result_1.end(), 'c'); + + const std::string input_query_2 = "select count(0) from s3object where cast(_1 as int) + 1 = 2;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_NE(s3select_result_2,failure_sign); + + ASSERT_EQ(stoi(s3select_result_2), count1); + + const std::string input_query_3 = "select count(0) from s3object where cast(_1 as int) + 1 = 3;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + ASSERT_EQ(stoi(s3select_result_3), count2); + + const std::string input_query_4 = "select count(0) from s3object where cast(_1 as int) + 1 < 2 or cast(_1 as int) + 1 > 3;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_NE(s3select_result_4,failure_sign); + + ASSERT_EQ(stoi(s3select_result_4), count3); +} + +TEST(TestS3selectFunctions, test_trim_expressions) +{ + std::string input; + size_t size = 10000; + generate_csv_trim(input, size); + const std::string input_query_1 = "select count(0) from stdin where trim(_1) = \"aeiou\";"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from stdin where substring(_1 from 6 for 5) = \"aeiou\";"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from stdin where trim(both from _1) = \"aeiou\";"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from stdin where substring(_1,6,5) = \"aeiou\";"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); +} + +TEST(TestS3selectFunctions, truefalse) +{ + test_single_column_single_row("select 2 from s3object where true or false;","2\n"); + test_single_column_single_row("select 2 from s3object where true or true;","2\n"); + test_single_column_single_row("select 2 from s3object where null or true ;","2\n"); + test_single_column_single_row("select 2 from s3object where true and true;","2\n"); + test_single_column_single_row("select 2 from s3object where true = true ;","2\n"); + test_single_column_single_row("select 2 from stdin where 1<2 = true;","2\n"); + test_single_column_single_row("select 2 from stdin where 1=1 = true;","2\n"); + test_single_column_single_row("select 2 from stdin where false=false = true;","2\n"); + test_single_column_single_row("select 2 from s3object where false or true;","2\n"); + test_single_column_single_row("select true,false from s3object where false = false;","true,false\n"); + test_single_column_single_row("select count(0) from s3object where not (1>2) = true;","1"); + test_single_column_single_row("select count(0) from s3object where not (1>2) = (not false);","1"); + test_single_column_single_row("select (true or false) from s3object;","true\n"); + test_single_column_single_row("select (true and true) from s3object;","true\n"); + test_single_column_single_row("select (true and null) from s3object;","null\n"); + test_single_column_single_row("select (false or false) from s3object;","false\n"); + test_single_column_single_row("select (not true) from s3object;","false\n"); + test_single_column_single_row("select (not 1 > 2) from s3object;","true\n"); + test_single_column_single_row("select (not 1 > 2) as a1,cast(a1 as int)*4 from s3object;","true,4\n"); + test_single_column_single_row("select (1 > 2) from s3object;","false\n"); + test_single_column_single_row("select case when (nullif(3,3) is null) = true then \"case-1-1\" else \"case-2-2\" end, case when (\"a\" in (\"a\",\"b\")) = true then \"case-3-3\" else \"case-4-4\" end, case when 1>3 then \"case_5_5\" else \"case-6-6\" end from s3object where (3*3 = 9);","case-1-1,case-3-3,case-6-6\n"); +} + +TEST(TestS3selectFunctions, boolcast) +{ + test_single_column_single_row("select cast(5 as bool) from s3object;","true\n"); + test_single_column_single_row("select cast(0 as bool) from s3object;","false\n"); + test_single_column_single_row("select cast(true as bool) from s3object;","true\n"); + test_single_column_single_row("select cast('a' as bool) from s3object;","false\n"); +} + +TEST(TestS3selectFunctions, floatcast) +{ + test_single_column_single_row("select cast('1234a' as float) from s3object;","#failure#","extra characters after the number"); + test_single_column_single_row("select cast('a1234' as float) from s3object;","#failure#","text cannot be converted to a number"); + test_single_column_single_row("select cast('999e+999' as float) from s3object;","#failure#","converted value would fall out of the range of the result type!"); +} + +TEST(TestS3selectFunctions, intcast) +{ + test_single_column_single_row("select cast('1234a' as int) from s3object;","#failure#","extra characters after the number"); + test_single_column_single_row("select cast('a1234' as int) from s3object;","#failure#","text cannot be converted to a number"); + test_single_column_single_row("select cast('9223372036854775808' as int) from s3object;","#failure#","converted value would fall out of the range of the result type!"); + test_single_column_single_row("select cast('-9223372036854775809' as int) from s3object;","#failure#","converted value would fall out of the range of the result type!"); +} + +TEST(TestS3selectFunctions, predicate_as_projection_column) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query = "select (int(_2) between int(_3) and int(_4)) from s3object where int(_2)>int(_3) and int(_2)<int(_4);"; + + std::string s3select_result = run_s3select(input_query,input); + + ASSERT_NE(s3select_result,failure_sign); + + auto count = std::count(s3select_result.begin(), s3select_result.end(), '0'); + + ASSERT_EQ(count,0); + + const std::string input_query_1 = "select (nullif(_1,_2) is null) from s3object where _1 = _2;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + auto count_1 = std::count(s3select_result_1.begin(), s3select_result_1.end(), '0'); + + ASSERT_EQ(count_1,0); + + const std::string input_query_2 = "select (nullif(_1,_2) is not null) from s3object where _1 != _2;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_NE(s3select_result_2,failure_sign); + + auto count_2 = std::count(s3select_result_2.begin(), s3select_result_2.end(), '0'); + + ASSERT_EQ(count_2,0); + + const std::string input_query_3 = "select (_1 like \"_3\") from s3object where character_length(_1) = 2 and substring(_1,2,1) in (\"3\");"; + + const char* json_query_3 = "select (_1.c1 like \"_3\") from s3object[*].root where character_length(_1.c1) = 2 and substring(_1.c1,2,1) in (\"3\");"; + + std::string s3select_result_3 = run_s3select(input_query_3,input, json_query_3); + + ASSERT_NE(s3select_result_3,failure_sign); + + auto count_3 = std::count(s3select_result_3.begin(), s3select_result_3.end(), '0'); + + ASSERT_EQ(count_3,0); + + const std::string input_query_4 = "select (int(_1) in (1)) from s3object where int(_1) = 1;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_NE(s3select_result_4,failure_sign); + + auto count_4 = std::count(s3select_result_4.begin(), s3select_result_4.end(), '0'); + + ASSERT_EQ(count_4,0); +} + +TEST(TestS3selectFunctions, truefalse_multirows_expressions) +{ + std::string input, input1; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from s3object where cast(_3 as int)>999 = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where char_length(_3)>3 = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from s3object where char_length(_3)=3 = true;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from s3object where cast(_3 as int)>99 = true and cast(_3 as int)<1000 = true;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + generate_rand_columns_csv_with_null(input1, size); + + const std::string input_query_5 = "select count(0) from s3object where (_3 is null) = true;"; + + std::string s3select_result_5 = run_s3select(input_query_5,input1); + + ASSERT_NE(s3select_result_5,failure_sign); + + const std::string input_query_6 = "select count(0) from s3object where (nullif(_3,null) is null) = true;"; + + std::string s3select_result_6 = run_s3select(input_query_6,input1); + + ASSERT_NE(s3select_result_6,failure_sign); + + ASSERT_EQ(s3select_result_5,s3select_result_6); +} + +TEST(TestS3selectFunctions, truefalse_date_time_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv_datetime(input, size); + const std::string input_query_1 = "select count(0) from s3object where extract(year from to_timestamp(_1)) > 1950 = true and extract(year from to_timestamp(_1)) < 1960 = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where int(substring(_1,1,4))>1950 = true and int(substring(_1,1,4))<1960 = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); +} + +TEST(TestS3selectFunctions, truefalse_trim_expressions) +{ + std::string input; + size_t size = 10000; + generate_csv_trim(input, size); + const std::string input_query_1 = "select count(0) from stdin where trim(_1) = \"aeiou\" = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from stdin where substring(_1 from 6 for 5) = \"aeiou\" = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); +} + +TEST(TestS3selectFunctions, tuefalse_like_expressions) +{ + std::string input, input1; + size_t size = 10000; + generate_csv(input, size); + const std::string input_query_1 = "select count(0) from stdin where (_4 like \"%ar\") = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from stdin where (substring(_4,char_length(_4),1) = \"r\") = true and (substring(_4,char_length(_4)-1,1) = \"a\") = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + generate_csv_like(input1, size); + + const std::string input_query_3 = "select count(0) from stdin where (_1 like \"%aeio%\") = true;"; + + std::string s3select_result_3 = run_s3select(input_query_3,input1); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from stdin where (substring(_1,4,4) = \"aeio\") = true;"; + + std::string s3select_result_4 = run_s3select(input_query_4,input1); + + ASSERT_EQ(s3select_result_3, s3select_result_4); + + const std::string input_query_5 = "select count(0) from stdin where (_1 like \"%r[r-s]\") = true;"; + + std::string s3select_result_5 = run_s3select(input_query_5,input1); + + ASSERT_NE(s3select_result_5,failure_sign); + + const std::string input_query_6 = "select count(0) from stdin where (substring(_1,char_length(_1),1) between \"r\" and \"s\") = true and (substring(_1,char_length(_1)-1,1) = \"r\") = true;"; + + std::string s3select_result_6 = run_s3select(input_query_6,input1); + + ASSERT_EQ(s3select_result_5, s3select_result_6); + + const std::string input_query_7 = "select count(0) from stdin where (_1 like \"%br_\") = true;"; + + std::string s3select_result_7 = run_s3select(input_query_7,input); + + ASSERT_NE(s3select_result_7,failure_sign); + + const std::string input_query_8 = "select count(0) from stdin where (substring(_1,char_length(_1)-1,1) = \"r\") = true and (substring(_1,char_length(_1)-2,1) = \"b\") = true;"; + + std::string s3select_result_8 = run_s3select(input_query_8,input); + + ASSERT_EQ(s3select_result_7, s3select_result_8); + + const std::string input_query_9 = "select count(0) from stdin where (_1 like \"%r[r-s]\") = false;"; + + std::string s3select_result_9 = run_s3select(input_query_9,input1); + + ASSERT_NE(s3select_result_9,failure_sign); + + const std::string input_query_10 = "select count(0) from stdin where (substring(_1,char_length(_1),1) not between \"r\" and \"s\") = true or (substring(_1,char_length(_1)-1,1) = \"r\") = false;"; + + std::string s3select_result_10 = run_s3select(input_query_10,input1); + + ASSERT_EQ(s3select_result_9, s3select_result_10); +} + +TEST(TestS3selectFunctions, truefalse_coalesce_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select count(0) from s3object where char_length(_3)>2 and char_length(_4)>2 = true and cast(substring(_3,1,2) as int) = cast(substring(_4,1,2) as int) = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from s3object where cast(_3 as int)>99 = true and cast(_4 as int)>99 = true and (coalesce(nullif(cast(substring(_3,1,2) as int),cast(substring(_4,1,2) as int)),7) = 7) = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); +} + +TEST(TestS3selectFunctions, truefalse_in_expressions) +{ + std::string input; + size_t size = 10000; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select int(_1) from s3object where (int(_1) in(1)) = true;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select int(_1) from s3object where int(_1) = 1 = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_7 = "select int(_2) from s3object where (int(_2)*2 in(int(_3)*2,int(_4)*3,int(_5)*5)) = true;"; + + std::string s3select_result_7 = run_s3select(input_query_7,input); + + ASSERT_NE(s3select_result_7,failure_sign); + + const std::string input_query_8 = "select int(_2) from s3object where int(_2)*2 = int(_3)*2 = true or int(_2)*2 = int(_4)*3 = true or int(_2)*2 = int(_5)*5 = true;"; + + std::string s3select_result_8 = run_s3select(input_query_8,input); + + ASSERT_EQ(s3select_result_7, s3select_result_8); + + const std::string input_query_9 = "select int(_1) from s3object where character_length(_1) = 2 = true and (substring(_1,2,1) in (\"3\")) = true;"; + + std::string s3select_result_9 = run_s3select(input_query_9,input); + + ASSERT_NE(s3select_result_9,failure_sign); + + const std::string input_query_10 = "select int(_1) from s3object where (_1 like \"_3\") = true;"; + + const char* json_query_10 = "select int(_1.c1) from s3object[*].root where (_1.c1 like \"_3\") = true;"; + + std::string s3select_result_10 = run_s3select(input_query_10,input,json_query_10); + + ASSERT_EQ(s3select_result_9, s3select_result_10); +} + +TEST(TestS3selectFunctions, truefalse_alias_expressions) +{ + std::string input; + size_t size = 100; + generate_rand_columns_csv(input, size); + const std::string input_query_1 = "select (int(_1) > int(_2)) as a1 from s3object where a1 = true ;"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select (int(_1) > int(_2)) from s3object where int(_1) > int(_2) = true;"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); +} +TEST(TestS3selectFunctions, charlength) +{ +test_single_column_single_row( "select char_length(\"abcde\") from stdin;","5\n"); +} + +TEST(TestS3selectFunctions, characterlength) +{ +test_single_column_single_row( "select character_length(\"abcde\") from stdin;","5\n"); +} + +TEST(TestS3selectFunctions, emptystring) +{ +test_single_column_single_row( "select char_length(\"\") from stdin;","0\n"); +} + +TEST(TestS3selectFunctions, lower) +{ +test_single_column_single_row( "select lower(\"ABcD12#$e\") from stdin;","abcd12#$e\n"); +} + +TEST(TestS3selectFunctions, upper) +{ +test_single_column_single_row( "select upper(\"abCD12#$e\") from stdin;","ABCD12#$E\n"); +} + +TEST(TestS3selectFunctions, mod) +{ +test_single_column_single_row( "select 5%2 from stdin;","1\n"); +} + +TEST(TestS3selectFunctions, modzero) +{ +test_single_column_single_row( "select 0%2 from stdin;","0\n"); +} + +TEST(TestS3selectFunctions, nullif) +{ +test_single_column_single_row( "select nullif(5,3) from stdin;","5\n"); +} + +TEST(TestS3selectFunctions, nullifeq) +{ +test_single_column_single_row( "select nullif(5,5) from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, nullifnull) +{ +test_single_column_single_row( "select nullif(null,null) from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, nullifintnull) +{ +test_single_column_single_row( "select nullif(7, null) from stdin;","7\n"); +} + +TEST(TestS3selectFunctions, nullifintstring) +{ +test_single_column_single_row( "select nullif(5, \"hello\") from stdin;","5\n"); +} + +TEST(TestS3selectFunctions, nullifstring) +{ +test_single_column_single_row( "select nullif(\"james\",\"bond\") from stdin;","james\n"); +} + +TEST(TestS3selectFunctions, nullifeqstring) +{ +test_single_column_single_row( "select nullif(\"redhat\",\"redhat\") from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, nullifnumericeq) +{ +test_single_column_single_row( "select nullif(1, 1.0) from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, nulladdition) +{ +test_single_column_single_row( "select 1 + null from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, isnull) +{ +test_single_column_single_row( "select \"true\" from stdin where nullif(1,1) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnullnot) +{ +test_single_column_single_row( "select \"true\" from stdin where not nullif(1,2) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull1) +{ +test_single_column_single_row( "select \"true\" from stdin where 7 + null is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull2) +{ +test_single_column_single_row( "select \"true\" from stdin where null + 7 is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull3) +{ +test_single_column_single_row( "select \"true\" from stdin where (null > 1) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull4) +{ +test_single_column_single_row( "select \"true\" from stdin where (1 <= null) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull5) +{ +test_single_column_single_row( "select \"true\" from stdin where (null > 2 and 1 = 0) is not null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull6) +{ +test_single_column_single_row( "select \"true\" from stdin where (null>2 and 2>1) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull7) +{ +test_single_column_single_row( "select \"true\" from stdin where (null>2 or null<=3) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull8) +{ +test_single_column_single_row( "select \"true\" from stdin where (5<4 or null<=3) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull9) +{ +test_single_column_single_row( "select \"true\" from stdin where (null<=3 or 5<3) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull10) +{ +test_single_column_single_row( "select \"true\" from stdin where (null<=3 or 5>3) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, nullnot) +{ +test_single_column_single_row( "select \"true\" from stdin where not (null>0 and 7<3) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, nullnot1) +{ +test_single_column_single_row( "select \"true\" from stdin where not (null>0 or 4>3) and (7<1) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, isnull11) +{ +test_single_column_single_row( "select \"true\" from stdin where (5>3 or null<1) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop) +{ +test_single_column_single_row( "select \"true\" from stdin where \"qwertyabcde\" like \"%abcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeopfalse) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"qwertybcde\" like \"%abcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop1) +{ +test_single_column_single_row( "select \"true\" from stdin where \"qwertyabcdeqwerty\" like \"%abcde%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop1false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"qwertyabcdqwerty\" like \"%abcde%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop2) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcdeqwerty\" like \"abcde%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop2false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"abdeqwerty\" like \"abcde%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop6) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abqwertyde\" like \"ab%de\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop3false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"aabcde\" like \"_bcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop3mix) +{ +test_single_column_single_row( "select \"true\" from stdin where \"aabbccdef\" like \"_ab%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop4mix) +{ +test_single_column_single_row( "select \"true\" from stdin where \"aabbccdef\" like \"%de_\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop4) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcde\" like \"abc_e\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop4false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"abcccddyddyde\" like \"abc_e\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop5) +{ +test_single_column_single_row( "select \"true\" from stdin where \"ebcde\" like \"[d-f]bcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop5false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"abcde\" like \"[d-f]bcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeopdynamic) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcde\" like substring(\"abcdefg\",1,5);" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop5not) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcde\" like \"[^d-f]bcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop7) +{ +test_single_column_single_row( "select \"true\" from stdin where \"qwertyabcde\" like \"%%%%abcde\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop8beginning) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcde\" like \"[abc]%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop8false) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"dabc\" like \"[abc]%\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, likeop8end) +{ +test_single_column_single_row( "select \"true\" from stdin where \"xyza\" like \"%[abc]\";" ,"true\n"); +} + +TEST(TestS3selectFunctions, inoperator) +{ +test_single_column_single_row( "select \"true\" from stdin where \"a\" in (\"b\", \"a\");" ,"true\n"); +} + +TEST(TestS3selectFunctions, inoperatorfalse) +{ +test_single_column_single_row( "select \"true\" from stdin where not \"a\" in (\"b\", \"c\");" ,"true\n"); +} + +TEST(TestS3selectFunctions, inoperatormore) +{ +test_single_column_single_row( "select \"true\" from stdin where \"a\" in (\"b\", \"a\", \"d\", \"e\", \"f\");" ,"true\n"); +} + +TEST(TestS3selectFunctions, inoperatormixtype) +{ +test_single_column_single_row( "select \"true\" from stdin where 10 in (5.0*2.0, 12+1, 9+1.2, 22/2, 12-3);" ,"true\n"); +} + +TEST(TestS3selectFunctions, mix) +{ +test_single_column_single_row( "select \"true\" from stdin where \"abcde\" like \"abc_e\" and 10 in (5.0*2.0, 12+1) and nullif(2,2) is null;" ,"true\n"); +} + +TEST(TestS3selectFunctions, case_when_then_else) +{ +test_single_column_single_row( "select case when (1+1+1*1=(2+1)*3) then \"case-1-1\" when ((4*3)=(12)) then \"case-1-2\" else \"case-else-1\" end , case when 1+1*7=(2+1)*3 then \"case-2-1\" when ((4*3)=(12)+1) then \"case-2-2\" else \"case-else-2\" end from stdin where (3*3=9);" ,"case-1-2,case-else-2\n"); +} + +TEST(TestS3selectFunctions, simple_case_when) +{ +test_single_column_single_row( "select case 2+1 when (3+4) then \"case-1-1\" when 3 then \"case-3\" else \"case-else-1\" end from stdin;","case-3\n"); +} + +TEST(TestS3selectFunctions, nested_case) +{ +test_single_column_single_row( "select case when ((3+4) = (7 *1)) then \"case-1-1\" else \"case-2-2\" end, case 1+3 when 2+3 then \"case-1-2\" else \"case-2-1\" end from stdin where (3*3 = 9);","case-1-1,case-2-1\n"); +} + +TEST(TestS3selectFunctions, substr11) +{ +test_single_column_single_row( "select substring(\"01234567890\",2*0+1,1.53*0+3) from stdin ;" ,"012\n"); +} + +TEST(TestS3selectFunctions, substr12) +{ +test_single_column_single_row( "select substring(\"01234567890\",2*0+1,1+2.0) from stdin ;" ,"012\n"); +} + +TEST(TestS3selectFunctions, substr13) +{ +test_single_column_single_row( "select substring(\"01234567890\",2.5*2+1,1+2) from stdin ;" ,"567\n"); +} + +TEST(TestS3selectFunctions, substr14) +{ +test_single_column_single_row( "select substring(\"123456789\",0) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr15) +{ +test_single_column_single_row( "select substring(\"123456789\",-4) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr16) +{ +test_single_column_single_row( "select substring(\"123456789\",0,100) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr17) +{ +test_single_column_single_row( "select substring(\"12345\",0,5) from stdin ;" ,"1234\n"); +} + +TEST(TestS3selectFunctions, substr18) +{ +test_single_column_single_row( "select substring(\"12345\",-1,5) from stdin ;" ,"123\n"); +} + +TEST(TestS3selectFunctions, substr19) +{ +test_single_column_single_row( "select substring(\"123456789\" from 0) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr20) +{ +test_single_column_single_row( "select substring(\"123456789\" from -4) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr21) +{ +test_single_column_single_row( "select substring(\"123456789\" from 0 for 100) from stdin ;" ,"123456789\n"); +} + +TEST(TestS3selectFunctions, substr22) +{ +test_single_column_single_row( "select \"true\" from stdin where 5 = cast(substring(\"523\",1,1) as int);" ,"true\n"); +} + +TEST(TestS3selectFunctions, substr23) +{ +test_single_column_single_row( "select \"true\" from stdin where cast(substring(\"523\",1,1) as int) > cast(substring(\"123\",1,1) as int) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, coalesce) +{ +test_single_column_single_row( "select coalesce(5,3) from stdin;","5\n"); +} + +TEST(TestS3selectFunctions, coalesceallnull) +{ +test_single_column_single_row( "select coalesce(nullif(5,5),nullif(1,1.0)) from stdin;","null\n"); +} + +TEST(TestS3selectFunctions, coalesceanull) +{ +test_single_column_single_row( "select coalesce(nullif(5,5),nullif(1,1.0),2) from stdin;","2\n"); +} + +TEST(TestS3selectFunctions, coalescewhere) +{ +test_single_column_single_row( "select \"true\" from stdin where coalesce(nullif(7.0,7),nullif(4,4.0),6) = 6;" ,"true\n"); +} + +TEST(TestS3selectFunctions, castint) +{ +test_single_column_single_row( "select cast(5.123 as int) from stdin ;" ,"5\n"); +} + +TEST(TestS3selectFunctions, castfloat) +{ +test_single_column_single_row( "select cast(1.234 as FLOAT) from stdin ;" ,"1.234\n"); +} + +TEST(TestS3selectFunctions, castfloatoperation) +{ +test_single_column_single_row( "select cast(1.234 as float) + cast(1.235 as float) from stdin ;" ,"2.4690000000000003\n"); +} + +TEST(TestS3selectFunctions, caststring) +{ +test_single_column_single_row( "select cast(1234 as string) from stdin ;" ,"1234\n"); +} + +TEST(TestS3selectFunctions, caststring1) +{ +test_single_column_single_row( "select cast('12hddd' as int) from stdin ;" ,"#failure#","extra characters after the number"); +} + +TEST(TestS3selectFunctions, caststring2) +{ +test_single_column_single_row( "select cast('124' as int) + 1 from stdin ;" ,"125\n"); +} + +TEST(TestS3selectFunctions, castsubstr) +{ +test_single_column_single_row( "select substring(cast(cast(\"1234567\" as int) as string),2,2) from stdin ;" ,"23\n"); +} + +TEST(TestS3selectFunctions, casttimestamp) +{ +test_single_column_single_row( "select cast('2010-01-15T13:30:10Z' as timestamp) from stdin ;" ,"2010-01-15T13:30:10Z\n"); +} + +TEST(TestS3selectFunctions, castdateadd) +{ +test_single_column_single_row( "select date_add(day, 2, cast('2010-01-15T13:30:10Z' as timestamp)) from stdin ;" ,"2010-01-17T13:30:10Z\n"); +} + +TEST(TestS3selectFunctions, castdatediff) +{ +test_single_column_single_row( "select date_diff(year,cast('2010-01-15T13:30:10Z' as timestamp), cast('2020-01-15T13:30:10Z' as timestamp)) from stdin ;" ,"10\n"); +} + +TEST(TestS3selectFunctions, trim) +{ +test_single_column_single_row( "select trim(\" \twelcome\t \") from stdin ;" ,"\twelcome\t\n"); +} + +TEST(TestS3selectFunctions, trim1) +{ +test_single_column_single_row( "select trim(\" foobar \") from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim2) +{ +test_single_column_single_row( "select trim(trailing from \" foobar \") from stdin ;" ," foobar\n"); +} + +TEST(TestS3selectFunctions, trim3) +{ +test_single_column_single_row( "select trim(leading from \" foobar \") from stdin ;" ,"foobar \n"); +} + +TEST(TestS3selectFunctions, trim4) +{ +test_single_column_single_row( "select trim(both from \" foobar \") from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim5) +{ +test_single_column_single_row( "select trim(from \" foobar \") from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim6) +{ +test_single_column_single_row( "select trim(both \"12\" from \"1112211foobar22211122\") from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim7) +{ +test_single_column_single_row( "select substring(trim(both from ' foobar '),2,3) from stdin ;" ,"oob\n"); +} + +TEST(TestS3selectFunctions, trim8) +{ +test_single_column_single_row( "select substring(trim(both '12' from '1112211foobar22211122'),1,6) from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim9) +{ +test_single_column_single_row( "select cast(trim(both \"12\" from \"111221134567822211122\") as int) + 5 from stdin ;" ,"345683\n"); +} + +TEST(TestS3selectFunctions, trimefalse) +{ +test_single_column_single_row( "select cast(trim(both from \"12\" \"111221134567822211122\") as int) + 5 from stdin ;" ,"#failure#",""); +} + +TEST(TestS3selectFunctions, trim10) +{ +test_single_column_single_row( "select trim(trim(leading from \" foobar \")) from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, trim11) +{ +test_single_column_single_row( "select trim(trailing from trim(leading from \" foobar \")) from stdin ;" ,"foobar\n"); +} + +TEST(TestS3selectFunctions, likescape) +{ + test_single_column_single_row("select \"true\" from stdin where \"abc_defgh\" like \"abc$_defgh\" escape \"$\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"j_kerhai\" like \"j#_%\" escape \"#\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"jok_ai\" like \"%#_ai\" escape \"#\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"jo_aibc\" like \"%#_ai%\" escape \"#\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"jok%abc\" like \"jok$%abc\" escape \"$\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"ab%%a\" like \"ab$%%a\" escape \"$\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"_a_\" like \"=_a=_\" escape \"=\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"abc#efgh\" like \"abc##efgh\" escape \"#\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"%abs%\" like \"#%abs#%\" escape \"#\";","true\n"); + test_single_column_single_row("select \"true\" from s3object where \"abc##efgh\" like \"abc####efgh\" escape \"#\";","true\n"); +} + +TEST(TestS3selectFunctions, likescapedynamic) +{ +test_single_column_single_row( "select \"true\" from s3object where \"abc#efgh\" like substring(\"abc##efghi\",1,9) escape \"#\";" ,"true\n"); +test_single_column_single_row( "select \"true\" from s3object where \"abcdefgh\" like substring(\"abcd%abc\",1,5);" ,"true\n"); +test_single_column_single_row( "select \"true\" from s3object where substring(\"abcde\",1,5) like \"abcd_\" ;" ,"true\n"); +test_single_column_single_row( "select \"true\" from s3object where substring(\"abcde\",1,5) like substring(\"abcd_ab\",1,5) ;" ,"true\n"); +} + +TEST(TestS3selectFunctions, test_escape_expressions) +{ + std::string input, input1; + size_t size = 10000; + generate_csv_escape(input, size); + const std::string input_query_1 = "select count(0) from stdin where _1 like \"%_ar\" escape \"%\";"; + + std::string s3select_result_1 = run_s3select(input_query_1,input); + + ASSERT_NE(s3select_result_1,failure_sign); + + const std::string input_query_2 = "select count(0) from stdin where substring(_1,char_length(_1),1) = \"r\" and substring(_1,char_length(_1)-1,1) = \"a\" and substring(_1,char_length(_1)-2,1) = \"_\";"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + ASSERT_EQ(s3select_result_1, s3select_result_2); + + const std::string input_query_3 = "select count(0) from stdin where _2 like \"%aeio$_\" escape \"$\";"; + + std::string s3select_result_3 = run_s3select(input_query_3,input); + + ASSERT_NE(s3select_result_3,failure_sign); + + const std::string input_query_4 = "select count(0) from stdin where substring(_2,1,5) = \"aeio_\";"; + + std::string s3select_result_4 = run_s3select(input_query_4,input); + + ASSERT_EQ(s3select_result_3, s3select_result_4); +} + +void generate_csv_multirow(std::string& out, int loop = 1) { + // schema is: int, float, string, string + std::stringstream ss; + for(int i = 0; i < loop; i++) + { + ss << "1,42926,7334,5.5,Brandise,Letsou,Brandise.Letsou@yopmail.com,worker,2020-10-26T11:21:30.397Z" << std::endl; + ss << "2,21169,3648,9.0,Zaria,Weinreb,Zaria.Weinreb@yopmail.com,worker,2009-12-02T01:22:45.8327+09:45" << std::endl; + ss << "3,35581,9091,2.1,Bibby,Primalia,Bibby.Primalia@yopmail.com,doctor,2001-02-27T23:18:23.446633-12:00" << std::endl; + ss << "4,38388,7345,4.7,Damaris,Arley,Damaris.Arley@yopmail.com,firefighter,1995-08-24T01:40:00+12:30" << std::endl; + ss << "5,42802,6464,7.0,Georgina,Georas,Georgina.Georas@yopmail.com,worker,2013-01-30T05:27:59.2Z" << std::endl; + ss << "6,45582,52863,0.1,Kelly,Hamil,Kelly.Hamil@yopmail.com,police officer,1998-03-31T17:25-01:05" << std::endl; + ss << "7,8548,7665,3.6,Claresta,Flita,Claresta.Flita@yopmail.com,doctor,2007-10-10T22:00:30Z" << std::endl; + ss << "8,22633,528,5.3,Bibby,Virgin,Bibby.Virgin@yopmail.com,developer,2020-06-30T11:07:01.23323-00:30" << std::endl; + ss << "9,38439,5645,2.8,Mahalia,Aldric,Mahalia.Aldric@yopmail.com,doctor,2019-04-20T20:21:22.23+05:15" << std::endl; + ss << "10,6611,7287,1.0,Pamella,Sibyls,Pamella.Sibyls@yopmail.com,police officer,2000-09-13T14:41Z" << std::endl; + } + out = ss.str(); +} + +TEST(TestS3selectFunctions, limit) +{ + std::string input_csv, input_query, expected_res; + generate_csv_multirow(input_csv, 2); + + input_query = "select _1 from stdin limit 0;"; + expected_res = ""; + std::cout << "Running query: 1 (when limit is zero)" << std::endl; + auto s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _1 from stdin limit 8;"; + expected_res = "1\n2\n3\n4\n5\n6\n7\n8\n"; + std::cout << "Running query: 2 (non-aggregate query, limit clause only)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _1 from stdin where _2 > _3 limit 8;"; + expected_res = "7\n"; + std::cout << "Running query: 3 (non-aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _1 from stdin where _2 > _3 limit 7;"; + expected_res = "7\n"; + std::cout << "Running query: 4 (non-aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _1 from stdin where _2 > _3 limit 6;"; + expected_res = ""; + std::cout << "Running query: 5 (non-aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin limit 9;"; + expected_res = "9"; + std::cout << "Running query: 6 (aggregate query, limit clause only)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin where _2 > _3 limit 8;"; + expected_res = "1"; + std::cout << "Running query: 7 (aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin where _2 > _3 limit 7;"; + expected_res = "1"; + std::cout << "Running query: 8 (aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin where _2 > _3 limit 6;"; + expected_res = "0"; + std::cout << "Running query: 9 (aggregate_query, where + limit clause)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + generate_csv_multirow(input_csv, 10000); + + input_query = "select count(0) from stdin limit 90000;"; + expected_res = "90000"; + std::cout << "Running query: 10 (aggregate_query, limit clause only, with Large input)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin where _2 > _3 limit 90000;"; + expected_res = "9000"; + std::cout << "Running query: 11 (aggregate_query, where + limit clause, with Large input)" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + std::string json_input=R"( +{ +"firstName": "Joe", +"lastName": "Jackson", +"gender": "male", +"age": 20, +"address": { +"streetAddress": "101", +"city": "San Diego", +"state": "CA" +}, + +"phoneNumbers": [ +{ "type": "home1", "number": "734928_1","addr": 11 }, +{ "type": "home2", "number": "734928_2","addr": 22 }, +{ "type": "home3", "number": "734928_3","addr": 33 }, +{ "type": "home4", "number": "734928_4","addr": 44 }, +{ "type": "home5", "number": "734928_5","addr": 55 }, +{ "type": "home6", "number": "734928_6","addr": 66 }, +{ "type": "home7", "number": "734928_7","addr": 77 }, +{ "type": "home8", "number": "734928_8","addr": 88 }, +{ "type": "home9", "number": "734928_9","addr": 99 }, +{ "type": "home10", "number": "734928_10","addr": 100 }, +{ "type": "home11", "number": "734928_11","addr": 101 }, +{ "type": "home12", "number": "734928_12","addr": 102 }, +{ "type": "home13", "number": "734928_13","addr": 103 }, +{ "type": "home14", "number": "734928_14","addr": 104 }, +{ "type": "home15", "number": "734928_15","addr": 105 } +], + +"key_after_array": "XXX", + +"description" : { + "main_desc" : "value_1", + "second_desc" : "value_2" +} + +} +)"; + + const char* input_query_json = "select _1.addr from s3object[*].phoneNumbers limit 0;"; + expected_res = ""; + std::cout << "Running query: 12 (json, limit is zero)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); + + input_query_json = "select _1.addr from s3object[*].phoneNumbers limit 5;"; + expected_res = "11\n22\n33\n44\n55\n"; + std::cout << "Running query: 13 (json, non-aggregate query, limit clause only)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); + + input_query_json = "select _1.addr from s3object[*].phoneNumbers where _1.type like \"%1%\" limit 12;"; + expected_res = "11\n100\n101\n102\n"; + std::cout << "Running query: 14 (json, non-aggregate query, where + limit clause)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); + + input_query_json = "select count(0) from s3object[*].phoneNumbers limit 9;"; + expected_res = "9"; + std::cout << "Running query: 15 (json, aggregate query, limit clause only, limit reached)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); + + input_query_json = "select count(0) from s3object[*].phoneNumbers limit 18;"; + expected_res = "15"; + std::cout << "Running query: 16 (json, aggregate query, limit clause only, end of stream)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); + + input_query_json = "select count(0) from s3object[*].phoneNumbers where _1.type like \"%1_\" limit 10;"; + expected_res = "1"; + std::cout << "Running query: 17 (json, aggregate query, where + limit clause)" << std::endl; + run_json_query(input_query_json, json_input, s3select_res); + EXPECT_EQ(s3select_res, expected_res); +} + +TEST(TestS3selectFunctions, nested_query_single_row_result) +{ + std::string input_csv, input_query, expected_res; + generate_csv_multirow(input_csv); + + input_query = "select to_string(to_timestamp(\'2009-09-17T17:56:06.234567Z\'), substring(\' athmywopgss-nghjkl\', 3, 10)) from stdin;"; + expected_res = "t5562009wopg06"; + std::cout << "Running query: 1" << std::endl; + auto s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select to_timestamp(upper(\'2009-09-17t17:56:06.234567z\')) from stdin;"; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2009-09-17T17:56:06.234567000Z"; + #else + expected_res = "2009-09-17T17:56:06.234567Z"; + #endif + std::cout << "Running query: 2" << std::endl; + s3select_res = run_s3select(input_query); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from stdin where extract( year from to_timestamp(_9)) < 2010;"; + expected_res = "6"; + std::cout << "Running query: 3" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + +} + +TEST(TestS3selectFunctions, nested_query_multirow_result) +{ + std::string input_csv, input_query, expected_res; + generate_csv_multirow(input_csv); + + input_query = "select to_string(to_timestamp(_9), substring(\' athmywopgssMMMMdXXXXX-nghjkl\', 2, 25)) from stdin;"; + expected_res = "AMt11212020wopg30October26Z-397000000g11\nAMt1222009wopg45December2+09:45-832700000g1\nPMt11182001wopg23February27-12:00-446633000g11\nAMt1401995wopg00August24+12:30-0g1\nAMt5272013wopg59January30Z-200000000g5\nPMt5251998wopg00March31-01:05-0g5\nPMt1002007wopg30October10Z-0g10\nAMt1172020wopg01June30-00:30-233230000g11\nPMt8212019wopg22April20+05:15-230000000g8\nPMt2412000wopg00September13Z-0g2\n"; + std::cout << "Running query: 1" << std::endl; + auto s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select to_timestamp(upper(lower(_9))) from stdin;"; + #if BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + expected_res = "2020-10-26T11:21:30.397000000Z\n2009-12-02T01:22:45.832700000+09:45\n2001-02-27T23:18:23.446633000-12:00\n1995-08-24T01:40:00+12:30\n2013-01-30T05:27:59.200000000Z\n1998-03-31T17:25:00-01:05\n2007-10-10T22:00:30Z\n2020-06-30T11:07:01.233230000-00:30\n2019-04-20T20:21:22.230000000+05:15\n2000-09-13T14:41:00Z\n"; + #else + expected_res = "2020-10-26T11:21:30.397000Z\n2009-12-02T01:22:45.832700+09:45\n2001-02-27T23:18:23.446633-12:00\n1995-08-24T01:40:00+12:30\n2013-01-30T05:27:59.200000Z\n1998-03-31T17:25:00-01:05\n2007-10-10T22:00:30Z\n2020-06-30T11:07:01.233230-00:30\n2019-04-20T20:21:22.230000+05:15\n2000-09-13T14:41:00Z\n"; + #endif + std::cout << "Running query: 2" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select count(0) from s3object where extract( year from to_timestamp(_9)) > 2010;"; + expected_res = "4"; + std::cout << "Running query: 3" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _9 from s3object where extract( year from to_timestamp(_9)) > 2010;"; + expected_res = "2020-10-26T11:21:30.397Z\n2013-01-30T05:27:59.2Z\n2020-06-30T11:07:01.23323-00:30\n2019-04-20T20:21:22.23+05:15\n"; + std::cout << "Running query: 4" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _2 from s3object where _2 like \"%11%\";"; + expected_res = "21169\n6611\n"; + std::cout << "Running query: 5" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _5 from s3object where _3 like \"__8\";"; + expected_res = "Bibby\n"; + std::cout << "Running query: 6" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); + + input_query = "select _2 from s3object where _2 like \"%11\";"; + expected_res = "6611\n"; + std::cout << "Running query: 7" << std::endl; + s3select_res = run_s3select(input_query, input_csv); + EXPECT_EQ(s3select_res, expected_res); +} + +TEST(TestS3selectFunctions, opserialization_expressions) +{ + std::string input; + size_t size = 10; + generate_rand_columns_csv(input, size); + + char a[5] = {'@', '#', '$', '%'}; + char b[4] = {'!', '^', '&', '*'}; + char x = a[rand() % 4]; + char y = b[rand() % 4]; + + const std::string input_query = "select * from s3object ;"; + + run_s3select_test_opserialization(input_query, input, &x, &y); + + const std::string input_query_1 = "select int(_1) from s3object where nullif(_1, _2) is not null;"; + + std::string s3select_result_1 = run_s3select_opserialization_quot(input_query_1,input, true); + + const std::string input_query_2 = "select int(_1) from s3object where int(_1) != int(_2);"; + + std::string s3select_result_2 = run_s3select(input_query_2,input); + + std::string s3select_result_2_final = string_to_quot(s3select_result_2); + + ASSERT_EQ(s3select_result_1, s3select_result_2_final); + + const std::string input_query_3 = "select int(_1) from s3object where int(_1) != int(_2);"; + + std::string s3select_result_3 = run_s3select_opserialization_quot(input_query_3,input); + + ASSERT_NE(s3select_result_1, s3select_result_3); + + const std::string input_query_4 = "select int(_1) from s3object where nullif(_1, _2) is not null;"; + + std::string s3select_result_4 = run_s3select_opserialization_quot(input_query_4,input, true, x); + + const std::string input_query_5 = "select int(_1) from s3object where int(_1) != int(_2);"; + + std::string s3select_result_5 = run_s3select(input_query_5,input); + + std::string s3select_result_5_final = string_to_quot(s3select_result_5, x); + + ASSERT_EQ(s3select_result_4, s3select_result_5_final); + + ASSERT_NE(s3select_result_4, s3select_result_1); +} + +void generate_csv_quote_and_escape(std::string& out, char quote = '"', char escp_ch = '\\') { + std::stringstream ss; + + ss << "1" << "," << " 1 " << "," << quote << "Apple" << "," << ":" << "," << "fruit" << quote << "," << "Apple" << "," << ":" << "," << "fruit" << std::endl; + ss << std::endl; + ss << "2" << "," << " 2" << "," << "Apple" << quote << "," << ":" << ","<< quote << "fruit" << "," << "Apple" << "," << ":" << "," << "fruit" << std::endl; + ss << " " << std::endl; + ss << "#3" << "," << "#3 " << "," << "Apple" << quote << "," << quote << ":" << quote << "," << quote << "fruit" << "," << "Apple" << "," << ":" << "," << "fruit" << std::endl; + ss << "4" << "," << " 4 " << "," << quote << quote << "Apple" << quote << "," << ":" << quote << quote << "," << quote << "fruit" << "," << "Apple" << "," << ":" << "," << "fruit" << std::endl; + ss << "5" << "," << "5 " << "," << "Apple" << escp_ch <<"," << ":" << escp_ch << "," << "fruit" << "," << "Apple" << "," << ":" << "," << "fruit" << std::endl; + + out = ss.str(); +} + +TEST(TestS3selectFunctions, csv_quote_string_and_escape_char) +{ + std::string input, s3select_result_1, s3select_result_2, s3select_result_3; + csv_object::csv_defintions csv; + generate_csv_quote_and_escape(input); + s3select s3select_syntax1, s3select_syntax2, s3select_syntax3; + + const std::string input_query_1 = "select _3 from s3object;"; + int status = s3select_syntax1.parse_query(input_query_1.c_str()); + ASSERT_EQ(status, 0); + + s3selectEngine::csv_object s3_csv_object_first(&s3select_syntax1, csv); + s3_csv_object_first.run_s3select_on_object(s3select_result_1, input.c_str(), input.size(), false, false, true); + + const std::string input_query_2 = "select _4,_5,_6 from s3object;"; + status = s3select_syntax2.parse_query(input_query_2.c_str()); + ASSERT_EQ(status, 0); + + s3selectEngine::csv_object s3_csv_object_second(&s3select_syntax2, csv); + s3_csv_object_second.run_s3select_on_object(s3select_result_2, input.c_str(), input.size(), false, false, true); + + EXPECT_EQ(s3select_result_1, s3select_result_2); + + csv.escape_char = '\0'; + csv.quot_char = '\0'; + + const std::string input_query_3 = "select * from s3object;"; + status = s3select_syntax3.parse_query(input_query_3.c_str()); + ASSERT_EQ(status, 0); + + s3selectEngine::csv_object s3_csv_object_third(&s3select_syntax3, csv); + s3_csv_object_third.run_s3select_on_object(s3select_result_3, input.c_str(), input.size(), false, false, true); + + EXPECT_EQ(s3select_result_3, input); +} + +TEST(TestS3selectFunctions, csv_comment_line_and_trim_char) +{ + std::string input; + std::string s3select_result_1, s3select_result_2; + generate_csv_quote_and_escape(input); + s3select s3select_syntax; + + csv_object::csv_defintions csv; + csv.comment_empty_lines = true; + csv.comment_chars.push_back('#'); + csv.trim_chars.push_back(' '); + csv.trim_chars.push_back('\t'); + + const std::string input_query_1 = "select _1 from s3object;"; + int status = s3select_syntax.parse_query(input_query_1.c_str()); + ASSERT_EQ(status, 0); + + s3selectEngine::csv_object s3_csv_object_first(&s3select_syntax, csv); + s3_csv_object_first.run_s3select_on_object(s3select_result_1, input.c_str(), input.size(), false, false, true); + + const std::string input_query_2 = "select _2 from s3object;"; + status = s3select_syntax.parse_query(input_query_2.c_str()); + ASSERT_EQ(status, 0); + + s3selectEngine::csv_object s3_csv_object_second(&s3select_syntax, csv); + s3_csv_object_second.run_s3select_on_object(s3select_result_2, input.c_str(), input.size(), false, false, true); + + EXPECT_EQ(s3select_result_1, s3select_result_2); +} + +TEST(TestS3selectFunctions, presto_syntax_alignments) +{ +/* + * the purpose of this test is to compare 2 queries with different syntax but with the same semantics + * differences are case-insensitive, table-alias, semicolon at the end-of-statement + */ + + std::string input; + size_t size = 10000; + + generate_rand_csv(input, size); + std::string input_for_presto = input; + + const std::string input_query = "select _1,_2 from s3object where _1 = _2;"; + + auto s3select_res = run_s3select(input_query, input); + + const std::string input_presto_query = "Select t._1,t._2 fRom s3OBJECT t whEre _1 = _2"; + + const char* json_query = "select _1.c1, _1.c2 from s3object[*].root where _1.c1 = _1.c2;"; + + auto s3select_presto_res = run_s3select(input_presto_query, input_for_presto, json_query); + + ASSERT_EQ(s3select_res, s3select_presto_res); + +} + +TEST(TestS3selectFunctions, csv_chunk_processing) +{ +//purpose: s3select processes chunk after chunk, doing so it needs to handle the "broken" line issue. +//i.e to identify partial line, save it and later merge it into with the other part on the next chunk. +// +#define STREAM_SIZE 1234 + std::string input_object, input_stream, s3select_result; + size_t input_off = 0,input_sz = 0; + int status; + s3selectEngine::csv_object::csv_defintions csv; + csv.use_header_info = false; + s3select s3select_syntax; + + + std::string input_query = "select * from stdin;"; + status = s3select_syntax.parse_query(input_query.c_str()); + s3selectEngine::csv_object s3_csv_object(&s3select_syntax, csv); + + generate_rand_csv(input_object, 10000); + size_t size_sum = 0; + std::string result_aggr; + + while(input_off<input_object.size()) + { + if ((input_object.size() - input_off) < STREAM_SIZE) + { + input_sz = (input_object.size() - input_off); + } + else + { + input_sz = STREAM_SIZE; + } + + size_sum += input_sz; + input_stream.assign(input_object.data() + input_off, input_object.data() + input_off + input_sz); + input_off += (input_sz); + + status = s3_csv_object.run_s3select_on_stream(s3select_result, input_stream.data(), input_stream.size(), input_object.size()); + + if(status<0) + { + std::cout << "failure on execution " << std::endl << s3_csv_object.get_error_description() << std::endl; + break; + } + + if(s3select_result.size()>0) + { + result_aggr.append(s3select_result); + s3select_result.clear(); + } + s3select_result.clear(); + }//while + + ASSERT_EQ(result_aggr,input_object); +} + +// JSON tests + +TEST(TestS3selectFunctions, json_queries) +{ + std::string json_input=R"( +{ +"firstName": "Joe", +"lastName": "Jackson", +"gender": "male", +"age": "twenty", +"address": { +"streetAddress": "101", +"city": "San Diego", +"state": "CA" +}, + +"firstName": "Joe_2", +"lastName": "Jackson_2", +"gender": "male", +"age": 21, +"address": { +"streetAddress": "101", +"city": "San Diego", +"state": "CA" +}, + +"phoneNumbers": [ +{ "type": "home1", "number": "734928_1","addr": 11 }, +{ "type": "home2", "number": "734928_2","addr": 22 }, +{ "type": "home3", "number": "734928_3","addr": 33 }, +{ "type": "home4", "number": "734928_4","addr": 44 }, +{ "type": "home5", "number": "734928_5","addr": 55 }, +{ "type": "home6", "number": "734928_6","addr": 66 }, +{ "type": "home7", "number": "734928_7","addr": 77 }, +{ "type": "home8", "number": "734928_8","addr": 88 }, +{ "type": "home9", "number": "734928_9","addr": 99 }, +{ "type": "home10", "number": "734928_10","addr": 100 } +], + +"key_after_array": "XXX", + +"description" : { + "main_desc" : "value_1", + "second_desc" : "value_2" +} + +} +)"; + + //count JSON structure, from-clause is empty. + std::string result; + const char* input_query = "select count(0) from s3object[*];"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,"1"); + + //count JSON structure, from-clause points an array of objects. + input_query = "select count(0) from s3object[*].phoneNumbers;"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,"10"); + + //select specific key in array, from-clause points an array of objects. + std::string expected_result=R"(11 +22 +33 +44 +55 +66 +77 +88 +99 +100 +)"; + input_query = "select _1.addr from s3object[*].phoneNumbers;"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + + //select specific keys in array, operation on fetched value, from-clause is empty. + expected_result=R"(Joe_2,XXX,25,value_1,value_2 +)"; + input_query = "select _1.firstname,_1.key_after_array,_1.age+4,_1.description.main_desc,_1.description.second_desc from s3object[*];"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +null,null,null +)"; + //select non-exists keys, from-clause points on array. + input_query = "select _1.firstname,_1.key_after_array,_1.age+4 from s3object[*].phonenumbers;"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(7349280 +)"; + + //select key, operation on value, with predicate(where-clause), from-clause points on array. + input_query = "select cast(substring(_1.number,1,6) as int) *10 from s3object[*].phonenumbers where _1.type='home2';"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(firstName. : Joe +lastName. : Jackson +gender. : male +age. : twenty +address.streetAddress. : 101 +address.city. : San Diego +address.state. : CA +firstName. : Joe_2 +lastName. : Jackson_2 +gender. : male +age. : 21 +address.streetAddress. : 101 +address.city. : San Diego +address.state. : CA +phoneNumbers.type. : home1 +phoneNumbers.number. : 734928_1 +phoneNumbers.addr. : 11 +phoneNumbers.type. : home2 +phoneNumbers.number. : 734928_2 +phoneNumbers.addr. : 22 +phoneNumbers.type. : home3 +phoneNumbers.number. : 734928_3 +phoneNumbers.addr. : 33 +phoneNumbers.type. : home4 +phoneNumbers.number. : 734928_4 +phoneNumbers.addr. : 44 +phoneNumbers.type. : home5 +phoneNumbers.number. : 734928_5 +phoneNumbers.addr. : 55 +phoneNumbers.type. : home6 +phoneNumbers.number. : 734928_6 +phoneNumbers.addr. : 66 +phoneNumbers.type. : home7 +phoneNumbers.number. : 734928_7 +phoneNumbers.addr. : 77 +phoneNumbers.type. : home8 +phoneNumbers.number. : 734928_8 +phoneNumbers.addr. : 88 +phoneNumbers.type. : home9 +phoneNumbers.number. : 734928_9 +phoneNumbers.addr. : 99 +phoneNumbers.type. : home10 +phoneNumbers.number. : 734928_10 +phoneNumbers.addr. : 100 +key_after_array. : XXX +description.main_desc. : value_1 +description.second_desc. : value_2 +#=== 0 ===# +)"; + + // star-operation on object, empty from-clause + input_query = "select * from s3object[*];"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(phoneNumbers.type. : home2 +phoneNumbers.number. : 734928_2 +phoneNumbers.addr. : 22 +#=== 0 ===# +phoneNumbers.type. : home3 +phoneNumbers.number. : 734928_3 +phoneNumbers.addr. : 33 +#=== 1 ===# +phoneNumbers.type. : home4 +phoneNumbers.number. : 734928_4 +phoneNumbers.addr. : 44 +#=== 2 ===# +phoneNumbers.type. : home5 +phoneNumbers.number. : 734928_5 +phoneNumbers.addr. : 55 +#=== 3 ===# +phoneNumbers.type. : home6 +phoneNumbers.number. : 734928_6 +phoneNumbers.addr. : 66 +#=== 4 ===# +phoneNumbers.type. : home7 +phoneNumbers.number. : 734928_7 +phoneNumbers.addr. : 77 +#=== 5 ===# +phoneNumbers.type. : home8 +phoneNumbers.number. : 734928_8 +phoneNumbers.addr. : 88 +#=== 6 ===# +)"; + + // star-operation on object, from-clause points on array, with where-clause + input_query = "select * from s3object[*].phonenumbers where _1.addr between 20 and 89;"; + run_json_query(input_query, json_input,result); + ASSERT_EQ(result,expected_result); + +} + +TEST(TestS3selectFunctions, json_queries_with_array) +{ + std::string result; + std::string expected_result; + std::string input_query; + + std::string INPUT_TEST_ARRAY_NEDICATIONS = R"( +{ +"problems": [{ + "Diabetes":[{ + "medications":[{ + "medicationsClasses":[{ + "className":[{ + "associatedDrug":[{ + "name":"asprin", + "dose":"", + "strength":"500 mg" + }, + { "name":"acamol" } + ], + "associatedDrug2":[{ + "name":"somethingElse", + "dose":"", + "strength":"500 mg" + }] + }], + "className2":[{ + "associatedDrug":[{ + "name":"asprin", + "dose":"", + "strength":"500 mg" + }], + "associatedDrug2":[{ + "name":"somethingElse", + "dose":"", + "strength":"500 mg" + }] + }] + }] + }], + "labs":[{ + "missing_field": "missing_value" + }] + }], + "Asthma":[{}] +}] +})"; + + expected_result=R"(acamol +)"; + + //access a JSON document containing a complex and nested arrays. this query accesses the object="name" at the second element of associatedDrug (within nested arrays) + input_query = "select _1.problems[0].Diabetes[0].medications[0].medicationsClasses[0].className[0].associatedDrug[1].name from s3object[*];"; + run_json_query(input_query.c_str(), INPUT_TEST_ARRAY_NEDICATIONS, result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(asprin +)"; + + //access a JSON document containing a complex and nested arrays. this query accesses the object="name" at the first element of associatedDrug (within nested arrays) + input_query = "select _1.problems[0].Diabetes[0].medications[0].medicationsClasses[0].className[0].associatedDrug[0].name from s3object[*];"; + run_json_query(input_query.c_str(), INPUT_TEST_ARRAY_NEDICATIONS, result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(somethingElse +)"; + //access a JSON document containing a complex and nested arrays. this query accesses the object="name" at the first element of associatedDrug2 (within nested arrays) + input_query = "select _1.problems[0].Diabetes[0].medications[0].medicationsClasses[0].className[0].associatedDrug2[0].name from s3object[*];"; + run_json_query(input_query.c_str(), INPUT_TEST_ARRAY_NEDICATIONS, result); + ASSERT_EQ(result,expected_result); + +} + +TEST(TestS3selectFunctions, json_queries_with_multi_dimensional_array) +{ + std::string result; + std::string expected_result; + std::string input_query; + + //return; //the syntax parser should be modified to accept array[1][2][3] + +std::string input_json_data = R"( +{ +"firstName": "Joe", +"lastName": "Jackson", +"gender": "male", +"age": "twenty", +"address": { +"streetAddress": "101", +"city": "San Diego", +"state": "CA" +}, + +"firstName": "Joe_2", +"lastName": "Jackson_2", +"gender": "male", +"age": 21, +"address": { +"streetAddress": "101", +"city": "San Diego", +"state": "CA" +}, + +"phoneNumbers": [ +{ "type": "home0", "number": "734928_0", "addr": 0 }, +{ "type": "home1", "number": "734928_1", "addr": 11 }, +{ "type": "home2", "number": "734928_2", "addr": 22 }, +{ "type": "home3", "number": "734928_3", "addr": 33 }, +{ "type": "home4", "number": "734928_4", "addr": 44 }, +{ "type": "home5", "number": "734928_5", "addr": 55 }, +{ "type": "home6", "number": "734928_6", "addr": 66 }, +{ "type": "home7", "number": "734928_7", "addr": 77 }, +{ "type": "home8", "number": "734928_8", "addr": 88 }, +{ "type": "home9", "number": "734928_9", "addr": 99 }, +{ "type": "home10", "number": "734928_10", "addr": 100 }, +"element-11", + [ 11 , 22 , + [ 44, 55] ,"post 3D" , + { + "first_key_in_object_in_array" : "value_for_irst_key_in_object_in_array", + "key_in_array" : "value_per_key_in_array" + } + ], + {"classname" : "stam"}, + { "associatedDrug":[{ + "name":"asprin", + "dose":"", + "strength":"500 mg" + }], + "associatedDrug#2":[{ + "name":"somethingElse", + "dose":"", + "strength":"500 mg" + }] +} +], +"key_after_array": "XXX" +} +)"; + + expected_result=R"(null +)"; + //phoneNumbers[12][2][2] is not a discrete value, should return null + input_query = "select _1.phoneNumbers[12][2][2] from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + //the following tests ia about accessing multi-dimension array + expected_result=R"(55 +)"; + input_query = "select _1.phoneNumbers[12][2][1] from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + + expected_result=R"(post 3D +)"; + input_query = "select _1.phoneNumbers[12][3] from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(11 +)"; + input_query = "select _1.phoneNumbers[12][0] from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(element-11 +)"; + input_query = "select _1.phoneNumbers[11] from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + +input_json_data = R"( +[ + { + "authors": [ + { + "id": 2312688602 + }, + { + "id": 123 + } + ], + "wrong" : {"id" : "it-is-wrong"} + } +] +)"; + + expected_result=R"(2312688602 +)"; + input_query = "select _1.authors[0].id from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + expected_result=R"(123 +)"; + input_query = "select _1.authors[1].id from s3object[*];"; + run_json_query(input_query.c_str(), input_json_data, result); + ASSERT_EQ(result,expected_result); + + + } |