@@ -3387,6 +3387,35 @@ void SQLTagStore::SizeGetter(const FunctionCallbackInfo<Value>& args) { |
3387 | 3387 | args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Size())); |
3388 | 3388 | } |
3389 | 3389 |
|
| 3390 | +bool SQLTagStore::ResetAndBindStatement( |
| 3391 | + Environment* env, |
| 3392 | + StatementSync* stmt, |
| 3393 | + const FunctionCallbackInfo<Value>& args) { |
| 3394 | + Isolate* isolate = env->isolate(); |
| 3395 | + int r = stmt->ResetStatement(); |
| 3396 | + CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, false); |
| 3397 | + |
| 3398 | + r = sqlite3_clear_bindings(stmt->statement_); |
| 3399 | + CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, false); |
| 3400 | + |
| 3401 | + uint32_t n_params = args.Length() - 1; |
| 3402 | + int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
| 3403 | + if (param_count != static_cast<int>(n_params)) { |
| 3404 | + THROW_ERR_INVALID_ARG_VALUE( |
| 3405 | + env, |
| 3406 | + "SQLite parameters must be bound using template literal placeholders."); |
| 3407 | + return false; |
| 3408 | + } |
| 3409 | + |
| 3410 | + for (int i = 0; i < param_count; ++i) { |
| 3411 | + if (!stmt->BindValue(args[i + 1], i + 1)) { |
| 3412 | + return false; |
| 3413 | + } |
| 3414 | + } |
| 3415 | + |
| 3416 | + return true; |
| 3417 | +} |
| 3418 | + |
3390 | 3419 | void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) { |
3391 | 3420 | SQLTagStore* session; |
3392 | 3421 | ASSIGN_OR_RETURN_UNWRAP(&session, args.This()); |
@@ -3401,15 +3430,8 @@ void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) { |
3401 | 3430 | return; |
3402 | 3431 | } |
3403 | 3432 |
|
3404 | | - uint32_t n_params = args.Length() - 1; |
3405 | | - int r = stmt->ResetStatement(); |
3406 | | - CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void()); |
3407 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3408 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3409 | | - Local<Value> value = args[i + 1]; |
3410 | | - if (!stmt->BindValue(value, i + 1)) { |
3411 | | - return; |
3412 | | - } |
| 3433 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3434 | + return; |
3413 | 3435 | } |
3414 | 3436 |
|
3415 | 3437 | Local<Object> result; |
@@ -3434,15 +3456,8 @@ void SQLTagStore::Iterate(const FunctionCallbackInfo<Value>& args) { |
3434 | 3456 | return; |
3435 | 3457 | } |
3436 | 3458 |
|
3437 | | - uint32_t n_params = args.Length() - 1; |
3438 | | - int r = stmt->ResetStatement(); |
3439 | | - CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void()); |
3440 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3441 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3442 | | - Local<Value> value = args[i + 1]; |
3443 | | - if (!stmt->BindValue(value, i + 1)) { |
3444 | | - return; |
3445 | | - } |
| 3459 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3460 | + return; |
3446 | 3461 | } |
3447 | 3462 |
|
3448 | 3463 | BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate( |
@@ -3469,18 +3484,8 @@ void SQLTagStore::Get(const FunctionCallbackInfo<Value>& args) { |
3469 | 3484 | return; |
3470 | 3485 | } |
3471 | 3486 |
|
3472 | | - uint32_t n_params = args.Length() - 1; |
3473 | | - Isolate* isolate = env->isolate(); |
3474 | | - |
3475 | | - int r = stmt->ResetStatement(); |
3476 | | - CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void()); |
3477 | | - |
3478 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3479 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3480 | | - Local<Value> value = args[i + 1]; |
3481 | | - if (!stmt->BindValue(value, i + 1)) { |
3482 | | - return; |
3483 | | - } |
| 3487 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3488 | + return; |
3484 | 3489 | } |
3485 | 3490 |
|
3486 | 3491 | Local<Value> result; |
@@ -3508,18 +3513,8 @@ void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) { |
3508 | 3513 | return; |
3509 | 3514 | } |
3510 | 3515 |
|
3511 | | - uint32_t n_params = args.Length() - 1; |
3512 | | - Isolate* isolate = env->isolate(); |
3513 | | - |
3514 | | - int r = stmt->ResetStatement(); |
3515 | | - CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void()); |
3516 | | - |
3517 | | - int param_count = sqlite3_bind_parameter_count(stmt->statement_); |
3518 | | - for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) { |
3519 | | - Local<Value> value = args[i + 1]; |
3520 | | - if (!stmt->BindValue(value, i + 1)) { |
3521 | | - return; |
3522 | | - } |
| 3516 | + if (!ResetAndBindStatement(env, stmt.get(), args)) { |
| 3517 | + return; |
3523 | 3518 | } |
3524 | 3519 |
|
3525 | 3520 | auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); }); |
|