1# Handling Results 2 3The [`CassResult`](http://datastax.github.io/cpp-driver/api/struct.CassResult/) object 4is typically returned for `SELECT` statements. For mutations (`INSERT`, `UPDATE`, 5and `DELETE`) only a status code will be present and can be accessed using 6`cass_future_error_code()`. However, when using lightweight transactions a 7result object will be available to check the status of the transaction. The 8result object is obtained from executed statements' future object. 9 10**Important**: Rows, column values, collections, decimals, strings, and bytes 11objects are all invalidated when the result object is freed. All of these 12objects point to memory held by the result. This allows the driver to avoid 13unnecessarily copying data. 14 15```c 16void process_result(CassFuture* future) { 17 const CassResult* result = cass_future_get_result(future); 18 19 /* Process result */ 20 21 cass_result_free(result); 22} 23``` 24 25*Note*: The result object is immutable and can be accessed by multiple threads concurrently. 26 27## Rows and Column Values 28 29The result object represents a collection of rows. The first row, if present, 30can be obtained using `cass_result_first_row()`. Multiple rows are accessed 31using a [`CassIterator`](http://datastax.github.io/cpp-driver/api/struct.CassIterator/) 32object. After a row has been retrieved, the column value(s) can be accessed from 33a row by either index or by name. The iterator object can also be used with 34enumerated column values. 35 36```c 37void process_first_row(const CassResult* result) { 38 const CassRow* row = cass_result_first_row(result); 39 40 /* Get the first column value using the index */ 41 const CassValue* column1 = cass_row_get_column(row, 0); 42} 43``` 44 45```c 46void process_first_row_by_name(const CassResult* result) { 47 const CassRow* row = cass_result_first_row(result); 48 49 /* Get the value of the column named "column1" */ 50 const CassValue* column1 = cass_row_get_column_by_name(row, "column1"); 51} 52``` 53 54Once the [`CassValue`](http://datastax.github.io/cpp-driver/api/struct.CassValue/) 55has been obtained from the column, the actual value can be retrieved and 56assigned into the proper datatype. 57 58```c 59void get_values_from_row(const CassRow* row) { 60 cass_int32_t int_value; 61 const CassValue* column1 = cass_row_get_column(row, 0); 62 cass_value_get_int32(column1, &int_value); 63 64 cass_int64_t timestamp_value; 65 const CassValue* column2 = cass_row_get_column(row, 1); 66 cass_value_get_int64(column2, ×tamp_value); 67 68 const char* string_value; 69 size_t string_value_length; 70 const CassValue* column3 = cass_row_get_column(row, 2); 71 cass_value_get_string(column3, &string_value, &string_value_length); 72} 73``` 74 75## Iterators 76 77Iterators can be used to iterate over the rows in a result, the columns in a 78row, or the values in a collection. 79 80**Important**: `cass_iterator_next()` invalidates values retrieved by the 81previous iteration. 82 83```c 84void iterate_over_rows(CassFuture* future) { 85 const CassResult* result = cass_future_get_result(future); 86 87 CassIterator* iterator = cass_iterator_from_result(result); 88 89 while (cass_iterator_next(iterator)) { 90 const CassRow* row = cass_iterator_get_row(iterator); 91 /* Retreive and use values from the row */ 92 } 93 94 cass_iterator_free(iterator); 95 96 cass_result_free(result); 97} 98``` 99 100All iterators use the same pattern, but will have different iterator creation 101and retrieval functions. Iterating over a map collection is slightly different 102because it has two values per entry, but utilizes the same basic pattern. 103 104```c 105/* Execute SELECT query where a map colleciton is returned */ 106 107void iterator_over_map_value(CassFuture* future) { 108 const CassResult* result = cass_future_get_result(future); 109 110 const CassRow* row = cass_result_first_row(result); 111 112 const CassValue* map = cass_row_get_column(row, 0); 113 114 CassIterator* iterator = cass_iterator_from_map(map); 115 116 while (cass_iterator_next(iterator)) { 117 /* A seperate call is used to get the key and the value */ 118 const CassValue* key = cass_iterator_get_map_key(iterator); 119 const CassValue* value = cass_iterator_get_map_value(iterator); 120 121 /* Use key/value pair */ 122 } 123 124 cass_iterator_free(iterator); 125 126 cass_result_free(result); 127} 128``` 129 130## Paging 131 132When communicating with Cassandra 2.0 or later, large result sets can be divided 133into multiple pages automatically. The 134[`CassResult`](http://datastax.github.io/cpp-driver/api/struct.CassResult/) object 135keeps track of the pagination state for the sequence of paging queries. When 136paging through the result set, the result object is checked to see if more pages 137exist where it is then attached to the statement before re-executing the query 138to get the next page. 139 140```c 141void page_results(CassSession* session) { 142 143 CassStatement* statement = cass_statement_new("SELECT * FROM table1", 0); 144 145 /* Return a 100 rows every time this statement is executed */ 146 cass_statement_set_paging_size(statement, 100); 147 148 cass_bool_t has_more_pages = cass_true; 149 150 while (has_more_pages) { 151 CassFuture* query_future = cass_session_execute(session, statement); 152 153 const CassResult* result = cass_future_get_result(query_future); 154 155 if (result == NULL) { 156 157 /* Handle error */ 158 159 cass_future_free(query_future); 160 break; 161 } 162 163 /* Get values from result... */ 164 165 /* Check to see if there are more pages remaining for this result */ 166 has_more_pages = cass_result_has_more_pages(result); 167 168 if (has_more_pages) { 169 /* If there are more pages we need to set the position for the next execute */ 170 cass_statement_set_paging_state(statement, result); 171 } 172 173 cass_future_free(query_future); 174 cass_result_free(result); 175 } 176 177 cass_statement_free(statement); 178} 179``` 180 181The [`cass_statement_set_paging_state()`] function abstracts the actual paging 182state token away from the application. The raw paging state token can be 183accessed using [`cass_result_paging_state()`] and added to a statement using 184[`cass_statement_set_paging_state_token()`]. 185 186**Warning**: The paging state token should not be exposed to or come from 187untrusted environments. That paging state could be spoofed and potentially used 188to gain access to other data. 189 190[`cass_statement_set_paging_state()`]: http://datastax.github.io/cpp-driver/api/struct.CassStatement/#cass-statement-set-paging-state 191[`cass_result_paging_state()`]: http://datastax.github.io/cpp-driver/api/struct.CassResult/#cass-result-paging-state 192[`cass_statement_set_paging_state_token()`]: http://datastax.github.io/cpp-driver/api/struct.CassStatement/#cass-statement-set-paging-state-token 193