File: test_pending_with_parameters.cpp

package info (click to toggle)
duckdb 1.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 299,196 kB
  • sloc: cpp: 865,414; ansic: 57,292; python: 18,871; sql: 12,663; lisp: 11,751; yacc: 7,412; lex: 1,682; sh: 747; makefile: 558
file content (135 lines) | stat: -rw-r--r-- 4,035 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "catch.hpp"
#include "test_helpers.hpp"

using namespace duckdb;
using namespace std;

static void CreateSimpleTable(Connection &con) {
	REQUIRE_NO_FAIL(con.Query("CREATE TABLE a (i TINYINT)"));
	REQUIRE_NO_FAIL(con.Query("INSERT INTO a VALUES (11), (12), (13)"));
}

static void ModifySimpleTable(Connection &con) {
	REQUIRE_NO_FAIL(con.Query("INSERT INTO a VALUES (14)"));
	REQUIRE_NO_FAIL(con.Query("DELETE FROM a where i=12"));
}

static void CheckSimpleQuery(Connection &con) {
	auto statements = con.ExtractStatements("SELECT COUNT(*) FROM a WHERE i=12");
	REQUIRE(statements.size() == 1);
	duckdb::vector<duckdb::Value> values = {Value(12)};
	auto pending_result = con.PendingQuery("SELECT COUNT(*) FROM a WHERE i=?", values, true);

	if (pending_result->HasError()) {
		printf("%s\n", pending_result->GetError().c_str());
	}

	REQUIRE(!pending_result->HasError());

	auto result = pending_result->Execute();
	REQUIRE(CHECK_COLUMN(result, 0, {1}));
}

static void CheckCatalogErrorQuery(Connection &con) {
	duckdb::vector<Value> values = {Value(12)};
	auto pending_result = con.PendingQuery("SELECT COUNT(*) FROM b WHERE i=?", values, true);
	REQUIRE((pending_result->HasError() && pending_result->GetErrorType() == ExceptionType::CATALOG));
}

static void CheckConversionErrorQuery(Connection &con) {
	// Check query with invalid prepared value
	duckdb::vector<Value> values = {Value("fawakaaniffoo")};
	auto pending_result = con.PendingQuery("SELECT COUNT(*) FROM a WHERE i=?", values, true);
	REQUIRE(!pending_result->HasError());
	auto result = pending_result->Execute();
	REQUIRE((result->HasError() && result->GetErrorType() == ExceptionType::CONVERSION));
}

static void CheckSimpleQueryAfterModification(Connection &con) {
	duckdb::vector<Value> values = {Value(14)};
	auto pending_result = con.PendingQuery("SELECT COUNT(*) FROM a WHERE i=?", values, true);
	REQUIRE(!pending_result->HasError());
	auto result = pending_result->Execute();
	REQUIRE(CHECK_COLUMN(result, 0, {1}));
}

TEST_CASE("Pending Query with Parameters", "[api]") {
	DuckDB db(nullptr);
	Connection con(db);
	con.EnableQueryVerification();

	CreateSimpleTable(con);
	CheckSimpleQuery(con);
	CheckSimpleQuery(con);
}

TEST_CASE("Pending Query with Parameters Catalog Error", "[api]") {
	DuckDB db(nullptr);
	Connection con(db);
	con.EnableQueryVerification();

	CreateSimpleTable(con);

	CheckCatalogErrorQuery(con);

	// Verify things are still sane
	CheckSimpleQuery(con);
}

TEST_CASE("Pending Query with Parameters Type Conversion Error", "[api]") {
	DuckDB db(nullptr);
	Connection con(db);
	con.EnableQueryVerification();

	CreateSimpleTable(con);

	CheckConversionErrorQuery(con);

	// Verify things are still sane
	CheckSimpleQuery(con);
}

TEST_CASE("Pending Query with Parameters with transactions", "[api]") {
	DuckDB db(nullptr);
	Connection con1(db);
	Connection con2(db);
	duckdb::vector<Value> empty_values = {};
	con1.EnableQueryVerification();

	CreateSimpleTable(con1);

	// CheckConversionErrorQuery(con1);

	// Begin a transaction in the PrepareAndExecute
	auto pending_result1 = con1.PendingQuery("BEGIN TRANSACTION", empty_values, true);
	if (pending_result1->HasError()) {
		printf("%s\n", pending_result1->GetError().c_str());
	}
	REQUIRE(!pending_result1->HasError());

	auto result1 = pending_result1->Execute();
	REQUIRE(!result1->HasError());
	CheckSimpleQuery(con1);

	// Modify table on other connection, leaving transaction open
	con2.BeginTransaction();
	ModifySimpleTable(con2);
	CheckSimpleQueryAfterModification(con2);

	// con1 sees nothing: both transactions are open
	CheckSimpleQuery(con1);

	con2.Commit();

	// con1 still sees nothing: its transaction was started before con2's
	CheckSimpleQuery(con1);

	// con 1 commits
	auto pending_result2 = con1.PendingQuery("COMMIT", empty_values, true);
	auto result2 = pending_result2->Execute();
	REQUIRE(!result2->HasError());

	// now con1 should see changes from con2
	CheckSimpleQueryAfterModification(con1);
	CheckSimpleQueryAfterModification(con2);
}