| 194 | } |
| 195 | |
| 196 | Status SqliteStatement::Bind(size_t batch_index, int64_t row_index) { |
| 197 | if (batch_index >= parameters_.size()) { |
| 198 | return Status::IndexError("Cannot bind to batch ", batch_index); |
| 199 | } |
| 200 | const RecordBatch& batch = *parameters_[batch_index]; |
| 201 | if (row_index < 0 || row_index >= batch.num_rows()) { |
| 202 | return Status::IndexError("Cannot bind to row ", row_index, " in batch ", |
| 203 | batch_index); |
| 204 | } |
| 205 | |
| 206 | if (sqlite3_clear_bindings(stmt_) != SQLITE_OK) { |
| 207 | return Status::Invalid("Failed to reset bindings: ", sqlite3_errmsg(db_)); |
| 208 | } |
| 209 | for (int c = 0; c < batch.num_columns(); ++c) { |
| 210 | Array* column = batch.column(c).get(); |
| 211 | int64_t column_index = row_index; |
| 212 | if (column->type_id() == Type::DENSE_UNION) { |
| 213 | // Allow polymorphic bindings via union |
| 214 | const auto& u = checked_cast<const DenseUnionArray&>(*column); |
| 215 | column_index = u.value_offset(column_index); |
| 216 | column = u.field(u.child_id(row_index)).get(); |
| 217 | } |
| 218 | |
| 219 | int rc = 0; |
| 220 | if (column->IsNull(column_index)) { |
| 221 | rc = sqlite3_bind_null(stmt_, c + 1); |
| 222 | continue; |
| 223 | } |
| 224 | switch (column->type_id()) { |
| 225 | case Type::INT32: { |
| 226 | const int32_t value = |
| 227 | checked_cast<const Int32Array&>(*column).Value(column_index); |
| 228 | rc = sqlite3_bind_int64(stmt_, c + 1, value); |
| 229 | break; |
| 230 | } |
| 231 | case Type::INT64: { |
| 232 | const int64_t value = |
| 233 | checked_cast<const Int64Array&>(*column).Value(column_index); |
| 234 | rc = sqlite3_bind_int64(stmt_, c + 1, value); |
| 235 | break; |
| 236 | } |
| 237 | case Type::FLOAT: { |
| 238 | const float value = checked_cast<const FloatArray&>(*column).Value(column_index); |
| 239 | rc = sqlite3_bind_double(stmt_, c + 1, value); |
| 240 | break; |
| 241 | } |
| 242 | case Type::DOUBLE: { |
| 243 | const double value = |
| 244 | checked_cast<const DoubleArray&>(*column).Value(column_index); |
| 245 | rc = sqlite3_bind_double(stmt_, c + 1, value); |
| 246 | break; |
| 247 | } |
| 248 | case Type::STRING: { |
| 249 | const std::string_view value = |
| 250 | checked_cast<const StringArray&>(*column).Value(column_index); |
| 251 | rc = sqlite3_bind_text(stmt_, c + 1, value.data(), static_cast<int>(value.size()), |
| 252 | SQLITE_TRANSIENT); |
| 253 | break; |
no test coverage detected