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 const CassSchemaMeta* schema_meta;
37
print_error(CassFuture * future)38 void print_error(CassFuture* future) {
39 const char* message;
40 size_t message_length;
41 cass_future_error_message(future, &message, &message_length);
42 fprintf(stderr, "Error: %.*s\n", (int)message_length, message);
43 }
44
create_cluster(const char * hosts)45 CassCluster* create_cluster(const char* hosts) {
46 CassCluster* cluster = cass_cluster_new();
47 cass_cluster_set_contact_points(cluster, hosts);
48 return cluster;
49 }
50
connect_session(CassSession * session,const CassCluster * cluster)51 CassError connect_session(CassSession* session, const CassCluster* cluster) {
52 CassError rc = CASS_OK;
53 CassFuture* future = cass_session_connect(session, cluster);
54
55 cass_future_wait(future);
56 rc = cass_future_error_code(future);
57 if (rc != CASS_OK) {
58 print_error(future);
59 }
60 cass_future_free(future);
61
62 return rc;
63 }
64
execute_query(CassSession * session,const char * query)65 CassError execute_query(CassSession* session, const char* query) {
66 CassError rc = CASS_OK;
67 CassFuture* future = NULL;
68 CassStatement* statement = cass_statement_new(query, 0);
69
70 future = cass_session_execute(session, statement);
71 cass_future_wait(future);
72
73 rc = cass_future_error_code(future);
74 if (rc != CASS_OK) {
75 print_error(future);
76 }
77
78 cass_future_free(future);
79 cass_statement_free(statement);
80
81 return rc;
82 }
83
insert_into_udt(CassSession * session)84 CassError insert_into_udt(CassSession* session) {
85 CassError rc = CASS_OK;
86 CassStatement* statement = NULL;
87 CassFuture* future = NULL;
88
89 CassUuid id;
90 char id_str[CASS_UUID_STRING_LENGTH];
91 const CassKeyspaceMeta* keyspace_meta = NULL;
92 const CassDataType* udt_address = NULL;
93 const CassDataType* udt_phone = NULL;
94
95 const char* query = "INSERT INTO examples.udt (id, address) VALUES (?, ?)";
96
97 statement = cass_statement_new(query, 2);
98
99 cass_uuid_gen_time(uuid_gen, &id);
100 cass_uuid_string(id, id_str);
101
102 keyspace_meta = cass_schema_meta_keyspace_by_name(schema_meta, "examples");
103 if (keyspace_meta != NULL) {
104 udt_address = cass_keyspace_meta_user_type_by_name(keyspace_meta, "address");
105 udt_phone = cass_keyspace_meta_user_type_by_name(keyspace_meta, "phone_numbers");
106 }
107
108 if (udt_address != NULL && udt_phone != NULL) {
109 int i;
110 CassUserType* address = cass_user_type_new_from_data_type(udt_address);
111 CassCollection* phone = cass_collection_new(CASS_COLLECTION_TYPE_SET, 2);
112
113 for (i = 0; i < 2; ++i) {
114 CassUserType* phone_numbers = cass_user_type_new_from_data_type(udt_phone);
115 cass_user_type_set_int32_by_name(phone_numbers, "phone1", i + 1);
116 cass_user_type_set_int32_by_name(phone_numbers, "phone2", i + 2);
117 cass_collection_append_user_type(phone, phone_numbers);
118 cass_user_type_free(phone_numbers);
119 }
120
121 cass_user_type_set_string_by_name(address, "street", id_str);
122 cass_user_type_set_string_by_name(address, "city", id_str);
123 cass_user_type_set_int32_by_name(address, "zip", (cass_int32_t)id.time_and_version);
124 cass_user_type_set_collection_by_name(address, "phone", phone);
125
126 cass_statement_bind_uuid(statement, 0, id);
127 cass_statement_bind_user_type(statement, 1, address);
128
129 future = cass_session_execute(session, statement);
130 cass_future_wait(future);
131
132 rc = cass_future_error_code(future);
133 if (rc != CASS_OK) {
134 print_error(future);
135 }
136
137 cass_future_free(future);
138 cass_user_type_free(address);
139 cass_collection_free(phone);
140 }
141
142 cass_statement_free(statement);
143
144 return rc;
145 }
146
select_from_udt(CassSession * session)147 CassError select_from_udt(CassSession* session) {
148 CassError rc = CASS_OK;
149 CassStatement* statement = NULL;
150 CassFuture* future = NULL;
151
152 const char* query = "SELECT * FROM examples.udt";
153
154 statement = cass_statement_new(query, 0);
155
156 future = cass_session_execute(session, statement);
157 cass_future_wait(future);
158
159 rc = cass_future_error_code(future);
160 if (rc != CASS_OK) {
161 print_error(future);
162 } else {
163 const CassResult* result = NULL;
164 CassIterator* rows = NULL;
165
166 result = cass_future_get_result(future);
167 rows = cass_iterator_from_result(result);
168
169 while (cass_iterator_next(rows)) {
170 CassUuid id;
171 char id_str[CASS_UUID_STRING_LENGTH];
172 const CassRow* row = cass_iterator_get_row(rows);
173 const CassValue* id_value = cass_row_get_column_by_name(row, "id");
174 const CassValue* address_value = cass_row_get_column_by_name(row, "address");
175 CassIterator* fields = cass_iterator_fields_from_user_type(address_value);
176
177 cass_value_get_uuid(id_value, &id);
178 cass_uuid_string(id, id_str);
179
180 printf("id %s ", id_str);
181
182 while (fields != NULL && cass_iterator_next(fields)) {
183 const char* field_name;
184 size_t field_name_length;
185 const CassValue* field_value = NULL;
186 cass_iterator_get_user_type_field_name(fields, &field_name, &field_name_length);
187 field_value = cass_iterator_get_user_type_field_value(fields);
188 printf("%.*s ", (int)field_name_length, field_name);
189
190 if (!cass_value_is_null(field_value)) {
191 if (cass_value_type(field_value) == CASS_VALUE_TYPE_VARCHAR) {
192 const char* text;
193 size_t text_length;
194 cass_value_get_string(field_value, &text, &text_length);
195 printf("\"%.*s\" ", (int)text_length, text);
196 } else if (cass_value_type(field_value) == CASS_VALUE_TYPE_INT) {
197 cass_int32_t i;
198 cass_value_get_int32(field_value, &i);
199 printf("%d ", i);
200 } else if (cass_value_type(field_value) == CASS_VALUE_TYPE_SET) {
201 CassIterator* phone_numbers = cass_iterator_from_collection(field_value);
202 while (cass_iterator_next(phone_numbers)) {
203 const CassValue* phone_value = cass_iterator_get_value(phone_numbers);
204 CassIterator* phone_fields = cass_iterator_fields_from_user_type(phone_value);
205 assert(cass_value_type(phone_value) == CASS_VALUE_TYPE_UDT);
206 while (cass_iterator_next(phone_fields)) {
207 const CassValue* phone_number_value =
208 cass_iterator_get_user_type_field_value(phone_fields);
209 cass_int32_t i;
210 cass_value_get_int32(phone_number_value, &i);
211 printf("%d ", i);
212 }
213 }
214 } else {
215 printf("<invalid> ");
216 }
217 } else {
218 printf("<null> ");
219 }
220 }
221
222 printf("\n");
223 }
224
225 cass_result_free(result);
226 cass_iterator_free(rows);
227 }
228
229 cass_future_free(future);
230 cass_statement_free(statement);
231
232 return rc;
233 }
234
main(int argc,char * argv[])235 int main(int argc, char* argv[]) {
236 CassCluster* cluster = NULL;
237 CassSession* session = cass_session_new();
238 char* hosts = "127.0.0.1";
239 if (argc > 1) {
240 hosts = argv[1];
241 }
242 cluster = create_cluster(hosts);
243
244 uuid_gen = cass_uuid_gen_new();
245
246 if (connect_session(session, cluster) != CASS_OK) {
247 cass_cluster_free(cluster);
248 cass_session_free(session);
249 return -1;
250 }
251
252 execute_query(session, "CREATE KEYSPACE examples WITH replication = { \
253 'class': 'SimpleStrategy', 'replication_factor': '3' }");
254
255 execute_query(session, "CREATE TYPE examples.phone_numbers (phone1 int, phone2 int)");
256
257 execute_query(session, "CREATE TYPE examples.address (street text, city text, zip int, phone "
258 "set<frozen<phone_numbers>>)");
259
260 execute_query(
261 session, "CREATE TABLE examples.udt (id timeuuid, address frozen<address>, PRIMARY KEY(id))");
262
263 schema_meta = cass_session_get_schema_meta(session);
264
265 insert_into_udt(session);
266 select_from_udt(session);
267
268 cass_cluster_free(cluster);
269 cass_session_free(session);
270
271 cass_uuid_gen_free(uuid_gen);
272 cass_schema_meta_free(schema_meta);
273
274 return 0;
275 }
276