1 /*
2   This is free and unencumbered software released into the public domain.
3 
4   Anyone is free to copy, modify, publish, use, compile, sell, or
5   distribute this software, either in source code form or as a compiled
6   binary, for any purpose, commercial or non-commercial, and by any
7   means.
8 
9   In jurisdictions that recognize copyright laws, the author or authors
10   of this software dedicate any and all copyright interest in the
11   software to the public domain. We make this dedication for the benefit
12   of the public at large and to the detriment of our heirs and
13   successors. We intend this dedication to be an overt act of
14   relinquishment in perpetuity of all present and future rights to this
15   software under copyright law.
16 
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23   OTHER DEALINGS IN THE SOFTWARE.
24 
25   For more information, please refer to <http://unlicense.org/>
26 */
27 
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "cassandra.h"
34 
35 CassUuidGen* uuid_gen;
36 
print_error(CassFuture * future)37 void print_error(CassFuture* future) {
38   const char* message;
39   size_t message_length;
40   cass_future_error_message(future, &message, &message_length);
41   fprintf(stderr, "Error: %.*s\n", (int)message_length, message);
42 }
43 
create_cluster(const char * hosts)44 CassCluster* create_cluster(const char* hosts) {
45   CassCluster* cluster = cass_cluster_new();
46   cass_cluster_set_contact_points(cluster, hosts);
47   return cluster;
48 }
49 
connect_session(CassSession * session,const CassCluster * cluster)50 CassError connect_session(CassSession* session, const CassCluster* cluster) {
51   CassError rc = CASS_OK;
52   CassFuture* future = cass_session_connect(session, cluster);
53 
54   cass_future_wait(future);
55   rc = cass_future_error_code(future);
56   if (rc != CASS_OK) {
57     print_error(future);
58   }
59   cass_future_free(future);
60 
61   return rc;
62 }
63 
execute_query(CassSession * session,const char * query)64 CassError execute_query(CassSession* session, const char* query) {
65   CassError rc = CASS_OK;
66   CassFuture* future = NULL;
67   CassStatement* statement = cass_statement_new(query, 0);
68 
69   future = cass_session_execute(session, statement);
70   cass_future_wait(future);
71 
72   rc = cass_future_error_code(future);
73   if (rc != CASS_OK) {
74     print_error(future);
75   }
76 
77   cass_future_free(future);
78   cass_statement_free(statement);
79 
80   return rc;
81 }
82 
prepare_query(CassSession * session,const char * query,const CassPrepared ** prepared)83 CassError prepare_query(CassSession* session, const char* query, const CassPrepared** prepared) {
84   CassError rc = CASS_OK;
85   CassFuture* future = NULL;
86 
87   future = cass_session_prepare(session, query);
88   cass_future_wait(future);
89 
90   rc = cass_future_error_code(future);
91   if (rc != CASS_OK) {
92     print_error(future);
93   } else {
94     *prepared = cass_future_get_prepared(future);
95   }
96 
97   cass_future_free(future);
98 
99   return rc;
100 }
101 
insert_into_tuple(CassSession * session)102 CassError insert_into_tuple(CassSession* session) {
103   CassError rc = CASS_OK;
104   CassStatement* statement = NULL;
105   CassFuture* future = NULL;
106 
107   CassUuid id;
108   char id_str[CASS_UUID_STRING_LENGTH];
109   CassTuple* item = NULL;
110 
111   const char* query = "INSERT INTO examples.tuples (id, item) VALUES (?, ?)";
112 
113   statement = cass_statement_new(query, 2);
114 
115   cass_uuid_gen_time(uuid_gen, &id);
116   cass_uuid_string(id, id_str);
117 
118   item = cass_tuple_new(2);
119 
120   cass_tuple_set_string(item, 0, id_str);
121   cass_tuple_set_int64(item, 1, id.time_and_version);
122 
123   cass_statement_bind_uuid(statement, 0, id);
124   cass_statement_bind_tuple(statement, 1, item);
125 
126   future = cass_session_execute(session, statement);
127   cass_future_wait(future);
128 
129   rc = cass_future_error_code(future);
130   if (rc != CASS_OK) {
131     print_error(future);
132   }
133 
134   cass_future_free(future);
135   cass_statement_free(statement);
136   cass_tuple_free(item);
137 
138   return rc;
139 }
140 
select_from_tuple(CassSession * session)141 CassError select_from_tuple(CassSession* session) {
142   CassError rc = CASS_OK;
143   CassStatement* statement = NULL;
144   CassFuture* future = NULL;
145 
146   const char* query = "SELECT * FROM examples.tuples";
147 
148   statement = cass_statement_new(query, 0);
149 
150   future = cass_session_execute(session, statement);
151   cass_future_wait(future);
152 
153   rc = cass_future_error_code(future);
154   if (rc != CASS_OK) {
155     print_error(future);
156   } else {
157     const CassResult* result = NULL;
158     CassIterator* rows = NULL;
159 
160     result = cass_future_get_result(future);
161     rows = cass_iterator_from_result(result);
162 
163     while (cass_iterator_next(rows)) {
164       CassUuid id;
165       char id_str[CASS_UUID_STRING_LENGTH];
166       const CassRow* row = cass_iterator_get_row(rows);
167       const CassValue* id_value = cass_row_get_column_by_name(row, "id");
168       const CassValue* item_value = cass_row_get_column_by_name(row, "item");
169       CassIterator* item = cass_iterator_from_tuple(item_value);
170 
171       cass_value_get_uuid(id_value, &id);
172       cass_uuid_string(id, id_str);
173 
174       printf("id %s ", id_str);
175 
176       while (cass_iterator_next(item)) {
177         const CassValue* value = cass_iterator_get_value(item);
178 
179         if (!cass_value_is_null(value)) {
180           if (cass_value_type(value) == CASS_VALUE_TYPE_VARCHAR) {
181             const char* text;
182             size_t text_length;
183             cass_value_get_string(value, &text, &text_length);
184             printf("\"%.*s\" ", (int)text_length, text);
185           } else if (cass_value_type(value) == CASS_VALUE_TYPE_BIGINT) {
186             cass_int64_t i;
187             cass_value_get_int64(value, &i);
188             printf("%lld ", (long long int)i);
189           } else {
190             printf("<invalid> ");
191           }
192         } else {
193           printf("<null> ");
194         }
195       }
196 
197       printf("\n");
198     }
199 
200     cass_result_free(result);
201     cass_iterator_free(rows);
202   }
203 
204   cass_future_free(future);
205   cass_statement_free(statement);
206 
207   return rc;
208 }
209 
main(int argc,char * argv[])210 int main(int argc, char* argv[]) {
211   CassCluster* cluster = NULL;
212   CassSession* session = cass_session_new();
213   char* hosts = "127.0.0.1";
214   if (argc > 1) {
215     hosts = argv[1];
216   }
217   cluster = create_cluster(hosts);
218 
219   uuid_gen = cass_uuid_gen_new();
220 
221   if (connect_session(session, cluster) != CASS_OK) {
222     cass_cluster_free(cluster);
223     cass_session_free(session);
224     return -1;
225   }
226 
227   execute_query(session, "CREATE KEYSPACE examples WITH replication = { \
228                            'class': 'SimpleStrategy', 'replication_factor': '3' }");
229 
230   execute_query(session, "CREATE TABLE examples.tuples (id timeuuid, item frozen<tuple<text, "
231                          "bigint>>, PRIMARY KEY(id))");
232 
233   insert_into_tuple(session);
234   select_from_tuple(session);
235 
236   cass_cluster_free(cluster);
237   cass_session_free(session);
238 
239   cass_uuid_gen_free(uuid_gen);
240 
241   return 0;
242 }
243