After sqlGenericQuery() returns SQLITE_ROW, you can call this function * with the 'row' object pointer in order to get the rows composing the * result set. It returns 1 if the next row is available, otherwise 0 * is returned (and the row object is freed). If you stop the iteration * before all the elements are used, you need to call sqlEnd(). */
| 132 | * is returned (and the row object is freed). If you stop the iteration |
| 133 | * before all the elements are used, you need to call sqlEnd(). */ |
| 134 | int sqlNextRow(sqlRow *row) { |
| 135 | if (row->stmt == NULL) return 0; |
| 136 | |
| 137 | if (row->col != NULL) { |
| 138 | if (sqlite3_step(row->stmt) != SQLITE_ROW) { |
| 139 | sqlEnd(row); |
| 140 | return 0; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | xfree(row->col); |
| 145 | row->cols = sqlite3_data_count(row->stmt); |
| 146 | row->col = xmalloc(row->cols*sizeof(sqlCol)); |
| 147 | for (int j = 0; j < row->cols; j++) { |
| 148 | row->col[j].type = sqlite3_column_type(row->stmt,j); |
| 149 | if (row->col[j].type == SQLITE_INTEGER) { |
| 150 | row->col[j].i = sqlite3_column_int64(row->stmt,j); |
| 151 | } else if (row->col[j].type == SQLITE_FLOAT) { |
| 152 | row->col[j].d = sqlite3_column_double(row->stmt,j); |
| 153 | } else if (row->col[j].type == SQLITE_TEXT) { |
| 154 | row->col[j].s = (char*)sqlite3_column_text(row->stmt,j); |
| 155 | row->col[j].i = sqlite3_column_bytes(row->stmt,j); |
| 156 | } else if (row->col[j].type == SQLITE_BLOB) { |
| 157 | row->col[j].s = sqlite3_column_blob(row->stmt,j); |
| 158 | row->col[j].i = sqlite3_column_bytes(row->stmt,j); |
| 159 | } else { |
| 160 | /* SQLITE_NULL. */ |
| 161 | row->col[j].s = NULL; |
| 162 | row->col[j].i = 0; |
| 163 | row->col[j].d = 0; |
| 164 | } |
| 165 | } |
| 166 | return 1; |
| 167 | } |
| 168 | |
| 169 | /* Wrapper for sqlGenericQuery() returning the last inserted ID or 0 |
| 170 | * on error. */ |
no test coverage detected