@@ -3431,6 +3431,35 @@ void SQLTagStore::SizeGetter(const FunctionCallbackInfo<Value>& args) { |
3431 | 3431 | args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Size())); |
3432 | 3432 | } |
3433 | 3433 |
|
| 3434 | +bool SQLTagStore::ResetAndBindStatement( |
| 3435 | + Environment* env, |
| 3436 | + StatementSync* stmt, |
| 3437 | + const FunctionCallbackInfo<Value>& args) { |
| 3438 | + Isolate* isolate = env->isolate(); |
| 3439 | + int r = stmt->ResetStatement(); |
| 3440 | + CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, false); |
| 3441 | + |
| 3442 | + r = sqlite3_clear_bindings(stmt->statement_); |
| 3443 | + CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, false); |
| 3444 | + |
| 3445 | + uint32_t n_params = args.Length() - 1; |
| 3446 | + int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
| 3447 | + if (param_count != static_cast<int>(n_params)) { |
| 3448 | + THROW_ERR_INVALID_ARG_VALUE( |
| 3449 | + env, |
| 3450 | + "SQLite parameters must be bound using template literal placeholders."); |
| 3451 | + return false; |
| 3452 | + } |
| 3453 | + |
| 3454 | + for (int i = 0; i < param_count; ++i) { |
| 3455 | + if (!stmt->BindValue(args[i + 1], i + 1)) { |
| 3456 | + return false; |
| 3457 | + } |
| 3458 | + } |
| 3459 | + |
| 3460 | + return true; |
| 3461 | +} |
| 3462 | + |
3434 | 3463 | void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) { |
3435 | 3464 | SQLTagStore* session; |
3436 | 3465 | ASSIGN_OR_RETURN_UNWRAP(&session, args.This()); |
@@ -3445,15 +3474,8 @@ void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) { |
3445 | 3474 | return; |
3446 | 3475 | } |
3447 | 3476 |
|
3448 | | - uint32_t n_params = args.Length() - 1; |
3449 | | - int r = stmt->ResetStatement(); |
3450 | | - CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void()); |
3451 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3452 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3453 | | - Local<Value> value = args[i + 1]; |
3454 | | - if (!stmt->BindValue(value, i + 1)) { |
3455 | | - return; |
3456 | | - } |
| 3477 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3478 | + return; |
3457 | 3479 | } |
3458 | 3480 |
|
3459 | 3481 | Local<Object> result; |
@@ -3478,15 +3500,8 @@ void SQLTagStore::Iterate(const FunctionCallbackInfo<Value>& args) { |
3478 | 3500 | return; |
3479 | 3501 | } |
3480 | 3502 |
|
3481 | | - uint32_t n_params = args.Length() - 1; |
3482 | | - int r = stmt->ResetStatement(); |
3483 | | - CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void()); |
3484 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3485 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3486 | | - Local<Value> value = args[i + 1]; |
3487 | | - if (!stmt->BindValue(value, i + 1)) { |
3488 | | - return; |
3489 | | - } |
| 3503 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3504 | + return; |
3490 | 3505 | } |
3491 | 3506 |
|
3492 | 3507 | BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate( |
@@ -3513,18 +3528,8 @@ void SQLTagStore::Get(const FunctionCallbackInfo<Value>& args) { |
3513 | 3528 | return; |
3514 | 3529 | } |
3515 | 3530 |
|
3516 | | - uint32_t n_params = args.Length() - 1; |
3517 | | - Isolate* isolate = env->isolate(); |
3518 | | - |
3519 | | - int r = stmt->ResetStatement(); |
3520 | | - CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void()); |
3521 | | - |
3522 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3523 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3524 | | - Local<Value> value = args[i + 1]; |
3525 | | - if (!stmt->BindValue(value, i + 1)) { |
3526 | | - return; |
3527 | | - } |
| 3531 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3532 | + return; |
3528 | 3533 | } |
3529 | 3534 |
|
3530 | 3535 | Local<Value> result; |
@@ -3552,18 +3557,8 @@ void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) { |
3552 | 3557 | return; |
3553 | 3558 | } |
3554 | 3559 |
|
3555 | | - uint32_t n_params = args.Length() - 1; |
3556 | | - Isolate* isolate = env->isolate(); |
3557 | | - |
3558 | | - int r = stmt->ResetStatement(); |
3559 | | - CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void()); |
3560 | | - |
3561 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3562 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3563 | | - Local<Value> value = args[i + 1]; |
3564 | | - if (!stmt->BindValue(value, i + 1)) { |
3565 | | - return; |
3566 | | - } |
| 3560 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3561 | + return; |
3567 | 3562 | } |
3568 | 3563 |
|
3569 | 3564 | auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); }); |
|