-
Notifications
You must be signed in to change notification settings - Fork 0
/
sample-app.c
181 lines (138 loc) · 4.24 KB
/
sample-app.c
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libpq-fe.h"
#define HOST "127.0.0.1"
#define PORT "5433"
#define DB_NAME "yugabyte"
#define USER "yugabyte"
#define PASSWORD "yugabyte"
// Uncomment and define the SSL settings for YugabyteDB Managed and other secured deployments
// #define SSL_MODE ""
// #define SSL_ROOT_CERT ""
#ifdef SSL_MODE
#define CONN_STR "host=" HOST " port=" PORT " dbname=" DB_NAME \
" user=" USER " password=" PASSWORD \
" sslmode=" SSL_MODE " sslrootcert=" SSL_ROOT_CERT
#else
#define CONN_STR "host=" HOST " port=" PORT " dbname=" DB_NAME \
" user=" USER " password=" PASSWORD
#endif
PGconn *connect();
void createDatabase(PGconn *conn);
void selectAccounts(PGconn *conn);
void printErrorAndExit(PGconn *conn, PGresult *res);
void transferMoneyBetweenAccounts(PGconn *conn);
int main(int argc, char **argv)
{
PGconn *conn;
conn = connect();
createDatabase(conn);
selectAccounts(conn);
transferMoneyBetweenAccounts(conn);
selectAccounts(conn);
PQfinish(conn);
return 0;
}
PGconn *connect()
{
PGconn *conn;
printf(">>>> Connecting to YugabyteDB!\n");
PQinitSSL(1);
conn = PQconnectdb(CONN_STR);
if (PQstatus(conn) != CONNECTION_OK)
{
printErrorAndExit(conn, NULL);
}
printf(">>>> Successfully connected to YugabyteDB!\n");
return conn;
}
void createDatabase(PGconn *conn)
{
PGresult *res;
res = PQexec(conn, "DROP TABLE IF EXISTS DemoAccount");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
res = PQexec(conn, "CREATE TABLE DemoAccount ( \
id int PRIMARY KEY, \
name varchar, \
age int, \
country varchar, \
balance int)");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
res = PQexec(conn, "INSERT INTO DemoAccount VALUES \
(1, 'Jessica', 28, 'USA', 10000), \
(2, 'John', 28, 'Canada', 9000)");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
PQclear(res);
printf(">>>> Successfully created table DemoAccount.\n");
}
void selectAccounts(PGconn *conn)
{
PGresult *res;
int i;
printf(">>>> Selecting accounts:\n");
res = PQexec(conn, "SELECT name, age, country, balance FROM DemoAccount");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
printErrorAndExit(conn, res);
}
for (i = 0; i < PQntuples(res); i++)
{
printf("name = %s, age = %s, country = %s, balance = %s\n",
PQgetvalue(res, i, 0), PQgetvalue(res, i, 1), PQgetvalue(res, i, 2), PQgetvalue(res, i, 3));
}
PQclear(res);
}
void transferMoneyBetweenAccounts(PGconn *conn)
{
PGresult *res;
res = PQexec(conn, "BEGIN TRANSACTION");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
res = PQexec(conn, "UPDATE DemoAccount SET balance = balance - 800 WHERE name = \'Jessica\'");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
res = PQexec(conn, "UPDATE DemoAccount SET balance = balance + 800 WHERE name = \'John\'");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
res = PQexec(conn, "COMMIT");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printErrorAndExit(conn, res);
}
PQclear(res);
printf(">>>> Transferred 800 between accounts\n");
}
void printErrorAndExit(PGconn *conn, PGresult *res)
{
char *errCode;
if (res)
{
errCode = PQresultErrorField(res, PG_DIAG_SQLSTATE);
// Applies to logic of the transferMoneyBetweenAccounts method
if (errCode && strcmp(errCode, "40001"))
{
printf("The operation is aborted due to a concurrent transaction that is modifying the same set of rows. \
Consider adding retry logic or switch to the pessimistic locking.\n");
}
PQclear(res);
}
fprintf(stderr, "%s", PQerrorMessage(conn));
PQfinish(conn);
exit(1);
}