1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7/* Test Case disclaimer
8 *
9 * Assertions built using the Domain Testing technique
10 * at: https://bbst.courses/wp-content/uploads/2018/01/Kaner-Intro-to-Domain-Testing-2018.pdf
11 *
12 */
13TEST_CASE("Prefix test", "[function]") {
14 unique_ptr<QueryResult> result;
15 DuckDB db(nullptr);
16 Connection con(db);
17 con.EnableQueryVerification();
18
19 SECTION("Early out prefix") {
20 result = con.Query("SELECT prefix('abcd', 'a')");
21 REQUIRE(CHECK_COLUMN(result, 0, {true}));
22 result = con.Query("SELECT prefix('abcd', 'ab')");
23 REQUIRE(CHECK_COLUMN(result, 0, {true}));
24 result = con.Query("SELECT prefix('abcd', 'abc')");
25 REQUIRE(CHECK_COLUMN(result, 0, {true}));
26 result = con.Query("SELECT prefix('abcd', 'abcd')");
27 REQUIRE(CHECK_COLUMN(result, 0, {true}));
28 result = con.Query("SELECT prefix('abcd', 'b')");
29 REQUIRE(CHECK_COLUMN(result, 0, {false}));
30 }
31
32 SECTION("Inlined string") {
33 result = con.Query("SELECT prefix('abcdefgh', 'a')");
34 REQUIRE(CHECK_COLUMN(result, 0, {true}));
35 result = con.Query("SELECT prefix('abcdefgh', 'ab')");
36 REQUIRE(CHECK_COLUMN(result, 0, {true}));
37 result = con.Query("SELECT prefix('abcdefgh', 'abc')");
38 REQUIRE(CHECK_COLUMN(result, 0, {true}));
39 result = con.Query("SELECT prefix('abcdefgh', 'abcd')");
40 REQUIRE(CHECK_COLUMN(result, 0, {true}));
41 result = con.Query("SELECT prefix('abcdefgh', 'abcde')");
42 REQUIRE(CHECK_COLUMN(result, 0, {true}));
43 result = con.Query("SELECT prefix('abcdefgh', 'b')");
44 REQUIRE(CHECK_COLUMN(result, 0, {false}));
45 }
46
47 SECTION("Stored pointer string") {
48 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'a')");
49 REQUIRE(CHECK_COLUMN(result, 0, {true}));
50 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'ab')");
51 REQUIRE(CHECK_COLUMN(result, 0, {true}));
52 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'abc')");
53 REQUIRE(CHECK_COLUMN(result, 0, {true}));
54 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'abcd')");
55 REQUIRE(CHECK_COLUMN(result, 0, {true}));
56 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'abcde')");
57 REQUIRE(CHECK_COLUMN(result, 0, {true}));
58 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'b')");
59 REQUIRE(CHECK_COLUMN(result, 0, {false}));
60
61 result = con.Query("SELECT prefix('abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwx')");
62 REQUIRE(CHECK_COLUMN(result, 0, {true}));
63 }
64
65 SECTION("Empty string and prefix") {
66 result = con.Query("SELECT prefix('', 'aaa')");
67 REQUIRE(CHECK_COLUMN(result, 0, {false}));
68
69 result = con.Query("SELECT prefix('aaa', '')");
70 REQUIRE(CHECK_COLUMN(result, 0, {true}));
71 }
72
73 SECTION("Issue #572 alloc exception on empty table") {
74 REQUIRE_NO_FAIL(con.Query("CREATE TABLE t0(c0 VARCHAR)"));
75 REQUIRE_NO_FAIL(con.Query("SELECT * FROM t0 WHERE PREFIX(t0.c0, '')"));
76 }
77
78 SECTION("Prefix test with UTF8") {
79 // átomo (atom)
80 result = con.Query("SELECT prefix('\xc3\xa1tomo', '\xc3\xa1')");
81 REQUIRE(CHECK_COLUMN(result, 0, {true}));
82 result = con.Query("SELECT prefix('\xc3\xa1tomo', 'á')");
83 REQUIRE(CHECK_COLUMN(result, 0, {true}));
84 result = con.Query("SELECT prefix('\xc3\xa1tomo', 'a')");
85 REQUIRE(CHECK_COLUMN(result, 0, {false}));
86
87 // olá mundo (hello world)
88 result = con.Query("SELECT prefix('ol\xc3\xa1 mundo', 'ol\xc3\xa1')");
89 REQUIRE(CHECK_COLUMN(result, 0, {true}));
90 result = con.Query("SELECT prefix('ol\xc3\xa1 mundo', 'olá')");
91 REQUIRE(CHECK_COLUMN(result, 0, {true}));
92 result = con.Query("SELECT prefix('ol\xc3\xa1 mundo', 'ola')");
93 REQUIRE(CHECK_COLUMN(result, 0, {false}));
94
95 //ñeft
96 result = con.Query("SELECT prefix('\xc3\xb1\x65\x66\x74', '\xc3\xb1')");
97 REQUIRE(CHECK_COLUMN(result, 0, {true}));
98 result = con.Query("SELECT prefix('\xc3\xb1\x65\x66\x74', 'ñ')");
99 REQUIRE(CHECK_COLUMN(result, 0, {true}));
100 result = con.Query("SELECT prefix('\xc3\xb1\x65\x66\x74', 'ñeft')");
101 REQUIRE(CHECK_COLUMN(result, 0, {true}));
102 result = con.Query("SELECT prefix('\xc3\xb1\x65\x66\x74', 'neft')");
103 REQUIRE(CHECK_COLUMN(result, 0, {false}));
104
105 // two ñ three ₡ four 🦆 end
106 string str_utf8 = "'two \xc3\xb1 three \xE2\x82\xA1 four \xF0\x9F\xA6\x86 end'";
107
108 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two \xc3\xb1')");
109 REQUIRE(CHECK_COLUMN(result, 0, {true}));
110 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ')");
111 REQUIRE(CHECK_COLUMN(result, 0, {true}));
112 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two n')");
113 REQUIRE(CHECK_COLUMN(result, 0, {false}));
114
115 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ three')");
116 REQUIRE(CHECK_COLUMN(result, 0, {true}));
117 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ three \xE2\x82\xA1')");
118 REQUIRE(CHECK_COLUMN(result, 0, {true}));
119 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ three \xE2\x82\xA1 four \xF0\x9F\xA6\x86')");
120 REQUIRE(CHECK_COLUMN(result, 0, {true}));
121 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ three \xE2\x82\xA1 four \xF0\x9F\xA6\x86 end')");
122 REQUIRE(CHECK_COLUMN(result, 0, {true}));
123 result = con.Query("SELECT prefix(" + str_utf8 + ", 'two ñ three ₡ four 🦆 end')");
124 REQUIRE(CHECK_COLUMN(result, 0, {true}));
125 }
126}
127