#include "node_sqlite.h"
#include <path.h>
#include "base_object-inl.h"
#include "debug_utils-inl.h"
#include "env-inl.h"
#include "memory_tracker-inl.h"
#include "node.h"
#include "node_errors.h"
#include "node_mem-inl.h"
#include "node_url.h"
#include "simdutf.h"
#include "sqlite3.h"
#include "threadpoolwork-inl.h"
#include "util-inl.h"

#include <array>
#include <cinttypes>
#include <cmath>
#include <limits>

namespace node {
namespace sqlite {

using v8::Array;
using v8::ArrayBuffer;
using v8::BackingStoreInitializationMode;
using v8::BackingStoreOnFailureMode;
using v8::BigInt;
using v8::Boolean;
using v8::ConstructorBehavior;
using v8::Context;
using v8::DictionaryTemplate;
using v8::DontDelete;
using v8::EscapableHandleScope;
using v8::Exception;
using v8::Function;
using v8::FunctionCallback;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Int32;
using v8::Integer;
using v8::Intercepted;
using v8::Isolate;
using v8::JustVoid;
using v8::Local;
using v8::LocalVector;
using v8::Maybe;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
using v8::Nothing;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::Promise;
using v8::PropertyCallbackInfo;
using v8::PropertyHandlerFlags;
using v8::SideEffectType;
using v8::String;
using v8::TryCatch;
using v8::Uint8Array;
using v8::Value;

inline MaybeLocal<String> Utf8StringMaybeOneByte(Isolate* isolate,
                                                 std::string_view input) {
  const int len = static_cast<int>(input.size());
  if (simdutf::validate_ascii(input.data(), input.size())) {
    return String::NewFromOneByte(
        isolate,
        reinterpret_cast<const uint8_t*>(input.data()),
        NewStringType::kNormal,
        len);
  }
  return String::NewFromUtf8(
      isolate, input.data(), NewStringType::kNormal, len);
}

#define CHECK_ERROR_OR_THROW(isolate, db, expr, expected, ret)                 \
  do {                                                                         \
    int r_ = (expr);                                                           \
    if (r_ != (expected)) {                                                    \
      THROW_ERR_SQLITE_ERROR((isolate), (db));                                 \
      return (ret);                                                            \
    }                                                                          \
  } while (0)

#define THROW_AND_RETURN_ON_BAD_STATE(env, condition, msg)                     \
  do {                                                                         \
    if ((condition)) {                                                         \
      THROW_ERR_INVALID_STATE((env), (msg));                                   \
      return;                                                                  \
    }                                                                          \
  } while (0)

#define SQLITE_VALUE_TO_JS(from, isolate, use_big_int_args, result, ...)       \
  do {                                                                         \
    switch (sqlite3_##from##_type(__VA_ARGS__)) {                              \
      case SQLITE_INTEGER: {                                                   \
        sqlite3_int64 val = sqlite3_##from##_int64(__VA_ARGS__);               \
        if ((use_big_int_args)) {                                              \
          (result) = BigInt::New((isolate), val);                              \
        } else if (std::abs(val) <= kMaxSafeJsInteger) {                       \
          (result) = Number::New((isolate), val);                              \
        } else {                                                               \
          THROW_ERR_OUT_OF_RANGE((isolate),                                    \
                                 "Value is too large to be represented as a "  \
                                 "JavaScript number: %" PRId64,                \
                                 val);                                         \
        }                                                                      \
        break;                                                                 \
      }                                                                        \
      case SQLITE_FLOAT: {                                                     \
        (result) =                                                             \
            Number::New((isolate), sqlite3_##from##_double(__VA_ARGS__));      \
        break;                                                                 \
      }                                                                        \
      case SQLITE_TEXT: {                                                      \
        const char* v =                                                        \
            reinterpret_cast<const char*>(sqlite3_##from##_text(__VA_ARGS__)); \
        const int v_len = sqlite3_##from##_bytes(__VA_ARGS__);                 \
        (result) =                                                             \
            Utf8StringMaybeOneByte((isolate), std::string_view(v, v_len))      \
                .As<Value>();                                                  \
        break;                                                                 \
      }                                                                        \
      case SQLITE_NULL: {                                                      \
        (result) = Null((isolate));                                            \
        break;                                                                 \
      }                                                                        \
      case SQLITE_BLOB: {                                                      \
        size_t size =                                                          \
            static_cast<size_t>(sqlite3_##from##_bytes(__VA_ARGS__));          \
        auto data = reinterpret_cast<const uint8_t*>(                          \
            sqlite3_##from##_blob(__VA_ARGS__));                               \
        auto store = ArrayBuffer::NewBackingStore(                             \
            (isolate), size, BackingStoreInitializationMode::kUninitialized);  \
        memcpy(store->Data(), data, size);                                     \
        auto ab = ArrayBuffer::New((isolate), std::move(store));               \
        (result) = Uint8Array::New(ab, 0, size);                               \
        break;                                                                 \
      }                                                                        \
      default:                                                                 \
        UNREACHABLE("Bad SQLite value");                                       \
    }                                                                          \
  } while (0)

namespace {
Local<DictionaryTemplate> getLazyIterTemplate(Environment* env) {
  auto iter_template = env->iter_template();
  if (iter_template.IsEmpty()) {
    static constexpr std::string_view iter_keys[] = {"done", "value"};
    iter_template = DictionaryTemplate::New(env->isolate(), iter_keys);
    env->set_iter_template(iter_template);
  }
  return iter_template;
}
}  // namespace

// Helper function to find limit info from JS property name
static constexpr const LimitInfo* GetLimitInfoFromName(std::string_view name) {
  for (const auto& info : kLimitMapping) {
    if (name == info.js_name) {
      return &info;
    }
  }
  return nullptr;
}

inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
                                            const char* message) {
  Local<String> js_msg;
  Local<Object> e;
  Environment* env = Environment::GetCurrent(isolate);
  if (!String::NewFromUtf8(isolate, message).ToLocal(&js_msg) ||
      !Exception::Error(js_msg)
           ->ToObject(isolate->GetCurrentContext())
           .ToLocal(&e) ||
      e->Set(isolate->GetCurrentContext(),
             env->code_string(),
             env->err_sqlite_error_string())
          .IsNothing()) {
    return MaybeLocal<Object>();
  }
  return e;
}

inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate, int errcode) {
  const char* errstr = sqlite3_errstr(errcode);
  Local<String> js_errmsg;
  Local<Object> e;
  Environment* env = Environment::GetCurrent(isolate);
  if (!String::NewFromUtf8(isolate, errstr).ToLocal(&js_errmsg) ||
      !CreateSQLiteError(isolate, errstr).ToLocal(&e) ||
      e->Set(env->context(),
             env->errcode_string(),
             Integer::New(isolate, errcode))
          .IsNothing() ||
      e->Set(env->context(), env->errstr_string(), js_errmsg).IsNothing()) {
    return MaybeLocal<Object>();
  }
  return e;
}

inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate, sqlite3* db) {
  int errcode = sqlite3_extended_errcode(db);
  const char* errstr = sqlite3_errstr(errcode);
  const char* errmsg = sqlite3_errmsg(db);
  Local<String> js_errmsg;
  Local<Object> e;
  Environment* env = Environment::GetCurrent(isolate);
  if (!String::NewFromUtf8(isolate, errstr).ToLocal(&js_errmsg) ||
      !CreateSQLiteError(isolate, errmsg).ToLocal(&e) ||
      e->Set(isolate->GetCurrentContext(),
             env->errcode_string(),
             Integer::New(isolate, errcode))
          .IsNothing() ||
      e->Set(isolate->GetCurrentContext(), env->errstr_string(), js_errmsg)
          .IsNothing()) {
    return MaybeLocal<Object>();
  }
  return e;
}

void JSValueToSQLiteResult(Isolate* isolate,
                           sqlite3_context* ctx,
                           Local<Value> value) {
  if (value->IsNullOrUndefined()) {
    sqlite3_result_null(ctx);
  } else if (value->IsNumber()) {
    sqlite3_result_double(ctx, value.As<Number>()->Value());
  } else if (value->IsString()) {
    Utf8Value val(isolate, value.As<String>());
    sqlite3_result_text(ctx, *val, val.length(), SQLITE_TRANSIENT);
  } else if (value->IsArrayBufferView()) {
    ArrayBufferViewContents<uint8_t> buf(value);
    sqlite3_result_blob(ctx, buf.data(), buf.length(), SQLITE_TRANSIENT);
  } else if (value->IsBigInt()) {
    bool lossless;
    int64_t as_int = value.As<BigInt>()->Int64Value(&lossless);
    if (!lossless) {
      sqlite3_result_error(ctx, "BigInt value is too large for SQLite", -1);
      return;
    }
    sqlite3_result_int64(ctx, as_int);
  } else if (value->IsPromise()) {
    sqlite3_result_error(
        ctx, "Asynchronous user-defined functions are not supported", -1);
  } else {
    sqlite3_result_error(
        ctx,
        "Returned JavaScript value cannot be converted to a SQLite value",
        -1);
  }
}

class DatabaseSync;

inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, DatabaseSync* db) {
  if (db->ShouldIgnoreSQLiteError()) {
    db->SetIgnoreNextSQLiteError(false);
    return;
  }

  Local<Object> e;
  if (CreateSQLiteError(isolate, db->Connection()).ToLocal(&e)) {
    isolate->ThrowException(e);
  }
}

inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, const char* message) {
  Local<Object> e;
  if (CreateSQLiteError(isolate, message).ToLocal(&e)) {
    isolate->ThrowException(e);
  }
}

inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, int errcode) {
  const char* errstr = sqlite3_errstr(errcode);

  Environment* env = Environment::GetCurrent(isolate);
  Local<Object> error;
  if (CreateSQLiteError(isolate, errstr).ToLocal(&error) &&
      error
          ->Set(isolate->GetCurrentContext(),
                env->errcode_string(),
                Integer::New(isolate, errcode))
          .IsJust()) {
    isolate->ThrowException(error);
  }
}

inline MaybeLocal<Value> NullableSQLiteStringToValue(Isolate* isolate,
                                                     const char* str) {
  if (str == nullptr) {
    return Null(isolate);
  }

  return String::NewFromUtf8(isolate, str, NewStringType::kInternalized)
      .As<Value>();
}

class CustomAggregate {
 public:
  explicit CustomAggregate(Environment* env,
                           DatabaseSync* db,
                           bool use_bigint_args,
                           Local<Value> start,
                           Local<Function> step_fn,
                           Local<Function> inverse_fn,
                           Local<Function> result_fn)
      : env_(env),
        db_(db),
        use_bigint_args_(use_bigint_args),
        start_(env->isolate(), start),
        step_fn_(env->isolate(), step_fn),
        inverse_fn_(env->isolate(), inverse_fn),
        result_fn_(env->isolate(), result_fn) {}

  static void xStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
    xStepBase(ctx, argc, argv, &CustomAggregate::step_fn_);
  }

  static void xInverse(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
    xStepBase(ctx, argc, argv, &CustomAggregate::inverse_fn_);
  }

  static void xFinal(sqlite3_context* ctx) { xValueBase(ctx, true); }

  static void xValue(sqlite3_context* ctx) { xValueBase(ctx, false); }

  static void xDestroy(void* self) {
    delete static_cast<CustomAggregate*>(self);
  }

 private:
  struct aggregate_data {
    Global<Value> value;
    bool initialized;
    bool is_window;
  };

  static inline void xStepBase(sqlite3_context* ctx,
                               int argc,
                               sqlite3_value** argv,
                               Global<Function> CustomAggregate::*mptr) {
    CustomAggregate* self =
        static_cast<CustomAggregate*>(sqlite3_user_data(ctx));
    Environment* env = self->env_;
    Isolate* isolate = env->isolate();
    auto agg = self->GetAggregate(ctx);

    if (!agg) {
      return;
    }

    auto recv = Undefined(isolate);
    LocalVector<Value> js_argv(isolate);
    js_argv.reserve(argc + 1);

    js_argv.emplace_back(Local<Value>::New(isolate, agg->value));

    for (int i = 0; i < argc; ++i) {
      sqlite3_value* value = argv[i];
      MaybeLocal<Value> js_val;
      SQLITE_VALUE_TO_JS(value, isolate, self->use_bigint_args_, js_val, value);
      if (js_val.IsEmpty()) {
        // Ignore the SQLite error because a JavaScript exception is pending.
        self->db_->SetIgnoreNextSQLiteError(true);
        sqlite3_result_error(ctx, "", 0);
        return;
      }

      Local<Value> local;
      if (!js_val.ToLocal(&local)) {
        // Ignore the SQLite error because a JavaScript exception is pending.
        self->db_->SetIgnoreNextSQLiteError(true);
        sqlite3_result_error(ctx, "", 0);
        return;
      }

      js_argv.emplace_back(local);
    }

    Local<Value> ret;
    if (!(self->*mptr)
             .Get(isolate)
             ->Call(env->context(), recv, argc + 1, js_argv.data())
             .ToLocal(&ret)) {
      self->db_->SetIgnoreNextSQLiteError(true);
      sqlite3_result_error(ctx, "", 0);
      return;
    }

    agg->value.Reset(isolate, ret);
  }

  static inline void xValueBase(sqlite3_context* ctx, bool is_final) {
    CustomAggregate* self =
        static_cast<CustomAggregate*>(sqlite3_user_data(ctx));
    Environment* env = self->env_;
    Isolate* isolate = env->isolate();
    auto agg = self->GetAggregate(ctx);

    if (!agg) {
      return;
    }

    if (!is_final) {
      agg->is_window = true;
    } else if (agg->is_window) {
      DestroyAggregateData(ctx);
      return;
    }

    Local<Value> result;
    if (!self->result_fn_.IsEmpty()) {
      Local<Function> fn =
          Local<Function>::New(env->isolate(), self->result_fn_);
      Local<Value> js_arg[] = {Local<Value>::New(isolate, agg->value)};

      if (!fn->Call(env->context(), Null(isolate), 1, js_arg)
               .ToLocal(&result)) {
        self->db_->SetIgnoreNextSQLiteError(true);
        sqlite3_result_error(ctx, "", 0);
      }
    } else {
      result = Local<Value>::New(isolate, agg->value);
    }

    if (!result.IsEmpty()) {
      JSValueToSQLiteResult(isolate, ctx, result);
    }

    if (is_final) {
      DestroyAggregateData(ctx);
    }
  }

  static void DestroyAggregateData(sqlite3_context* ctx) {
    aggregate_data* agg = static_cast<aggregate_data*>(
        sqlite3_aggregate_context(ctx, sizeof(aggregate_data)));
    CHECK(agg->initialized);
    agg->value.Reset();
  }

  aggregate_data* GetAggregate(sqlite3_context* ctx) {
    aggregate_data* agg = static_cast<aggregate_data*>(
        sqlite3_aggregate_context(ctx, sizeof(aggregate_data)));
    if (!agg->initialized) {
      Isolate* isolate = env_->isolate();
      Local<Value> start_v = Local<Value>::New(isolate, start_);
      if (start_v->IsFunction()) {
        auto fn = start_v.As<Function>();
        MaybeLocal<Value> retval =
            fn->Call(env_->context(), Null(isolate), 0, nullptr);
        if (!retval.ToLocal(&start_v)) {
          db_->SetIgnoreNextSQLiteError(true);
          sqlite3_result_error(ctx, "", 0);
          return nullptr;
        }
      }

      agg->value.Reset(env_->isolate(), start_v);
      agg->initialized = true;
    }

    return agg;
  }

  Environment* env_;
  DatabaseSync* db_;
  bool use_bigint_args_;
  Global<Value> start_;
  Global<Function> step_fn_;
  Global<Function> inverse_fn_;
  Global<Function> result_fn_;
};

class BackupJob : public ThreadPoolWork {
 public:
  explicit BackupJob(Environment* env,
                     DatabaseSync* source,
                     Local<Promise::Resolver> resolver,
                     std::string source_db,
                     std::string destination_name,
                     std::string dest_db,
                     int pages,
                     Local<Function> progressFunc)
      : ThreadPoolWork(env, "node_sqlite3.BackupJob"),
        env_(env),
        source_(source),
        pages_(pages),
        source_db_(std::move(source_db)),
        destination_name_(std::move(destination_name)),
        dest_db_(std::move(dest_db)) {
    resolver_.Reset(env->isolate(), resolver);
    progressFunc_.Reset(env->isolate(), progressFunc);
  }

  void ScheduleBackup() {
    Isolate* isolate = env()->isolate();
    HandleScope handle_scope(isolate);
    backup_status_ = sqlite3_open_v2(
        destination_name_.c_str(),
        &dest_,
        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI,
        nullptr);
    Local<Promise::Resolver> resolver =
        Local<Promise::Resolver>::New(env()->isolate(), resolver_);
    if (backup_status_ != SQLITE_OK) {
      HandleBackupError(resolver);
      return;
    }

    backup_ = sqlite3_backup_init(
        dest_, dest_db_.c_str(), source_->Connection(), source_db_.c_str());
    if (backup_ == nullptr) {
      HandleBackupError(resolver);
      return;
    }

    this->ScheduleWork();
  }

  void DoThreadPoolWork() override {
    backup_status_ = sqlite3_backup_step(backup_, pages_);
  }

  void AfterThreadPoolWork(int status) override {
    HandleScope handle_scope(env()->isolate());
    Local<Promise::Resolver> resolver =
        Local<Promise::Resolver>::New(env()->isolate(), resolver_);

    if (!(backup_status_ == SQLITE_OK || backup_status_ == SQLITE_DONE ||
          backup_status_ == SQLITE_BUSY || backup_status_ == SQLITE_LOCKED)) {
      HandleBackupError(resolver, backup_status_);
      return;
    }

    int total_pages = sqlite3_backup_pagecount(backup_);
    int remaining_pages = sqlite3_backup_remaining(backup_);
    if (remaining_pages != 0) {
      Local<Function> fn =
          Local<Function>::New(env()->isolate(), progressFunc_);
      if (!fn.IsEmpty()) {
        Local<Object> progress_info = Object::New(env()->isolate());
        if (progress_info
                ->Set(env()->context(),
                      env()->total_pages_string(),
                      Integer::New(env()->isolate(), total_pages))
                .IsNothing() ||
            progress_info
                ->Set(env()->context(),
                      env()->remaining_pages_string(),
                      Integer::New(env()->isolate(), remaining_pages))
                .IsNothing()) {
          return;
        }

        Local<Value> argv[] = {progress_info};
        TryCatch try_catch(env()->isolate());
        USE(fn->Call(env()->context(), Null(env()->isolate()), 1, argv));
        if (try_catch.HasCaught()) {
          Local<Value> exception = try_catch.Exception();
          Finalize();
          resolver->Reject(env()->context(), exception).ToChecked();
          delete this;
          return;
        }
      }

      // There's still work to do
      this->ScheduleWork();
      return;
    }

    if (backup_status_ != SQLITE_DONE) {
      HandleBackupError(resolver);
      return;
    }

    Finalize();
    resolver
        ->Resolve(env()->context(), Integer::New(env()->isolate(), total_pages))
        .ToChecked();
    delete this;
  }

  void Finalize() {
    Cleanup();
    if (source_) {
      source_->RemoveBackup(this);
      source_.reset();
    }
  }

  void Cleanup() {
    if (backup_) {
      sqlite3_backup_finish(backup_);
      backup_ = nullptr;
    }

    if (dest_) {
      backup_status_ = sqlite3_errcode(dest_);
      sqlite3_close_v2(dest_);
      dest_ = nullptr;
    }
  }

 private:
  void HandleBackupError(Local<Promise::Resolver> resolver) {
    Local<Object> e;
    if (!CreateSQLiteError(env()->isolate(), dest_).ToLocal(&e)) {
      Finalize();
      delete this;
      return;
    }

    Finalize();
    resolver->Reject(env()->context(), e).ToChecked();
    delete this;
  }

  void HandleBackupError(Local<Promise::Resolver> resolver, int errcode) {
    Local<Object> e;
    if (!CreateSQLiteError(env()->isolate(), errcode).ToLocal(&e)) {
      Finalize();
      delete this;
      return;
    }

    Finalize();
    resolver->Reject(env()->context(), e).ToChecked();
    delete this;
  }

  Environment* env() const { return env_; }

  Environment* env_;
  BaseObjectPtr<DatabaseSync> source_;
  Global<Promise::Resolver> resolver_;
  Global<Function> progressFunc_;
  sqlite3* dest_ = nullptr;
  sqlite3_backup* backup_ = nullptr;
  int pages_;
  int backup_status_ = SQLITE_OK;
  std::string source_db_;
  std::string destination_name_;
  std::string dest_db_;
};

UserDefinedFunction::UserDefinedFunction(Environment* env,
                                         Local<Function> fn,
                                         DatabaseSync* db,
                                         bool use_bigint_args)
    : env_(env),
      fn_(env->isolate(), fn),
      db_(db),
      use_bigint_args_(use_bigint_args) {}

UserDefinedFunction::~UserDefinedFunction() {}

void UserDefinedFunction::xFunc(sqlite3_context* ctx,
                                int argc,
                                sqlite3_value** argv) {
  UserDefinedFunction* self =
      static_cast<UserDefinedFunction*>(sqlite3_user_data(ctx));
  Environment* env = self->env_;
  Isolate* isolate = env->isolate();
  auto recv = Undefined(isolate);
  auto fn = self->fn_.Get(isolate);
  LocalVector<Value> js_argv(isolate);
  js_argv.reserve(argc);

  for (int i = 0; i < argc; ++i) {
    sqlite3_value* value = argv[i];
    MaybeLocal<Value> js_val = MaybeLocal<Value>();
    SQLITE_VALUE_TO_JS(value, isolate, self->use_bigint_args_, js_val, value);
    if (js_val.IsEmpty()) {
      // Ignore the SQLite error because a JavaScript exception is pending.
      self->db_->SetIgnoreNextSQLiteError(true);
      sqlite3_result_error(ctx, "", 0);
      return;
    }

    Local<Value> local;
    if (!js_val.ToLocal(&local)) {
      // Ignore the SQLite error because a JavaScript exception is pending.
      self->db_->SetIgnoreNextSQLiteError(true);
      sqlite3_result_error(ctx, "", 0);
      return;
    }

    js_argv.emplace_back(local);
  }

  MaybeLocal<Value> retval =
      fn->Call(env->context(), recv, argc, js_argv.data());
  Local<Value> result;
  if (!retval.ToLocal(&result)) {
    // Ignore the SQLite error because a JavaScript exception is pending.
    self->db_->SetIgnoreNextSQLiteError(true);
    sqlite3_result_error(ctx, "", 0);
    return;
  }

  JSValueToSQLiteResult(isolate, ctx, result);
}

void UserDefinedFunction::xDestroy(void* self) {
  delete static_cast<UserDefinedFunction*>(self);
}

DatabaseSyncLimits::DatabaseSyncLimits(Environment* env,
                                       Local<Object> object,
                                       BaseObjectWeakPtr<DatabaseSync> database)
    : BaseObject(env, object), database_(std::move(database)) {
  MakeWeak();
}

DatabaseSyncLimits::~DatabaseSyncLimits() = default;

void DatabaseSyncLimits::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("database", database_);
}

Local<ObjectTemplate> DatabaseSyncLimits::GetTemplate(Environment* env) {
  Local<ObjectTemplate> tmpl = env->sqlite_limits_template();
  if (!tmpl.IsEmpty()) return tmpl;

  Isolate* isolate = env->isolate();
  tmpl = ObjectTemplate::New(isolate);
  tmpl->SetInternalFieldCount(DatabaseSyncLimits::kInternalFieldCount);
  tmpl->SetHandler(NamedPropertyHandlerConfiguration(
      LimitsGetter,
      LimitsSetter,
      LimitsQuery,
      nullptr,  // deleter - not allowed
      LimitsEnumerator,
      nullptr,  // definer
      nullptr,
      Local<Value>(),
      PropertyHandlerFlags::kHasNoSideEffect));

  env->set_sqlite_limits_template(tmpl);
  return tmpl;
}

Intercepted DatabaseSyncLimits::LimitsGetter(
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
  // Skip symbols
  if (!property->IsString()) {
    return Intercepted::kNo;
  }

  DatabaseSyncLimits* limits;
  ASSIGN_OR_RETURN_UNWRAP(&limits, info.Holder(), Intercepted::kNo);

  Environment* env = limits->env();
  Isolate* isolate = env->isolate();

  Utf8Value prop_name(isolate, property);
  const LimitInfo* limit_info = GetLimitInfoFromName(prop_name.ToStringView());

  if (limit_info == nullptr) {
    return Intercepted::kNo;  // Unknown property, let default handling occur
  }

  if (!limits->database_ || !limits->database_->IsOpen()) {
    THROW_ERR_INVALID_STATE(env, "database is not open");
    return Intercepted::kYes;
  }

  int current_value = sqlite3_limit(
      limits->database_->Connection(), limit_info->sqlite_limit_id, -1);
  info.GetReturnValue().Set(Integer::New(isolate, current_value));
  return Intercepted::kYes;
}

Intercepted DatabaseSyncLimits::LimitsSetter(
    Local<Name> property,
    Local<Value> value,
    const PropertyCallbackInfo<Boolean>& info) {
  if (!property->IsString()) {
    return Intercepted::kNo;
  }

  DatabaseSyncLimits* limits;
  ASSIGN_OR_RETURN_UNWRAP(&limits, info.Holder(), Intercepted::kNo);

  Environment* env = limits->env();
  Isolate* isolate = env->isolate();

  Utf8Value prop_name(isolate, property);
  const LimitInfo* limit_info = GetLimitInfoFromName(prop_name.ToStringView());

  if (limit_info == nullptr) {
    return Intercepted::kNo;
  }

  if (!limits->database_ || !limits->database_->IsOpen()) {
    THROW_ERR_INVALID_STATE(env, "database is not open");
    return Intercepted::kYes;
  }

  if (!value->IsNumber()) {
    THROW_ERR_INVALID_ARG_TYPE(
        isolate, "Limit value must be a non-negative integer or Infinity.");
    return Intercepted::kYes;
  }

  const double num_value = value.As<Number>()->Value();
  int new_value;

  if (std::isinf(num_value) && num_value > 0) {
    // Positive Infinity resets the limit to the compile-time maximum
    new_value = std::numeric_limits<int>::max();
  } else if (!value->IsInt32()) {
    THROW_ERR_INVALID_ARG_TYPE(
        isolate, "Limit value must be a non-negative integer or Infinity.");
    return Intercepted::kYes;
  } else {
    new_value = value.As<Int32>()->Value();
    if (new_value < 0) {
      THROW_ERR_OUT_OF_RANGE(isolate, "Limit value must be non-negative.");
      return Intercepted::kYes;
    }
  }

  sqlite3_limit(
      limits->database_->Connection(), limit_info->sqlite_limit_id, new_value);
  return Intercepted::kYes;
}

Intercepted DatabaseSyncLimits::LimitsQuery(
    Local<Name> property, const PropertyCallbackInfo<Integer>& info) {
  if (!property->IsString()) {
    return Intercepted::kNo;
  }

  Isolate* isolate = info.GetIsolate();
  Utf8Value prop_name(isolate, property);
  const LimitInfo* limit_info = GetLimitInfoFromName(prop_name.ToStringView());

  if (!limit_info) {
    return Intercepted::kNo;
  }

  // Property exists and is writable
  info.GetReturnValue().Set(
      Integer::New(isolate, v8::PropertyAttribute::DontDelete));
  return Intercepted::kYes;
}

void DatabaseSyncLimits::LimitsEnumerator(
    const PropertyCallbackInfo<Array>& info) {
  Isolate* isolate = info.GetIsolate();
  LocalVector<Value> names(isolate);

  for (const auto& [js_name, sqlite_limit_id] : kLimitMapping) {
    Local<String> name;
    if (!String::NewFromUtf8(
             isolate, js_name.data(), NewStringType::kNormal, js_name.size())
             .ToLocal(&name)) {
      return;
    }
    names.push_back(name);
  }

  info.GetReturnValue().Set(Array::New(isolate, names.data(), names.size()));
}

BaseObjectPtr<DatabaseSyncLimits> DatabaseSyncLimits::Create(
    Environment* env, BaseObjectWeakPtr<DatabaseSync> database) {
  Local<Object> obj;
  if (!GetTemplate(env)->NewInstance(env->context()).ToLocal(&obj)) {
    return nullptr;
  }

  return MakeBaseObject<DatabaseSyncLimits>(env, obj, std::move(database));
}

DatabaseSync::DatabaseSync(Environment* env,
                           Local<Object> object,
                           DatabaseOpenConfiguration&& open_config,
                           bool open,
                           bool allow_load_extension)
    : BaseObject(env, object), open_config_(std::move(open_config)) {
  MakeWeak();
  connection_ = nullptr;
  allow_load_extension_ = allow_load_extension;
  enable_load_extension_ = allow_load_extension;
  ignore_next_sqlite_error_ = false;

  if (open) {
    Open();
  }
}

void DatabaseSync::AddBackup(BackupJob* job) {
  backups_.insert(job);
}

void DatabaseSync::RemoveBackup(BackupJob* job) {
  backups_.erase(job);
}

void DatabaseSync::DeleteSessions() {
  // all attached sessions need to be deleted before the database is closed
  // https://www.sqlite.org/session/sqlite3session_create.html
  for (auto* session : sessions_) {
    sqlite3session_delete(session);
  }
  sessions_.clear();
}

DatabaseSync::~DatabaseSync() {
  FinalizeBackups();

  if (IsOpen()) {
    FinalizeStatements();
    DeleteSessions();
    sqlite3_close_v2(connection_);
    connection_ = nullptr;
  }
}

void DatabaseSync::MemoryInfo(MemoryTracker* tracker) const {
  // TODO(tniessen): more accurately track the size of all fields
  tracker->TrackFieldWithSize(
      "open_config", sizeof(open_config_), "DatabaseOpenConfiguration");
}

bool DatabaseSync::Open() {
  if (IsOpen()) {
    THROW_ERR_INVALID_STATE(env(), "database is already open");
    return false;
  }

  // TODO(cjihrig): Support additional flags.
  int default_flags = SQLITE_OPEN_URI;
  int flags = open_config_.get_read_only()
                  ? SQLITE_OPEN_READONLY
                  : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  int r = sqlite3_open_v2(open_config_.location().c_str(),
                          &connection_,
                          flags | default_flags,
                          nullptr);
  CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);

  r = sqlite3_db_config(connection_,
                        SQLITE_DBCONFIG_DQS_DML,
                        static_cast<int>(open_config_.get_enable_dqs()),
                        nullptr);
  CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);
  r = sqlite3_db_config(connection_,
                        SQLITE_DBCONFIG_DQS_DDL,
                        static_cast<int>(open_config_.get_enable_dqs()),
                        nullptr);
  CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);

  int foreign_keys_enabled;
  r = sqlite3_db_config(
      connection_,
      SQLITE_DBCONFIG_ENABLE_FKEY,
      static_cast<int>(open_config_.get_enable_foreign_keys()),
      &foreign_keys_enabled);
  CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);
  CHECK_EQ(foreign_keys_enabled, open_config_.get_enable_foreign_keys());

  int defensive_enabled;
  r = sqlite3_db_config(connection_,
                        SQLITE_DBCONFIG_DEFENSIVE,
                        static_cast<int>(open_config_.get_enable_defensive()),
                        &defensive_enabled);
  CHECK_ERROR_OR_THROW(env()->isolate(), this, r, SQLITE_OK, false);
  CHECK_EQ(defensive_enabled, open_config_.get_enable_defensive());

  sqlite3_busy_timeout(connection_, open_config_.get_timeout());

  // Apply initial limits
  for (const auto& [js_name, sqlite_limit_id] : kLimitMapping) {
    const auto& limit_value = open_config_.initial_limits()[sqlite_limit_id];
    if (limit_value.has_value()) {
      sqlite3_limit(connection_, sqlite_limit_id, *limit_value);
    }
  }

  if (allow_load_extension_) {
    if (env()->permission()->enabled()) [[unlikely]] {
      THROW_ERR_LOAD_SQLITE_EXTENSION(env(),
                                      "Cannot load SQLite extensions when the "
                                      "permission model is enabled.");
      return false;
    }
    const int load_extension_ret = sqlite3_db_config(
        connection_, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr);
    CHECK_ERROR_OR_THROW(
        env()->isolate(), this, load_extension_ret, SQLITE_OK, false);
  }

  return true;
}

void DatabaseSync::FinalizeBackups() {
  for (auto backup : backups_) {
    backup->Cleanup();
  }

  backups_.clear();
}

void DatabaseSync::FinalizeStatements() {
  for (auto stmt : statements_) {
    stmt->Finalize();
  }

  statements_.clear();
}

void DatabaseSync::UntrackStatement(StatementSync* statement) {
  auto it = statements_.find(statement);
  if (it != statements_.end()) {
    statements_.erase(it);
  }
}

inline bool DatabaseSync::IsOpen() {
  return connection_ != nullptr;
}

inline sqlite3* DatabaseSync::Connection() {
  return connection_;
}

void DatabaseSync::SetIgnoreNextSQLiteError(bool ignore) {
  ignore_next_sqlite_error_ = ignore;
}

bool DatabaseSync::ShouldIgnoreSQLiteError() {
  return ignore_next_sqlite_error_;
}

void DatabaseSync::CreateTagStore(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db = BaseObject::Unwrap<DatabaseSync>(args.This());
  Environment* env = Environment::GetCurrent(args);

  if (!db->IsOpen()) {
    THROW_ERR_INVALID_STATE(env, "database is not open");
    return;
  }
  int capacity = 1000;
  if (args.Length() > 0 && args[0]->IsNumber()) {
    capacity = args[0].As<Number>()->Value();
  }

  BaseObjectPtr<SQLTagStore> session =
      SQLTagStore::Create(env, BaseObjectWeakPtr<DatabaseSync>(db), capacity);
  if (!session) {
    // Handle error if creation failed
    THROW_ERR_SQLITE_ERROR(env->isolate(), "Failed to create SQLTagStore");
    return;
  }
  args.GetReturnValue().Set(session->object());
}

std::optional<std::string> ValidateDatabasePath(Environment* env,
                                                Local<Value> path,
                                                const std::string& field_name) {
  constexpr auto has_null_bytes = [](std::string_view str) {
    return str.find('\0') != std::string_view::npos;
  };
  if (path->IsString()) {
    Utf8Value location(env->isolate(), path.As<String>());
    if (!has_null_bytes(location.ToStringView())) {
      return location.ToString();
    }
  } else if (path->IsUint8Array()) {
    Local<Uint8Array> buffer = path.As<Uint8Array>();
    size_t byteOffset = buffer->ByteOffset();
    size_t byteLength = buffer->ByteLength();
    auto data =
        static_cast<const uint8_t*>(buffer->Buffer()->Data()) + byteOffset;
    if (std::find(data, data + byteLength, 0) == data + byteLength) {
      return std::string(reinterpret_cast<const char*>(data), byteLength);
    }
  } else if (path->IsObject()) {  // When is URL
    auto url = path.As<Object>();
    Local<Value> href;
    if (url->Get(env->context(), env->href_string()).ToLocal(&href) &&
        href->IsString()) {
      Utf8Value location_value(env->isolate(), href.As<String>());
      auto location = location_value.ToStringView();
      if (!has_null_bytes(location)) {
        CHECK(ada::can_parse(location));
        if (!location.starts_with("file:")) {
          THROW_ERR_INVALID_URL_SCHEME(env->isolate());
          return std::nullopt;
        }

        return location_value.ToString();
      }
    }
  }

  THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                             "The \"%s\" argument must be a string, "
                             "Uint8Array, or URL without null bytes.",
                             field_name);

  return std::nullopt;
}

void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  if (!args.IsConstructCall()) {
    THROW_ERR_CONSTRUCT_CALL_REQUIRED(env);
    return;
  }

  std::optional<std::string> location =
      ValidateDatabasePath(env, args[0], "path");
  if (!location.has_value()) {
    return;
  }

  DatabaseOpenConfiguration open_config(std::move(location.value()));
  bool open = true;
  bool allow_load_extension = false;
  if (args.Length() > 1) {
    if (!args[1]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[1].As<Object>();
    Local<String> open_string = FIXED_ONE_BYTE_STRING(env->isolate(), "open");
    Local<Value> open_v;
    if (!options->Get(env->context(), open_string).ToLocal(&open_v)) {
      return;
    }
    if (!open_v->IsUndefined()) {
      if (!open_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(), "The \"options.open\" argument must be a boolean.");
        return;
      }
      open = open_v.As<Boolean>()->Value();
    }

    Local<String> read_only_string =
        FIXED_ONE_BYTE_STRING(env->isolate(), "readOnly");
    Local<Value> read_only_v;
    if (!options->Get(env->context(), read_only_string).ToLocal(&read_only_v)) {
      return;
    }
    if (!read_only_v->IsUndefined()) {
      if (!read_only_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.readOnly\" argument must be a boolean.");
        return;
      }
      open_config.set_read_only(read_only_v.As<Boolean>()->Value());
    }

    Local<String> enable_foreign_keys_string =
        FIXED_ONE_BYTE_STRING(env->isolate(), "enableForeignKeyConstraints");
    Local<Value> enable_foreign_keys_v;
    if (!options->Get(env->context(), enable_foreign_keys_string)
             .ToLocal(&enable_foreign_keys_v)) {
      return;
    }
    if (!enable_foreign_keys_v->IsUndefined()) {
      if (!enable_foreign_keys_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.enableForeignKeyConstraints\" argument must be a "
            "boolean.");
        return;
      }
      open_config.set_enable_foreign_keys(
          enable_foreign_keys_v.As<Boolean>()->Value());
    }

    Local<String> enable_dqs_string = FIXED_ONE_BYTE_STRING(
        env->isolate(), "enableDoubleQuotedStringLiterals");
    Local<Value> enable_dqs_v;
    if (!options->Get(env->context(), enable_dqs_string)
             .ToLocal(&enable_dqs_v)) {
      return;
    }
    if (!enable_dqs_v->IsUndefined()) {
      if (!enable_dqs_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.enableDoubleQuotedStringLiterals\" argument must be "
            "a boolean.");
        return;
      }
      open_config.set_enable_dqs(enable_dqs_v.As<Boolean>()->Value());
    }

    Local<String> allow_extension_string =
        FIXED_ONE_BYTE_STRING(env->isolate(), "allowExtension");
    Local<Value> allow_extension_v;
    if (!options->Get(env->context(), allow_extension_string)
             .ToLocal(&allow_extension_v)) {
      return;
    }

    if (!allow_extension_v->IsUndefined()) {
      if (!allow_extension_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.allowExtension\" argument must be a boolean.");
        return;
      }
      allow_load_extension = allow_extension_v.As<Boolean>()->Value();
    }

    Local<Value> timeout_v;
    if (!options->Get(env->context(), env->timeout_string())
             .ToLocal(&timeout_v)) {
      return;
    }

    if (!timeout_v->IsUndefined()) {
      if (!timeout_v->IsInt32()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.timeout\" argument must be an integer.");
        return;
      }

      open_config.set_timeout(timeout_v.As<Int32>()->Value());
    }

    Local<Value> read_bigints_v;
    if (options->Get(env->context(), env->read_bigints_string())
            .ToLocal(&read_bigints_v)) {
      if (!read_bigints_v->IsUndefined()) {
        if (!read_bigints_v->IsBoolean()) {
          THROW_ERR_INVALID_ARG_TYPE(
              env->isolate(),
              R"(The "options.readBigInts" argument must be a boolean.)");
          return;
        }
        open_config.set_use_big_ints(read_bigints_v.As<Boolean>()->Value());
      }
    }

    Local<Value> return_arrays_v;
    if (options->Get(env->context(), env->return_arrays_string())
            .ToLocal(&return_arrays_v)) {
      if (!return_arrays_v->IsUndefined()) {
        if (!return_arrays_v->IsBoolean()) {
          THROW_ERR_INVALID_ARG_TYPE(
              env->isolate(),
              R"(The "options.returnArrays" argument must be a boolean.)");
          return;
        }
        open_config.set_return_arrays(return_arrays_v.As<Boolean>()->Value());
      }
    }

    Local<Value> allow_bare_named_params_v;
    if (options->Get(env->context(), env->allow_bare_named_params_string())
            .ToLocal(&allow_bare_named_params_v)) {
      if (!allow_bare_named_params_v->IsUndefined()) {
        if (!allow_bare_named_params_v->IsBoolean()) {
          THROW_ERR_INVALID_ARG_TYPE(
              env->isolate(),
              R"(The "options.allowBareNamedParameters" )"
              "argument must be a boolean.");
          return;
        }
        open_config.set_allow_bare_named_params(
            allow_bare_named_params_v.As<Boolean>()->Value());
      }
    }

    Local<Value> allow_unknown_named_params_v;
    if (options->Get(env->context(), env->allow_unknown_named_params_string())
            .ToLocal(&allow_unknown_named_params_v)) {
      if (!allow_unknown_named_params_v->IsUndefined()) {
        if (!allow_unknown_named_params_v->IsBoolean()) {
          THROW_ERR_INVALID_ARG_TYPE(
              env->isolate(),
              R"(The "options.allowUnknownNamedParameters" )"
              "argument must be a boolean.");
          return;
        }
        open_config.set_allow_unknown_named_params(
            allow_unknown_named_params_v.As<Boolean>()->Value());
      }
    }

    Local<Value> defensive_v;
    if (!options->Get(env->context(), env->defensive_string())
             .ToLocal(&defensive_v)) {
      return;
    }
    if (!defensive_v->IsUndefined()) {
      if (!defensive_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.defensive\" argument must be a boolean.");
        return;
      }
      open_config.set_enable_defensive(defensive_v.As<Boolean>()->Value());
    }

    // Parse limits option
    Local<Value> limits_v;
    if (!options->Get(env->context(), env->limits_string())
             .ToLocal(&limits_v)) {
      return;
    }
    if (!limits_v->IsUndefined()) {
      if (!limits_v->IsObject()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.limits\" argument must be an object.");
        return;
      }

      Local<Object> limits_obj = limits_v.As<Object>();

      // Iterate through known limit names and extract values
      for (const auto& [js_name, sqlite_limit_id] : kLimitMapping) {
        Local<String> key;
        if (!String::NewFromUtf8(env->isolate(),
                                 js_name.data(),
                                 NewStringType::kNormal,
                                 js_name.size())
                 .ToLocal(&key)) {
          return;
        }

        Local<Value> val;
        if (!limits_obj->Get(env->context(), key).ToLocal(&val)) {
          return;
        }

        if (!val->IsUndefined()) {
          if (!val->IsInt32()) {
            std::string msg = "The \"options.limits." + std::string(js_name) +
                              "\" argument must be an integer.";
            THROW_ERR_INVALID_ARG_TYPE(env->isolate(), msg);
            return;
          }

          int limit_val = val.As<Int32>()->Value();
          if (limit_val < 0) {
            std::string msg = "The \"options.limits." + std::string(js_name) +
                              "\" argument must be non-negative.";
            THROW_ERR_OUT_OF_RANGE(env->isolate(), msg);
            return;
          }

          open_config.set_initial_limit(sqlite_limit_id, limit_val);
        }
      }
    }
  }

  new DatabaseSync(
      env, args.This(), std::move(open_config), open, allow_load_extension);
}

void DatabaseSync::Open(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  db->Open();
}

void DatabaseSync::IsOpenGetter(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  args.GetReturnValue().Set(db->IsOpen());
}

void DatabaseSync::IsTransactionGetter(
    const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
  args.GetReturnValue().Set(sqlite3_get_autocommit(db->connection_) == 0);
}

void DatabaseSync::LimitsGetter(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);

  Local<Value> limits_val =
      db->object()->GetInternalField(kLimitsObject).template As<Value>();

  if (limits_val->IsUndefined()) {
    BaseObjectPtr<DatabaseSyncLimits> limits =
        DatabaseSyncLimits::Create(env, BaseObjectWeakPtr<DatabaseSync>(db));
    if (limits) {
      db->object()->SetInternalField(kLimitsObject, limits->object());
      args.GetReturnValue().Set(limits->object());
    }
  } else {
    args.GetReturnValue().Set(limits_val);
  }
}

void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
  db->FinalizeStatements();
  db->DeleteSessions();
  int r = sqlite3_close_v2(db->connection_);
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
  db->connection_ = nullptr;
}

void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  Close(args);
  if (try_catch.HasCaught()) {
    CHECK(try_catch.CanContinue());
  }
}

void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  if (!args[0]->IsString()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"sql\" argument must be a string.");
    return;
  }

  std::optional<bool> return_arrays;
  std::optional<bool> use_big_ints;
  std::optional<bool> allow_bare_named_params;
  std::optional<bool> allow_unknown_named_params;

  if (args.Length() > 1 && !args[1]->IsUndefined()) {
    if (!args[1]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }
    Local<Object> options = args[1].As<Object>();

    Local<Value> return_arrays_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "returnArrays"))
             .ToLocal(&return_arrays_v)) {
      return;
    }
    if (!return_arrays_v->IsUndefined()) {
      if (!return_arrays_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.returnArrays\" argument must be a boolean.");
        return;
      }
      return_arrays = return_arrays_v->IsTrue();
    }

    Local<Value> read_big_ints_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "readBigInts"))
             .ToLocal(&read_big_ints_v)) {
      return;
    }
    if (!read_big_ints_v->IsUndefined()) {
      if (!read_big_ints_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.readBigInts\" argument must be a boolean.");
        return;
      }
      use_big_ints = read_big_ints_v->IsTrue();
    }

    Local<Value> allow_bare_named_params_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(),
                                         "allowBareNamedParameters"))
             .ToLocal(&allow_bare_named_params_v)) {
      return;
    }
    if (!allow_bare_named_params_v->IsUndefined()) {
      if (!allow_bare_named_params_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.allowBareNamedParameters\" argument must be a "
            "boolean.");
        return;
      }
      allow_bare_named_params = allow_bare_named_params_v->IsTrue();
    }

    Local<Value> allow_unknown_named_params_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(),
                                         "allowUnknownNamedParameters"))
             .ToLocal(&allow_unknown_named_params_v)) {
      return;
    }
    if (!allow_unknown_named_params_v->IsUndefined()) {
      if (!allow_unknown_named_params_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.allowUnknownNamedParameters\" argument must be a "
            "boolean.");
        return;
      }
      allow_unknown_named_params = allow_unknown_named_params_v->IsTrue();
    }
  }

  Utf8Value sql(env->isolate(), args[0].As<String>());
  sqlite3_stmt* s = nullptr;
  int r = sqlite3_prepare_v2(db->connection_, *sql, -1, &s, nullptr);

  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
  BaseObjectPtr<StatementSync> stmt =
      StatementSync::Create(env, BaseObjectPtr<DatabaseSync>(db), s);
  db->statements_.insert(stmt.get());

  if (return_arrays.has_value()) {
    stmt->return_arrays_ = return_arrays.value();
  }
  if (use_big_ints.has_value()) {
    stmt->use_big_ints_ = use_big_ints.value();
  }
  if (allow_bare_named_params.has_value()) {
    stmt->allow_bare_named_params_ = allow_bare_named_params.value();
  }
  if (allow_unknown_named_params.has_value()) {
    stmt->allow_unknown_named_params_ = allow_unknown_named_params.value();
  }

  args.GetReturnValue().Set(stmt->object());
}

void DatabaseSync::Exec(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  if (!args[0]->IsString()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"sql\" argument must be a string.");
    return;
  }

  Utf8Value sql(env->isolate(), args[0].As<String>());
  int r = sqlite3_exec(db->connection_, *sql, nullptr, nullptr, nullptr);
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
}

void DatabaseSync::CustomFunction(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  if (!args[0]->IsString()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"name\" argument must be a string.");
    return;
  }

  int fn_index = args.Length() < 3 ? 1 : 2;
  bool use_bigint_args = false;
  bool varargs = false;
  bool deterministic = false;
  bool direct_only = false;

  if (fn_index > 1) {
    if (!args[1]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[1].As<Object>();
    Local<Value> use_bigint_args_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "useBigIntArguments"))
             .ToLocal(&use_bigint_args_v)) {
      return;
    }

    if (!use_bigint_args_v->IsUndefined()) {
      if (!use_bigint_args_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.useBigIntArguments\" argument must be a boolean.");
        return;
      }
      use_bigint_args = use_bigint_args_v.As<Boolean>()->Value();
    }

    Local<Value> varargs_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "varargs"))
             .ToLocal(&varargs_v)) {
      return;
    }

    if (!varargs_v->IsUndefined()) {
      if (!varargs_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.varargs\" argument must be a boolean.");
        return;
      }
      varargs = varargs_v.As<Boolean>()->Value();
    }

    Local<Value> deterministic_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "deterministic"))
             .ToLocal(&deterministic_v)) {
      return;
    }

    if (!deterministic_v->IsUndefined()) {
      if (!deterministic_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.deterministic\" argument must be a boolean.");
        return;
      }
      deterministic = deterministic_v.As<Boolean>()->Value();
    }

    Local<Value> direct_only_v;
    if (!options
             ->Get(env->context(),
                   FIXED_ONE_BYTE_STRING(env->isolate(), "directOnly"))
             .ToLocal(&direct_only_v)) {
      return;
    }

    if (!direct_only_v->IsUndefined()) {
      if (!direct_only_v->IsBoolean()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.directOnly\" argument must be a boolean.");
        return;
      }
      direct_only = direct_only_v.As<Boolean>()->Value();
    }
  }

  if (!args[fn_index]->IsFunction()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"function\" argument must be a function.");
    return;
  }

  Utf8Value name(env->isolate(), args[0].As<String>());
  Local<Function> fn = args[fn_index].As<Function>();

  int argc = 0;
  if (varargs) {
    argc = -1;
  } else {
    Local<Value> js_len;
    if (!fn->Get(env->context(), env->length_string()).ToLocal(&js_len)) {
      return;
    }
    argc = js_len.As<Int32>()->Value();
  }

  UserDefinedFunction* user_data =
      new UserDefinedFunction(env, fn, db, use_bigint_args);
  int text_rep = SQLITE_UTF8;

  if (deterministic) {
    text_rep |= SQLITE_DETERMINISTIC;
  }

  if (direct_only) {
    text_rep |= SQLITE_DIRECTONLY;
  }

  int r = sqlite3_create_function_v2(db->connection_,
                                     *name,
                                     argc,
                                     text_rep,
                                     user_data,
                                     UserDefinedFunction::xFunc,
                                     nullptr,
                                     nullptr,
                                     UserDefinedFunction::xDestroy);
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
}

void DatabaseSync::Location(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  std::string db_name = "main";
  if (!args[0]->IsUndefined()) {
    if (!args[0]->IsString()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"dbName\" argument must be a string.");
      return;
    }

    db_name = Utf8Value(env->isolate(), args[0].As<String>()).ToString();
  }

  const char* db_filename =
      sqlite3_db_filename(db->connection_, db_name.c_str());
  if (!db_filename || db_filename[0] == '\0') {
    args.GetReturnValue().Set(Null(env->isolate()));
    return;
  }

  Local<String> ret;
  if (String::NewFromUtf8(env->isolate(), db_filename).ToLocal(&ret)) {
    args.GetReturnValue().Set(ret);
  }
}

void DatabaseSync::Serialize(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  std::string db_name = "main";
  if (!args[0]->IsUndefined()) {
    if (!args[0]->IsString()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"dbName\" argument must be a string.");
      return;
    }
    db_name = Utf8Value(env->isolate(), args[0].As<String>()).ToString();
  }

  sqlite3_int64 size = 0;
  unsigned char* data =
      sqlite3_serialize(db->connection_, db_name.c_str(), &size, 0);

  if (data == nullptr) {
    if (size == 0) {
      Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), 0);
      args.GetReturnValue().Set(Uint8Array::New(ab, 0, 0));
      return;
    }
    THROW_ERR_SQLITE_ERROR(env->isolate(), db);
    return;
  }

  // V8 sandbox forbids external backing stores so allocate inside the
  // sandbox and copy. Without sandbox wrap the output directly using
  // sqlite3_free as the destructor to avoid the copy.
#ifdef V8_ENABLE_SANDBOX
  auto free_data = OnScopeLeave([&] { sqlite3_free(data); });
  auto store = ArrayBuffer::NewBackingStore(
      env->isolate(),
      size,
      BackingStoreInitializationMode::kUninitialized,
      BackingStoreOnFailureMode::kReturnNull);
  if (!store) {
    THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
    return;
  }
  memcpy(store->Data(), data, size);
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(store));
#else
  auto store = ArrayBuffer::NewBackingStore(
      data, size, [](void* ptr, size_t, void*) { sqlite3_free(ptr); }, nullptr);
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(store));
#endif

  args.GetReturnValue().Set(Uint8Array::New(ab, 0, size));
}

void DatabaseSync::Deserialize(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  if (!args[0]->IsUint8Array()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"buffer\" argument must be a Uint8Array.");
    return;
  }

  Local<Uint8Array> input = args[0].As<Uint8Array>();
  size_t byte_length = input->ByteLength();

  if (byte_length == 0) {
    THROW_ERR_INVALID_ARG_VALUE(env,
                                "The \"buffer\" argument must not be empty.");
    return;
  }

  std::string db_name = "main";
  if (args.Length() > 1 && !args[1]->IsUndefined()) {
    if (!args[1]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[1].As<Object>();
    Local<String> db_name_key = FIXED_ONE_BYTE_STRING(env->isolate(), "dbName");
    Local<Value> db_name_value;
    if (!options->Get(env->context(), db_name_key).ToLocal(&db_name_value)) {
      return;
    }

    if (!db_name_value->IsUndefined()) {
      if (!db_name_value->IsString()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.dbName\" argument must be a string.");
        return;
      }
      db_name =
          Utf8Value(env->isolate(), db_name_value.As<String>()).ToString();
    }
  }

  // sqlite3_malloc64 is required because SQLITE_DESERIALIZE_FREEONCLOSE
  // transfers ownership to SQLite, which calls sqlite3_free() on close.
  // See: https://www.sqlite.org/c3ref/deserialize.html
  unsigned char* buf =
      static_cast<unsigned char*>(sqlite3_malloc64(byte_length));
  if (buf == nullptr) {
    THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
    return;
  }

  input->CopyContents(buf, byte_length);

  db->FinalizeStatements();

  int r = sqlite3_deserialize(
      db->connection_,
      db_name.c_str(),
      buf,
      byte_length,
      byte_length,
      SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE);
  if (r != SQLITE_OK) {
    THROW_ERR_SQLITE_ERROR(env->isolate(), db);
    return;
  }
}

void DatabaseSync::AggregateFunction(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
  Utf8Value name(env->isolate(), args[0].As<String>());
  Local<Object> options = args[1].As<Object>();
  Local<Value> start_v;
  if (!options->Get(env->context(), env->start_string()).ToLocal(&start_v)) {
    return;
  }

  if (start_v->IsUndefined()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"options.start\" argument must be a "
                               "function or a primitive value.");
    return;
  }

  Local<Value> step_v;
  if (!options->Get(env->context(), env->step_string()).ToLocal(&step_v)) {
    return;
  }

  if (!step_v->IsFunction()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env->isolate(), "The \"options.step\" argument must be a function.");
    return;
  }

  Local<Value> result_v;
  if (!options->Get(env->context(), env->result_string()).ToLocal(&result_v)) {
    return;
  }

  bool use_bigint_args = false;
  bool varargs = false;
  bool direct_only = false;
  Local<Value> use_bigint_args_v;
  Local<Function> inverseFunc = Local<Function>();
  if (!options
           ->Get(env->context(),
                 FIXED_ONE_BYTE_STRING(env->isolate(), "useBigIntArguments"))
           .ToLocal(&use_bigint_args_v)) {
    return;
  }

  if (!use_bigint_args_v->IsUndefined()) {
    if (!use_bigint_args_v->IsBoolean()) {
      THROW_ERR_INVALID_ARG_TYPE(
          env->isolate(),
          "The \"options.useBigIntArguments\" argument must be a boolean.");
      return;
    }
    use_bigint_args = use_bigint_args_v.As<Boolean>()->Value();
  }

  Local<Value> varargs_v;
  if (!options
           ->Get(env->context(),
                 FIXED_ONE_BYTE_STRING(env->isolate(), "varargs"))
           .ToLocal(&varargs_v)) {
    return;
  }

  if (!varargs_v->IsUndefined()) {
    if (!varargs_v->IsBoolean()) {
      THROW_ERR_INVALID_ARG_TYPE(
          env->isolate(),
          "The \"options.varargs\" argument must be a boolean.");
      return;
    }
    varargs = varargs_v.As<Boolean>()->Value();
  }

  Local<Value> direct_only_v;
  if (!options
           ->Get(env->context(),
                 FIXED_ONE_BYTE_STRING(env->isolate(), "directOnly"))
           .ToLocal(&direct_only_v)) {
    return;
  }

  if (!direct_only_v->IsUndefined()) {
    if (!direct_only_v->IsBoolean()) {
      THROW_ERR_INVALID_ARG_TYPE(
          env->isolate(),
          "The \"options.directOnly\" argument must be a boolean.");
      return;
    }
    direct_only = direct_only_v.As<Boolean>()->Value();
  }

  Local<Value> inverse_v;
  if (!options->Get(env->context(), env->inverse_string())
           .ToLocal(&inverse_v)) {
    return;
  }

  if (!inverse_v->IsUndefined()) {
    if (!inverse_v->IsFunction()) {
      THROW_ERR_INVALID_ARG_TYPE(
          env->isolate(),
          "The \"options.inverse\" argument must be a function.");
      return;
    }
    inverseFunc = inverse_v.As<Function>();
  }

  Local<Function> stepFunction = step_v.As<Function>();
  Local<Function> resultFunction =
      result_v->IsFunction() ? result_v.As<Function>() : Local<Function>();
  int argc = -1;
  if (!varargs) {
    Local<Value> js_len;
    if (!stepFunction->Get(env->context(), env->length_string())
             .ToLocal(&js_len)) {
      return;
    }

    // Subtract 1 because the first argument is the aggregate value.
    argc = js_len.As<Int32>()->Value() - 1;
    if (!inverseFunc.IsEmpty() &&
        !inverseFunc->Get(env->context(), env->length_string())
             .ToLocal(&js_len)) {
      return;
    }

    argc = std::max({argc, js_len.As<Int32>()->Value() - 1, 0});
  }

  int text_rep = SQLITE_UTF8;
  if (direct_only) {
    text_rep |= SQLITE_DIRECTONLY;
  }

  auto xInverse = !inverseFunc.IsEmpty() ? CustomAggregate::xInverse : nullptr;
  auto xValue = xInverse ? CustomAggregate::xValue : nullptr;
  int r = sqlite3_create_window_function(db->connection_,
                                         *name,
                                         argc,
                                         text_rep,
                                         new CustomAggregate(env,
                                                             db,
                                                             use_bigint_args,
                                                             start_v,
                                                             stepFunction,
                                                             inverseFunc,
                                                             resultFunction),
                                         CustomAggregate::xStep,
                                         CustomAggregate::xFinal,
                                         xValue,
                                         xInverse,
                                         CustomAggregate::xDestroy);
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
}

void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
  std::string table;
  std::string db_name = "main";

  Environment* env = Environment::GetCurrent(args);
  if (args.Length() > 0) {
    if (!args[0]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[0].As<Object>();

    Local<String> table_key = env->table_string();
    bool hasIt;
    if (!options->HasOwnProperty(env->context(), table_key).To(&hasIt)) {
      return;
    }
    if (hasIt) {
      Local<Value> table_value;
      if (!options->Get(env->context(), table_key).ToLocal(&table_value)) {
        return;
      }

      if (table_value->IsString()) {
        table = Utf8Value(env->isolate(), table_value).ToString();
      } else {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(), "The \"options.table\" argument must be a string.");
        return;
      }
    }

    Local<String> db_key = FIXED_ONE_BYTE_STRING(env->isolate(), "db");

    if (!options->HasOwnProperty(env->context(), db_key).To(&hasIt)) {
      return;
    }
    if (hasIt) {
      Local<Value> db_value;
      if (!options->Get(env->context(), db_key).ToLocal(&db_value)) {
        // An error will have been scheduled.
        return;
      }
      if (db_value->IsString()) {
        db_name = Utf8Value(env->isolate(), db_value).ToString();
      } else {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(), "The \"options.db\" argument must be a string.");
        return;
      }
    }
  }

  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  sqlite3_session* pSession;
  int r = sqlite3session_create(db->connection_, db_name.c_str(), &pSession);
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
  db->sessions_.insert(pSession);

  r = sqlite3session_attach(pSession, table == "" ? nullptr : table.c_str());
  CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());

  BaseObjectPtr<Session> session =
      Session::Create(env, BaseObjectWeakPtr<DatabaseSync>(db), pSession);
  args.GetReturnValue().Set(session->object());
}

void Backup(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  if (args.Length() < 1 || !args[0]->IsObject()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"sourceDb\" argument must be an object.");
    return;
  }

  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args[0].As<Object>());
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
  std::optional<std::string> dest_path =
      ValidateDatabasePath(env, args[1], "path");
  if (!dest_path.has_value()) {
    return;
  }

  int rate = 100;
  std::string source_db = "main";
  std::string dest_db = "main";
  Local<Function> progressFunc = Local<Function>();

  if (args.Length() > 2) {
    if (!args[2]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[2].As<Object>();
    Local<Value> rate_v;
    if (!options->Get(env->context(), env->rate_string()).ToLocal(&rate_v)) {
      return;
    }

    if (!rate_v->IsUndefined()) {
      if (!rate_v->IsInt32()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.rate\" argument must be an integer.");
        return;
      }
      rate = rate_v.As<Int32>()->Value();
    }

    Local<Value> source_v;
    if (!options->Get(env->context(), env->source_string())
             .ToLocal(&source_v)) {
      return;
    }

    if (!source_v->IsUndefined()) {
      if (!source_v->IsString()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.source\" argument must be a string.");
        return;
      }

      source_db = Utf8Value(env->isolate(), source_v.As<String>()).ToString();
    }

    Local<Value> target_v;
    if (!options->Get(env->context(), env->target_string())
             .ToLocal(&target_v)) {
      return;
    }

    if (!target_v->IsUndefined()) {
      if (!target_v->IsString()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.target\" argument must be a string.");
        return;
      }

      dest_db = Utf8Value(env->isolate(), target_v.As<String>()).ToString();
    }

    Local<Value> progress_v;
    if (!options->Get(env->context(), env->progress_string())
             .ToLocal(&progress_v)) {
      return;
    }

    if (!progress_v->IsUndefined()) {
      if (!progress_v->IsFunction()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.progress\" argument must be a function.");
        return;
      }
      progressFunc = progress_v.As<Function>();
    }
  }

  Local<Promise::Resolver> resolver;
  if (!Promise::Resolver::New(env->context()).ToLocal(&resolver)) {
    return;
  }

  args.GetReturnValue().Set(resolver->GetPromise());
  BackupJob* job = new BackupJob(env,
                                 db,
                                 resolver,
                                 std::move(source_db),
                                 dest_path.value(),
                                 std::move(dest_db),
                                 rate,
                                 progressFunc);
  db->AddBackup(job);
  job->ScheduleBackup();
}

struct ConflictCallbackContext {
  std::function<bool(std::string_view)> filterCallback;
  std::function<int(int)> conflictCallback;
};

// the reason for using static functions here is that SQLite needs a
// function pointer

static int xConflict(void* pCtx, int eConflict, sqlite3_changeset_iter* pIter) {
  auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
  if (!ctx->conflictCallback) return SQLITE_CHANGESET_ABORT;
  return ctx->conflictCallback(eConflict);
}

static int xFilter(void* pCtx, const char* zTab) {
  auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
  return ctx->filterCallback(zTab) ? 1 : 0;
}

void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
  ConflictCallbackContext context;

  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  if (!args[0]->IsUint8Array()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env->isolate(), "The \"changeset\" argument must be a Uint8Array.");
    return;
  }

  Local<Function> conflictFunc;
  Local<Function> filterFunc;
  if (args.Length() > 1 && !args[1]->IsUndefined()) {
    if (!args[1]->IsObject()) {
      THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                                 "The \"options\" argument must be an object.");
      return;
    }

    Local<Object> options = args[1].As<Object>();
    Local<Value> conflictValue;
    if (!options->Get(env->context(), env->onconflict_string())
             .ToLocal(&conflictValue)) {
      // An error will have been scheduled.
      return;
    }

    if (!conflictValue->IsUndefined()) {
      if (!conflictValue->IsFunction()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.onConflict\" argument must be a function.");
        return;
      }
      conflictFunc = conflictValue.As<Function>();
      context.conflictCallback = [env, &conflictFunc](int conflictType) -> int {
        Local<Value> argv[] = {Integer::New(env->isolate(), conflictType)};
        TryCatch try_catch(env->isolate());
        Local<Value> result =
            conflictFunc->Call(env->context(), Null(env->isolate()), 1, argv)
                .FromMaybe(Local<Value>());
        if (try_catch.HasCaught()) {
          try_catch.ReThrow();
          return SQLITE_CHANGESET_ABORT;
        }
        constexpr auto invalid_value = -1;
        if (!result->IsInt32()) return invalid_value;
        return result->Int32Value(env->context()).FromJust();
      };
    }

    bool hasIt;
    if (!options->HasOwnProperty(env->context(), env->filter_string())
             .To(&hasIt)) {
      return;
    }
    if (hasIt) {
      Local<Value> filterValue;
      if (!options->Get(env->context(), env->filter_string())
               .ToLocal(&filterValue)) {
        // An error will have been scheduled.
        return;
      }

      if (!filterValue->IsFunction()) {
        THROW_ERR_INVALID_ARG_TYPE(
            env->isolate(),
            "The \"options.filter\" argument must be a function.");
        return;
      }

      filterFunc = filterValue.As<Function>();

      context.filterCallback =
          [env, db, &filterFunc](std::string_view item) -> bool {
        // If there was an error in the previous call to the filter's
        // callback, we skip calling it again.
        if (db->ignore_next_sqlite_error_) {
          return false;
        }

        Local<Value> argv[1];
        if (!ToV8Value(env->context(), item, env->isolate())
                 .ToLocal(&argv[0])) {
          db->SetIgnoreNextSQLiteError(true);
          return false;
        }

        Local<Value> result;
        if (!filterFunc->Call(env->context(), Null(env->isolate()), 1, argv)
                 .ToLocal(&result)) {
          db->SetIgnoreNextSQLiteError(true);
          return false;
        }

        return result->BooleanValue(env->isolate());
      };
    }
  }

  ArrayBufferViewContents<uint8_t> buf(args[0]);
  int r = sqlite3changeset_apply(
      db->connection_,
      buf.length(),
      const_cast<void*>(static_cast<const void*>(buf.data())),
      context.filterCallback ? xFilter : nullptr,
      xConflict,
      static_cast<void*>(&context));
  if (r == SQLITE_OK) {
    args.GetReturnValue().Set(true);
    return;
  }
  if (r == SQLITE_ABORT) {
    // this is not an error, return false
    args.GetReturnValue().Set(false);
    return;
  }
  THROW_ERR_SQLITE_ERROR(env->isolate(), r);
}

void DatabaseSync::EnableLoadExtension(
    const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  auto isolate = args.GetIsolate();
  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(isolate,
                               "The \"allow\" argument must be a boolean.");
    return;
  }

  const int enable = args[0].As<Boolean>()->Value();

  if (db->allow_load_extension_ == false && enable == true) {
    THROW_ERR_INVALID_STATE(
        isolate,
        "Cannot enable extension loading because it was disabled at database "
        "creation.");
    return;
  }
  db->enable_load_extension_ = enable;
  const int load_extension_ret = sqlite3_db_config(
      db->connection_, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, enable, nullptr);
  CHECK_ERROR_OR_THROW(isolate, db, load_extension_ret, SQLITE_OK, void());
}

void DatabaseSync::EnableDefensive(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");

  auto isolate = args.GetIsolate();
  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(isolate,
                               "The \"active\" argument must be a boolean.");
    return;
  }

  const int enable = args[0].As<Boolean>()->Value();
  int defensive_enabled;
  const int defensive_ret = sqlite3_db_config(
      db->connection_, SQLITE_DBCONFIG_DEFENSIVE, enable, &defensive_enabled);
  CHECK_ERROR_OR_THROW(isolate, db, defensive_ret, SQLITE_OK, void());
}

void DatabaseSync::LoadExtension(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, db->connection_ == nullptr, "database is not open");
  THROW_AND_RETURN_ON_BAD_STATE(
      env, !db->allow_load_extension_, "extension loading is not allowed");
  THROW_AND_RETURN_ON_BAD_STATE(
      env, !db->enable_load_extension_, "extension loading is not allowed");

  if (!args[0]->IsString()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"path\" argument must be a string.");
    return;
  }

  auto isolate = env->isolate();

  BufferValue path(isolate, args[0]);
  BufferValue entryPoint(isolate, args[1]);
  CHECK_NOT_NULL(*path);
  ToNamespacedPath(env, &path);
  THROW_IF_INSUFFICIENT_PERMISSIONS(
      env, permission::PermissionScope::kFileSystemRead, path.ToStringView());
  char* errmsg = nullptr;
  const int r =
      sqlite3_load_extension(db->connection_, *path, *entryPoint, &errmsg);
  if (r != SQLITE_OK) {
    isolate->ThrowException(ERR_LOAD_SQLITE_EXTENSION(isolate, errmsg));
  }
}

void DatabaseSync::SetAuthorizer(const FunctionCallbackInfo<Value>& args) {
  DatabaseSync* db;
  ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();

  if (args[0]->IsNull()) {
    // Clear the authorizer
    sqlite3_set_authorizer(db->connection_, nullptr, nullptr);
    db->object()->SetInternalField(kAuthorizerCallback, Null(isolate));
    return;
  }

  if (!args[0]->IsFunction()) {
    THROW_ERR_INVALID_ARG_TYPE(
        isolate, "The \"callback\" argument must be a function or null.");
    return;
  }

  Local<Function> fn = args[0].As<Function>();

  db->object()->SetInternalField(kAuthorizerCallback, fn);

  int r = sqlite3_set_authorizer(
      db->connection_, DatabaseSync::AuthorizerCallback, db);

  if (r != SQLITE_OK) {
    CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, void());
  }
}

int DatabaseSync::AuthorizerCallback(void* user_data,
                                     int action_code,
                                     const char* param1,
                                     const char* param2,
                                     const char* param3,
                                     const char* param4) {
  DatabaseSync* db = static_cast<DatabaseSync*>(user_data);
  Environment* env = db->env();
  Isolate* isolate = env->isolate();
  HandleScope handle_scope(isolate);
  Local<Context> context = env->context();

  Local<Value> cb =
      db->object()->GetInternalField(kAuthorizerCallback).template As<Value>();

  CHECK(cb->IsFunction());

  Local<Function> callback = cb.As<Function>();

  LocalVector<Value> js_argv(
      isolate,
      {
          Integer::New(isolate, action_code),
          NullableSQLiteStringToValue(isolate, param1).ToLocalChecked(),
          NullableSQLiteStringToValue(isolate, param2).ToLocalChecked(),
          NullableSQLiteStringToValue(isolate, param3).ToLocalChecked(),
          NullableSQLiteStringToValue(isolate, param4).ToLocalChecked(),
      });

  MaybeLocal<Value> retval = callback->Call(
      context, Undefined(isolate), js_argv.size(), js_argv.data());

  Local<Value> result;

  if (!retval.ToLocal(&result)) {
    db->SetIgnoreNextSQLiteError(true);
    return SQLITE_DENY;
  }

  Local<String> error_message;

  if (!result->IsInt32()) {
    if (!String::NewFromUtf8(
             isolate,
             "Authorizer callback must return an integer authorization code")
             .ToLocal(&error_message)) {
      return SQLITE_DENY;
    }

    Local<Value> err = Exception::TypeError(error_message);
    isolate->ThrowException(err);
    db->SetIgnoreNextSQLiteError(true);
    return SQLITE_DENY;
  }

  int32_t int_result = result.As<Int32>()->Value();
  if (int_result != SQLITE_OK && int_result != SQLITE_DENY &&
      int_result != SQLITE_IGNORE) {
    if (!String::NewFromUtf8(
             isolate,
             "Authorizer callback returned a invalid authorization code")
             .ToLocal(&error_message)) {
      return SQLITE_DENY;
    }

    Local<Value> err = Exception::RangeError(error_message);
    isolate->ThrowException(err);
    db->SetIgnoreNextSQLiteError(true);
    return SQLITE_DENY;
  }

  return int_result;
}

StatementSync::StatementSync(Environment* env,
                             Local<Object> object,
                             BaseObjectPtr<DatabaseSync> db,
                             sqlite3_stmt* stmt)
    : BaseObject(env, object), db_(std::move(db)) {
  MakeWeak();
  statement_ = stmt;
  use_big_ints_ = db_->use_big_ints();
  return_arrays_ = db_->return_arrays();
  allow_bare_named_params_ = db_->allow_bare_named_params();
  allow_unknown_named_params_ = db_->allow_unknown_named_params();

  bare_named_params_ = std::nullopt;
}

StatementSync::~StatementSync() {
  if (!IsFinalized()) {
    db_->UntrackStatement(this);
    Finalize();
  }
}

void StatementSync::Finalize() {
  sqlite3_finalize(statement_);
  statement_ = nullptr;
  InvalidateColumnNameCache();
}

void StatementSync::InvalidateColumnNameCache() {
  cached_column_names_.clear();
}

inline bool StatementSync::IsFinalized() {
  return statement_ == nullptr;
}

inline int StatementSync::ResetStatement() {
  reset_generation_++;
  return sqlite3_reset(statement_);
}

bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
  int r = sqlite3_clear_bindings(statement_);
  CHECK_ERROR_OR_THROW(env()->isolate(), db_.get(), r, SQLITE_OK, false);

  int anon_idx = 1;
  int anon_start = 0;

  if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) {
    Local<Object> obj = args[0].As<Object>();
    Local<Context> context = Isolate::GetCurrent()->GetCurrentContext();
    Local<Array> keys;
    if (!obj->GetOwnPropertyNames(context).ToLocal(&keys)) {
      return false;
    }

    if (allow_bare_named_params_ && !bare_named_params_.has_value()) {
      bare_named_params_.emplace();
      int param_count = sqlite3_bind_parameter_count(statement_);
      // Parameter indexing starts at one.
      for (int i = 1; i <= param_count; ++i) {
        const char* name = sqlite3_bind_parameter_name(statement_, i);
        if (name == nullptr) {
          continue;
        }

        auto bare_name = std::string(name + 1);
        auto full_name = std::string(name);
        auto insertion = bare_named_params_->insert({bare_name, full_name});
        if (insertion.second == false) {
          auto existing_full_name = (*insertion.first).second;
          if (full_name != existing_full_name) {
            THROW_ERR_INVALID_STATE(
                env(),
                "Cannot create bare named parameter '%s' because of "
                "conflicting names '%s' and '%s'.",
                bare_name,
                existing_full_name,
                full_name);
            return false;
          }
        }
      }
    }

    uint32_t len = keys->Length();
    for (uint32_t j = 0; j < len; j++) {
      Local<Value> key;
      if (!keys->Get(context, j).ToLocal(&key)) {
        return false;
      }

      Utf8Value utf8_key(env()->isolate(), key);
      int r = sqlite3_bind_parameter_index(statement_, *utf8_key);
      if (r == 0) {
        if (allow_bare_named_params_) {
          auto lookup = bare_named_params_->find(std::string(*utf8_key));
          if (lookup != bare_named_params_->end()) {
            r = sqlite3_bind_parameter_index(statement_,
                                             lookup->second.c_str());
          }
        }

        if (r == 0) {
          if (allow_unknown_named_params_) {
            continue;
          } else {
            THROW_ERR_INVALID_STATE(
                env(), "Unknown named parameter '%s'", utf8_key);
            return false;
          }
        }
      }

      Local<Value> value;
      if (!obj->Get(context, key).ToLocal(&value)) {
        return false;
      }

      if (!BindValue(value, r)) {
        return false;
      }
    }
    anon_start++;
  }

  for (int i = anon_start; i < args.Length(); ++i) {
    while (1) {
      const char* param = sqlite3_bind_parameter_name(statement_, anon_idx);
      if (param == nullptr || param[0] == '?') break;
      anon_idx++;
    }

    if (!BindValue(args[i], anon_idx)) {
      return false;
    }

    anon_idx++;
  }

  return true;
}

bool StatementSync::BindValue(const Local<Value>& value, const int index) {
  // SQLite only supports a subset of JavaScript types. Some JS types such as
  // functions don't make sense to support. Other JS types such as booleans and
  // Dates could be supported by converting them to numbers. However, there
  // would not be a good way to read the values back from SQLite with the
  // original type.
  Isolate* isolate = env()->isolate();
  int r;
  if (value->IsNumber()) {
    const double val = value.As<Number>()->Value();
    r = sqlite3_bind_double(statement_, index, val);
  } else if (value->IsString()) {
    Utf8Value val(isolate, value.As<String>());
    if (val.IsAllocated()) {
      // Avoid an extra SQLite copy for large strings by transferring ownership
      // of the malloc()'d buffer to SQLite.
      char* data = *val;
      const sqlite3_uint64 length = static_cast<sqlite3_uint64>(val.length());
      val.Release();
      r = sqlite3_bind_text64(
          statement_, index, data, length, std::free, SQLITE_UTF8);
    } else {
      r = sqlite3_bind_text64(statement_,
                              index,
                              *val,
                              static_cast<sqlite3_uint64>(val.length()),
                              SQLITE_TRANSIENT,
                              SQLITE_UTF8);
    }
  } else if (value->IsNull()) {
    r = sqlite3_bind_null(statement_, index);
  } else if (value->IsArrayBufferView()) {
    ArrayBufferViewContents<uint8_t> buf(value);
    r = sqlite3_bind_blob64(statement_,
                            index,
                            buf.data(),
                            static_cast<sqlite3_uint64>(buf.length()),
                            SQLITE_TRANSIENT);
  } else if (value->IsBigInt()) {
    bool lossless;
    int64_t as_int = value.As<BigInt>()->Int64Value(&lossless);
    if (!lossless) {
      THROW_ERR_INVALID_ARG_VALUE(env(), "BigInt value is too large to bind.");
      return false;
    }
    r = sqlite3_bind_int64(statement_, index, as_int);
  } else {
    THROW_ERR_INVALID_ARG_TYPE(
        isolate,
        "Provided value cannot be bound to SQLite parameter %d.",
        index);
    return false;
  }

  CHECK_ERROR_OR_THROW(isolate, db_.get(), r, SQLITE_OK, false);
  return true;
}

MaybeLocal<Value> StatementSync::ColumnToValue(const int column) {
  return StatementExecutionHelper::ColumnToValue(
      env(), statement_, column, use_big_ints_);
}

MaybeLocal<Name> StatementSync::ColumnNameToName(const int column) {
  const char* col_name = sqlite3_column_name(statement_, column);
  if (col_name == nullptr) {
    THROW_ERR_INVALID_STATE(env(), "Cannot get name of column %d", column);
    return MaybeLocal<Name>();
  }

  return String::NewFromUtf8(
             env()->isolate(), col_name, NewStringType::kInternalized)
      .As<Name>();
}

// Populates `keys` with cached column names, rebuilding the cache if the
// statement was re-prepared.
bool StatementSync::GetCachedColumnNames(LocalVector<Name>* keys) {
  Isolate* isolate = env()->isolate();

  const int reprepare_count =
      sqlite3_stmt_status(statement_, SQLITE_STMTSTATUS_REPREPARE, false);
  if (reprepare_count != cached_column_names_reprepare_count_) {
    cached_column_names_.clear();
    const int num_cols = sqlite3_column_count(statement_);
    if (num_cols == 0) {
      cached_column_names_reprepare_count_ = reprepare_count;
      return true;
    }
    cached_column_names_.reserve(num_cols);
    for (int i = 0; i < num_cols; ++i) {
      Local<Name> key;
      if (!ColumnNameToName(i).ToLocal(&key)) {
        InvalidateColumnNameCache();
        return false;
      }
      cached_column_names_.emplace_back(Global<Name>(isolate, key));
    }
    cached_column_names_reprepare_count_ = reprepare_count;
  }

  keys->reserve(cached_column_names_.size());
  for (const auto& name : cached_column_names_) {
    keys->emplace_back(name.Get(isolate));
  }
  return true;
}

MaybeLocal<Value> StatementExecutionHelper::ColumnToValue(Environment* env,
                                                          sqlite3_stmt* stmt,
                                                          const int column,
                                                          bool use_big_ints) {
  Isolate* isolate = env->isolate();
  MaybeLocal<Value> js_val = MaybeLocal<Value>();
  SQLITE_VALUE_TO_JS(column, isolate, use_big_ints, js_val, stmt, column);
  return js_val;
}

MaybeLocal<Name> StatementExecutionHelper::ColumnNameToName(Environment* env,
                                                            sqlite3_stmt* stmt,
                                                            const int column) {
  const char* col_name = sqlite3_column_name(stmt, column);
  if (col_name == nullptr) {
    THROW_ERR_INVALID_STATE(env, "Cannot get name of column %d", column);
    return MaybeLocal<Name>();
  }

  return String::NewFromUtf8(
             env->isolate(), col_name, NewStringType::kInternalized)
      .As<Name>();
}

void StatementSync::MemoryInfo(MemoryTracker* tracker) const {}

Maybe<void> ExtractRowValues(Environment* env,
                             sqlite3_stmt* stmt,
                             int num_cols,
                             bool use_big_ints,
                             LocalVector<Value>* row_values) {
  row_values->clear();
  row_values->reserve(num_cols);
  for (int i = 0; i < num_cols; ++i) {
    Local<Value> val;
    if (!StatementExecutionHelper::ColumnToValue(env, stmt, i, use_big_ints)
             .ToLocal(&val)) {
      return Nothing<void>();
    }
    row_values->emplace_back(val);
  }
  return JustVoid();
}

MaybeLocal<Value> StatementExecutionHelper::All(Environment* env,
                                                DatabaseSync* db,
                                                sqlite3_stmt* stmt,
                                                bool return_arrays,
                                                bool use_big_ints) {
  Isolate* isolate = env->isolate();
  EscapableHandleScope scope(isolate);
  int r;
  int num_cols = sqlite3_column_count(stmt);
  LocalVector<Value> rows(isolate);
  LocalVector<Value> row_values(isolate);
  LocalVector<Name> row_keys(isolate);

  while ((r = sqlite3_step(stmt)) == SQLITE_ROW) {
    if (ExtractRowValues(env, stmt, num_cols, use_big_ints, &row_values)
            .IsNothing()) {
      return MaybeLocal<Value>();
    }

    if (return_arrays) {
      Local<Array> row_array =
          Array::New(isolate, row_values.data(), row_values.size());
      rows.emplace_back(row_array);
    } else {
      if (row_keys.size() == 0) {
        row_keys.reserve(num_cols);
        for (int i = 0; i < num_cols; ++i) {
          Local<Name> key;
          if (!ColumnNameToName(env, stmt, i).ToLocal(&key)) {
            return MaybeLocal<Value>();
          }
          row_keys.emplace_back(key);
        }
      }
      DCHECK_EQ(row_keys.size(), row_values.size());
      Local<Object> row_obj = Object::New(
          isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
      rows.emplace_back(row_obj);
    }
  }

  CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_DONE, MaybeLocal<Value>());
  return scope.Escape(Array::New(isolate, rows.data(), rows.size()));
}

MaybeLocal<Object> StatementExecutionHelper::Run(Environment* env,
                                                 DatabaseSync* db,
                                                 sqlite3_stmt* stmt,
                                                 bool use_big_ints) {
  Isolate* isolate = env->isolate();
  EscapableHandleScope scope(isolate);
  sqlite3_step(stmt);
  int r = sqlite3_reset(stmt);
  CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, MaybeLocal<Object>());

  sqlite3_int64 last_insert_rowid = sqlite3_last_insert_rowid(db->Connection());
  sqlite3_int64 changes = sqlite3_changes64(db->Connection());
  Local<Value> last_insert_rowid_val;
  Local<Value> changes_val;

  if (use_big_ints) {
    last_insert_rowid_val = BigInt::New(isolate, last_insert_rowid);
    changes_val = BigInt::New(isolate, changes);
  } else {
    last_insert_rowid_val = Number::New(isolate, last_insert_rowid);
    changes_val = Number::New(isolate, changes);
  }

  auto run_result_template = env->sqlite_run_result_template();
  if (run_result_template.IsEmpty()) {
    static constexpr std::string_view run_result_keys[] = {"changes",
                                                           "lastInsertRowid"};
    run_result_template = DictionaryTemplate::New(isolate, run_result_keys);
    env->set_sqlite_run_result_template(run_result_template);
  }

  MaybeLocal<Value> values[] = {changes_val, last_insert_rowid_val};
  Local<Object> result;
  if (!NewDictionaryInstance(env->context(), run_result_template, values)
           .ToLocal(&result)) {
    return MaybeLocal<Object>();
  }

  return scope.Escape(result);
}

BaseObjectPtr<StatementSyncIterator> StatementExecutionHelper::Iterate(
    Environment* env, BaseObjectPtr<StatementSync> stmt) {
  Local<Context> context = env->context();
  Local<Object> global = context->Global();
  Local<Value> js_iterator;
  Local<Value> js_iterator_prototype;
  if (!global->Get(context, env->iterator_string()).ToLocal(&js_iterator)) {
    return BaseObjectPtr<StatementSyncIterator>();
  }
  if (!js_iterator.As<Object>()
           ->Get(context, env->prototype_string())
           .ToLocal(&js_iterator_prototype)) {
    return BaseObjectPtr<StatementSyncIterator>();
  }

  BaseObjectPtr<StatementSyncIterator> iter =
      StatementSyncIterator::Create(env, stmt);

  if (!iter) {
    // Error in iterator creation, likely already threw in Create
    return BaseObjectPtr<StatementSyncIterator>();
  }

  if (iter->object()
          ->GetPrototype()
          .As<Object>()
          ->SetPrototype(context, js_iterator_prototype)
          .IsNothing()) {
    return BaseObjectPtr<StatementSyncIterator>();
  }

  return iter;
}

MaybeLocal<Value> StatementExecutionHelper::Get(Environment* env,
                                                DatabaseSync* db,
                                                sqlite3_stmt* stmt,
                                                bool return_arrays,
                                                bool use_big_ints) {
  Isolate* isolate = env->isolate();
  EscapableHandleScope scope(isolate);
  auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt); });

  int r = sqlite3_step(stmt);
  if (r == SQLITE_DONE) return scope.Escape(Undefined(isolate));
  if (r != SQLITE_ROW) {
    THROW_ERR_SQLITE_ERROR(isolate, db);
    return MaybeLocal<Value>();
  }

  int num_cols = sqlite3_column_count(stmt);
  if (num_cols == 0) {
    return Undefined(isolate);
  }

  LocalVector<Value> row_values(isolate);
  if (ExtractRowValues(env, stmt, num_cols, use_big_ints, &row_values)
          .IsNothing()) {
    return MaybeLocal<Value>();
  }

  if (return_arrays) {
    return scope.Escape(
        Array::New(isolate, row_values.data(), row_values.size()));
  } else {
    LocalVector<Name> keys(isolate);
    keys.reserve(num_cols);
    for (int i = 0; i < num_cols; ++i) {
      Local<Name> key;
      if (!ColumnNameToName(env, stmt, i).ToLocal(&key)) {
        return MaybeLocal<Value>();
      }
      keys.emplace_back(key);
    }

    DCHECK_EQ(keys.size(), row_values.size());
    return scope.Escape(Object::New(
        isolate, Null(isolate), keys.data(), row_values.data(), num_cols));
  }
}

void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  Isolate* isolate = env->isolate();
  int r = stmt->ResetStatement();
  CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());

  if (!stmt->BindParams(args)) {
    return;
  }

  auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });

  Local<Value> result;
  if (StatementExecutionHelper::All(env,
                                    stmt->db_.get(),
                                    stmt->statement_,
                                    stmt->return_arrays_,
                                    stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  int r = stmt->ResetStatement();
  CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());

  if (!stmt->BindParams(args)) {
    return;
  }

  BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate(
      env, BaseObjectPtr<StatementSync>(stmt));

  if (!iter) {
    return;
  }

  args.GetReturnValue().Set(iter->object());
}

void StatementSync::Get(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  int r = stmt->ResetStatement();
  CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());

  if (!stmt->BindParams(args)) {
    return;
  }

  Local<Value> result;
  if (StatementExecutionHelper::Get(env,
                                    stmt->db_.get(),
                                    stmt->statement_,
                                    stmt->return_arrays_,
                                    stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  int r = stmt->ResetStatement();
  CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());

  if (!stmt->BindParams(args)) {
    return;
  }

  Local<Object> result;
  if (StatementExecutionHelper::Run(
          env, stmt->db_.get(), stmt->statement_, stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void StatementSync::Columns(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  int num_cols = sqlite3_column_count(stmt->statement_);
  Isolate* isolate = env->isolate();
  LocalVector<Value> cols(isolate);
  auto sqlite_column_template = env->sqlite_column_template();
  if (sqlite_column_template.IsEmpty()) {
    static constexpr std::string_view col_keys[] = {
        "column", "database", "name", "table", "type"};
    sqlite_column_template = DictionaryTemplate::New(isolate, col_keys);
    env->set_sqlite_column_template(sqlite_column_template);
  }

  cols.reserve(num_cols);
  for (int i = 0; i < num_cols; ++i) {
    MaybeLocal<Value> values[] = {
        NullableSQLiteStringToValue(
            isolate, sqlite3_column_origin_name(stmt->statement_, i)),
        NullableSQLiteStringToValue(
            isolate, sqlite3_column_database_name(stmt->statement_, i)),
        stmt->ColumnNameToName(i),
        NullableSQLiteStringToValue(
            isolate, sqlite3_column_table_name(stmt->statement_, i)),
        NullableSQLiteStringToValue(
            isolate, sqlite3_column_decltype(stmt->statement_, i)),
    };

    Local<Object> col;
    if (!NewDictionaryInstanceNullProto(
             env->context(), sqlite_column_template, values)
             .ToLocal(&col)) {
      return;
    }
    cols.emplace_back(col);
  }

  args.GetReturnValue().Set(Array::New(isolate, cols.data(), cols.size()));
}

void StatementSync::SourceSQLGetter(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");
  Local<String> sql;
  if (!String::NewFromUtf8(env->isolate(), sqlite3_sql(stmt->statement_))
           .ToLocal(&sql)) {
    return;
  }
  args.GetReturnValue().Set(sql);
}

void StatementSync::ExpandedSQLGetter(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");

  // sqlite3_expanded_sql may return nullptr without producing an error code.
  char* expanded = sqlite3_expanded_sql(stmt->statement_);
  if (expanded == nullptr) {
    return THROW_ERR_SQLITE_ERROR(
        env->isolate(), "Expanded SQL text would exceed configured limits");
  }
  auto maybe_expanded = String::NewFromUtf8(env->isolate(), expanded);
  sqlite3_free(expanded);
  Local<String> result;
  if (!maybe_expanded.ToLocal(&result)) {
    return;
  }
  args.GetReturnValue().Set(result);
}

void StatementSync::SetAllowBareNamedParameters(
    const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");

  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env->isolate(),
        "The \"allowBareNamedParameters\" argument must be a boolean.");
    return;
  }

  stmt->allow_bare_named_params_ = args[0]->IsTrue();
}

void StatementSync::SetAllowUnknownNamedParameters(
    const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");

  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
                               "The \"enabled\" argument must be a boolean.");
    return;
  }

  stmt->allow_unknown_named_params_ = args[0]->IsTrue();
}

void StatementSync::SetReadBigInts(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");

  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env->isolate(), "The \"readBigInts\" argument must be a boolean.");
    return;
  }

  stmt->use_big_ints_ = args[0]->IsTrue();
}

void StatementSync::SetReturnArrays(const FunctionCallbackInfo<Value>& args) {
  StatementSync* stmt;
  ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, stmt->IsFinalized(), "statement has been finalized");

  if (!args[0]->IsBoolean()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env->isolate(), "The \"returnArrays\" argument must be a boolean.");
    return;
  }

  stmt->return_arrays_ = args[0]->IsTrue();
}

void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
  THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
}

SQLTagStore::SQLTagStore(Environment* env,
                         Local<Object> object,
                         BaseObjectWeakPtr<DatabaseSync> database,
                         int capacity)
    : BaseObject(env, object),
      database_(std::move(database)),
      sql_tags_(capacity) {
  MakeWeak();
}

static inline void SetSideEffectFreeGetter(
    Isolate* isolate,
    Local<FunctionTemplate> class_template,
    Local<String> name,
    FunctionCallback fn) {
  Local<FunctionTemplate> getter =
      FunctionTemplate::New(isolate,
                            fn,
                            Local<Value>(),
                            v8::Signature::New(isolate, class_template),
                            /* length */ 0,
                            ConstructorBehavior::kThrow,
                            SideEffectType::kHasNoSideEffect);
  class_template->InstanceTemplate()->SetAccessorProperty(
      name, getter, Local<FunctionTemplate>(), DontDelete);
}

SQLTagStore::~SQLTagStore() {}

Local<FunctionTemplate> SQLTagStore::GetConstructorTemplate(Environment* env) {
  Isolate* isolate = env->isolate();
  Local<FunctionTemplate> tmpl =
      NewFunctionTemplate(isolate, IllegalConstructor);
  tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "SQLTagStore"));
  tmpl->InstanceTemplate()->SetInternalFieldCount(
      SQLTagStore::kInternalFieldCount);
  SetProtoMethod(isolate, tmpl, "get", Get);
  SetProtoMethod(isolate, tmpl, "all", All);
  SetProtoMethod(isolate, tmpl, "iterate", Iterate);
  SetProtoMethod(isolate, tmpl, "run", Run);
  SetProtoMethod(isolate, tmpl, "clear", Clear);
  SetSideEffectFreeGetter(isolate,
                          tmpl,
                          FIXED_ONE_BYTE_STRING(isolate, "capacity"),
                          CapacityGetter);
  SetSideEffectFreeGetter(
      isolate, tmpl, FIXED_ONE_BYTE_STRING(isolate, "db"), DatabaseGetter);
  SetSideEffectFreeGetter(isolate, tmpl, env->size_string(), SizeGetter);
  return tmpl;
}

BaseObjectPtr<SQLTagStore> SQLTagStore::Create(
    Environment* env, BaseObjectWeakPtr<DatabaseSync> database, int capacity) {
  Local<Object> obj;
  if (!GetConstructorTemplate(env)
           ->InstanceTemplate()
           ->NewInstance(env->context())
           .ToLocal(&obj)) {
    return nullptr;
  }
  obj->SetInternalField(kDatabaseObject, database->object());
  return MakeBaseObject<SQLTagStore>(env, obj, std::move(database), capacity);
}

void SQLTagStore::CapacityGetter(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* store;
  ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
  args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Capacity()));
}

void SQLTagStore::DatabaseGetter(const FunctionCallbackInfo<Value>& args) {
  args.GetReturnValue().Set(
      args.This()->GetInternalField(kDatabaseObject).As<Value>());
}

void SQLTagStore::SizeGetter(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* store;
  ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
  args.GetReturnValue().Set(static_cast<double>(store->sql_tags_.Size()));
}

void SQLTagStore::Run(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);

  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");

  BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);

  if (!stmt) {
    return;
  }

  uint32_t n_params = args.Length() - 1;
  int r = sqlite3_reset(stmt->statement_);
  CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
  int param_count = sqlite3_bind_parameter_count(stmt->statement_);
  for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
    Local<Value> value = args[i + 1];
    if (!stmt->BindValue(value, i + 1)) {
      return;
    }
  }

  Local<Object> result;
  if (StatementExecutionHelper::Run(
          env, stmt->db_.get(), stmt->statement_, stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void SQLTagStore::Iterate(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);

  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");

  BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);

  if (!stmt) {
    return;
  }

  uint32_t n_params = args.Length() - 1;
  int r = sqlite3_reset(stmt->statement_);
  CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
  int param_count = sqlite3_bind_parameter_count(stmt->statement_);
  for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
    Local<Value> value = args[i + 1];
    if (!stmt->BindValue(value, i + 1)) {
      return;
    }
  }

  BaseObjectPtr<StatementSyncIterator> iter = StatementExecutionHelper::Iterate(
      env, BaseObjectPtr<StatementSync>(stmt));

  if (!iter) {
    return;
  }

  args.GetReturnValue().Set(iter->object());
}

void SQLTagStore::Get(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);

  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");

  BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);

  if (!stmt) {
    return;
  }

  uint32_t n_params = args.Length() - 1;
  Isolate* isolate = env->isolate();

  int r = sqlite3_reset(stmt->statement_);
  CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());

  int param_count = sqlite3_bind_parameter_count(stmt->statement_);
  for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
    Local<Value> value = args[i + 1];
    if (!stmt->BindValue(value, i + 1)) {
      return;
    }
  }

  Local<Value> result;
  if (StatementExecutionHelper::Get(env,
                                    stmt->db_.get(),
                                    stmt->statement_,
                                    stmt->return_arrays_,
                                    stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void SQLTagStore::All(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);

  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");

  BaseObjectPtr<StatementSync> stmt = PrepareStatement(args);

  if (!stmt) {
    return;
  }

  uint32_t n_params = args.Length() - 1;
  Isolate* isolate = env->isolate();

  int r = sqlite3_reset(stmt->statement_);
  CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());

  int param_count = sqlite3_bind_parameter_count(stmt->statement_);
  for (int i = 0; i < static_cast<int>(n_params) && i < param_count; ++i) {
    Local<Value> value = args[i + 1];
    if (!stmt->BindValue(value, i + 1)) {
      return;
    }
  }

  auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
  Local<Value> result;
  if (StatementExecutionHelper::All(env,
                                    stmt->db_.get(),
                                    stmt->statement_,
                                    stmt->return_arrays_,
                                    stmt->use_big_ints_)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void SQLTagStore::Clear(const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* store;
  ASSIGN_OR_RETURN_UNWRAP(&store, args.This());
  store->sql_tags_.Clear();
}

BaseObjectPtr<StatementSync> SQLTagStore::PrepareStatement(
    const FunctionCallbackInfo<Value>& args) {
  SQLTagStore* session = BaseObject::FromJSObject<SQLTagStore>(args.This());
  if (!session) {
    THROW_ERR_INVALID_ARG_TYPE(
        Environment::GetCurrent(args)->isolate(),
        "This method can only be called on SQLTagStore instances.");
    return BaseObjectPtr<StatementSync>();
  }
  Environment* env = Environment::GetCurrent(args);
  Isolate* isolate = env->isolate();
  Local<Context> context = isolate->GetCurrentContext();

  if (args.Length() < 1 || !args[0]->IsArray()) {
    THROW_ERR_INVALID_ARG_TYPE(
        isolate,
        "First argument must be an array of strings (template literal).");
    return BaseObjectPtr<StatementSync>();
  }

  Local<Array> strings = args[0].As<Array>();
  uint32_t n_strings = strings->Length();
  uint32_t n_params = args.Length() - 1;

  std::string sql;
  for (uint32_t i = 0; i < n_strings; ++i) {
    Local<Value> str_val;
    if (!strings->Get(context, i).ToLocal(&str_val) || !str_val->IsString()) {
      THROW_ERR_INVALID_ARG_TYPE(isolate,
                                 "Template literal parts must be strings.");
      return BaseObjectPtr<StatementSync>();
    }
    Utf8Value part(isolate, str_val);
    sql += part.ToStringView();
    if (i < n_params) {
      sql += "?";
    }
  }

  BaseObjectPtr<StatementSync> stmt = nullptr;
  if (session->sql_tags_.Exists(sql)) {
    stmt = session->sql_tags_.Get(sql);
    if (stmt->IsFinalized()) {
      session->sql_tags_.Erase(sql);
      stmt = nullptr;
    }
  }

  if (stmt == nullptr) {
    sqlite3_stmt* s = nullptr;
    int r = sqlite3_prepare_v2(
        session->database_->connection_, sql.data(), sql.size(), &s, nullptr);

    if (r != SQLITE_OK) {
      THROW_ERR_SQLITE_ERROR(isolate, session->database_.get());
      sqlite3_finalize(s);
      return BaseObjectPtr<StatementSync>();
    }

    BaseObjectPtr<StatementSync> stmt_obj = StatementSync::Create(
        env, BaseObjectPtr<DatabaseSync>(session->database_), s);

    if (!stmt_obj) {
      THROW_ERR_SQLITE_ERROR(isolate, "Failed to create StatementSync");
      sqlite3_finalize(s);
      return BaseObjectPtr<StatementSync>();
    }

    session->sql_tags_.Put(sql, stmt_obj);
    stmt = stmt_obj;
  }

  return stmt;
}

void SQLTagStore::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackFieldWithSize(MemoryInfoName(), SelfSize());
  tracker->TrackField("database", database_);
  size_t cache_content_size = 0;
  for (const auto& pair : sql_tags_) {
    cache_content_size += pair.first.capacity();
    cache_content_size += sizeof(pair.second);
  }
  tracker->TrackFieldWithSize("sql_tags_cache", cache_content_size);
}

Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
    Environment* env) {
  Local<FunctionTemplate> tmpl =
      env->sqlite_statement_sync_constructor_template();
  if (tmpl.IsEmpty()) {
    Isolate* isolate = env->isolate();
    tmpl = NewFunctionTemplate(isolate, IllegalConstructor);
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "StatementSync"));
    tmpl->InstanceTemplate()->SetInternalFieldCount(
        StatementSync::kInternalFieldCount);
    SetProtoMethod(isolate, tmpl, "iterate", StatementSync::Iterate);
    SetProtoMethod(isolate, tmpl, "all", StatementSync::All);
    SetProtoMethod(isolate, tmpl, "get", StatementSync::Get);
    SetProtoMethod(isolate, tmpl, "run", StatementSync::Run);
    SetProtoMethodNoSideEffect(
        isolate, tmpl, "columns", StatementSync::Columns);
    SetSideEffectFreeGetter(isolate,
                            tmpl,
                            FIXED_ONE_BYTE_STRING(isolate, "sourceSQL"),
                            StatementSync::SourceSQLGetter);
    SetSideEffectFreeGetter(isolate,
                            tmpl,
                            FIXED_ONE_BYTE_STRING(isolate, "expandedSQL"),
                            StatementSync::ExpandedSQLGetter);
    SetProtoMethod(isolate,
                   tmpl,
                   "setAllowBareNamedParameters",
                   StatementSync::SetAllowBareNamedParameters);
    SetProtoMethod(isolate,
                   tmpl,
                   "setAllowUnknownNamedParameters",
                   StatementSync::SetAllowUnknownNamedParameters);
    SetProtoMethod(
        isolate, tmpl, "setReadBigInts", StatementSync::SetReadBigInts);
    SetProtoMethod(
        isolate, tmpl, "setReturnArrays", StatementSync::SetReturnArrays);
    env->set_sqlite_statement_sync_constructor_template(tmpl);
  }
  return tmpl;
}

BaseObjectPtr<StatementSync> StatementSync::Create(
    Environment* env, BaseObjectPtr<DatabaseSync> db, sqlite3_stmt* stmt) {
  Local<Object> obj;
  if (!GetConstructorTemplate(env)
           ->InstanceTemplate()
           ->NewInstance(env->context())
           .ToLocal(&obj)) {
    return nullptr;
  }

  return MakeBaseObject<StatementSync>(env, obj, std::move(db), stmt);
}

StatementSyncIterator::StatementSyncIterator(Environment* env,
                                             Local<Object> object,
                                             BaseObjectPtr<StatementSync> stmt)
    : BaseObject(env, object), stmt_(std::move(stmt)) {
  MakeWeak();
  done_ = false;
  statement_reset_generation_ = stmt_->reset_generation_;
}

StatementSyncIterator::~StatementSyncIterator() {}
void StatementSyncIterator::MemoryInfo(MemoryTracker* tracker) const {}

Local<FunctionTemplate> StatementSyncIterator::GetConstructorTemplate(
    Environment* env) {
  Local<FunctionTemplate> tmpl =
      env->sqlite_statement_sync_iterator_constructor_template();
  if (tmpl.IsEmpty()) {
    Isolate* isolate = env->isolate();
    tmpl = NewFunctionTemplate(isolate, IllegalConstructor);
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "StatementSyncIterator"));
    tmpl->InstanceTemplate()->SetInternalFieldCount(
        StatementSyncIterator::kInternalFieldCount);
    SetProtoMethod(isolate, tmpl, "next", StatementSyncIterator::Next);
    SetProtoMethod(isolate, tmpl, "return", StatementSyncIterator::Return);
    env->set_sqlite_statement_sync_iterator_constructor_template(tmpl);
  }
  return tmpl;
}

BaseObjectPtr<StatementSyncIterator> StatementSyncIterator::Create(
    Environment* env, BaseObjectPtr<StatementSync> stmt) {
  Local<Object> obj;
  if (!GetConstructorTemplate(env)
           ->InstanceTemplate()
           ->NewInstance(env->context())
           .ToLocal(&obj)) {
    return BaseObjectPtr<StatementSyncIterator>();
  }

  return MakeBaseObject<StatementSyncIterator>(env, obj, std::move(stmt));
}

void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
  StatementSyncIterator* iter;
  ASSIGN_OR_RETURN_UNWRAP(&iter, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, iter->stmt_->IsFinalized(), "statement has been finalized");
  Isolate* isolate = env->isolate();

  auto iter_template = getLazyIterTemplate(env);

  if (iter->done_) {
    MaybeLocal<Value> values[]{
        Boolean::New(isolate, true),
        Null(isolate),
    };
    Local<Object> result;
    if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
            .ToLocal(&result)) {
      args.GetReturnValue().Set(result);
    }
    return;
  }

  THROW_AND_RETURN_ON_BAD_STATE(
      env,
      iter->statement_reset_generation_ != iter->stmt_->reset_generation_,
      "iterator was invalidated");

  int r = sqlite3_step(iter->stmt_->statement_);
  if (r != SQLITE_ROW) {
    CHECK_ERROR_OR_THROW(
        env->isolate(), iter->stmt_->db_.get(), r, SQLITE_DONE, void());
    sqlite3_reset(iter->stmt_->statement_);
    MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};
    Local<Object> result;
    if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
            .ToLocal(&result)) {
      args.GetReturnValue().Set(result);
    }
    return;
  }

  int num_cols = sqlite3_column_count(iter->stmt_->statement_);
  Local<Value> row_value;
  LocalVector<Name> row_keys(isolate);
  LocalVector<Value> row_values(isolate);

  if (ExtractRowValues(env,
                       iter->stmt_->statement_,
                       num_cols,
                       iter->stmt_->use_big_ints_,
                       &row_values)
          .IsNothing()) {
    return;
  }

  if (iter->stmt_->return_arrays_) {
    row_value = Array::New(isolate, row_values.data(), row_values.size());
  } else {
    // Use cached internalized column names to avoid repeated V8 string
    // creation and enable hidden class sharing across row objects.
    if (!iter->stmt_->GetCachedColumnNames(&row_keys)) return;

    DCHECK_EQ(row_keys.size(), row_values.size());
    row_value = Object::New(
        isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
  }

  MaybeLocal<Value> values[] = {Boolean::New(isolate, false), row_value};
  Local<Object> result;
  if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
  StatementSyncIterator* iter;
  ASSIGN_OR_RETURN_UNWRAP(&iter, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, iter->stmt_->IsFinalized(), "statement has been finalized");
  Isolate* isolate = env->isolate();

  sqlite3_reset(iter->stmt_->statement_);
  iter->done_ = true;

  auto iter_template = getLazyIterTemplate(env);
  MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};

  Local<Object> result;
  if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
          .ToLocal(&result)) {
    args.GetReturnValue().Set(result);
  }
}

Session::Session(Environment* env,
                 Local<Object> object,
                 BaseObjectWeakPtr<DatabaseSync> database,
                 sqlite3_session* session)
    : BaseObject(env, object),
      session_(session),
      database_(std::move(database)) {
  MakeWeak();
}

Session::~Session() {
  Delete();
}

BaseObjectPtr<Session> Session::Create(Environment* env,
                                       BaseObjectWeakPtr<DatabaseSync> database,
                                       sqlite3_session* session) {
  Local<Object> obj;
  if (!GetConstructorTemplate(env)
           ->InstanceTemplate()
           ->NewInstance(env->context())
           .ToLocal(&obj)) {
    return nullptr;
  }

  return MakeBaseObject<Session>(env, obj, std::move(database), session);
}

Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
  Local<FunctionTemplate> tmpl = env->sqlite_session_constructor_template();
  if (tmpl.IsEmpty()) {
    Isolate* isolate = env->isolate();
    tmpl = NewFunctionTemplate(isolate, IllegalConstructor);
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Session"));
    tmpl->InstanceTemplate()->SetInternalFieldCount(
        Session::kInternalFieldCount);
    SetProtoMethod(isolate,
                   tmpl,
                   "changeset",
                   Session::Changeset<sqlite3session_changeset>);
    SetProtoMethod(
        isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
    SetProtoMethod(isolate, tmpl, "close", Session::Close);
    SetProtoDispose(isolate, tmpl, Session::Dispose);
    env->set_sqlite_session_constructor_template(tmpl);
  }
  return tmpl;
}

void Session::MemoryInfo(MemoryTracker* tracker) const {}

template <Sqlite3ChangesetGenFunc sqliteChangesetFunc>
void Session::Changeset(const FunctionCallbackInfo<Value>& args) {
  Session* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");
  THROW_AND_RETURN_ON_BAD_STATE(
      env, session->session_ == nullptr, "session is not open");

  int nChangeset;
  void* pChangeset;
  int r = sqliteChangesetFunc(session->session_, &nChangeset, &pChangeset);
  CHECK_ERROR_OR_THROW(
      env->isolate(), session->database_.get(), r, SQLITE_OK, void());

  auto freeChangeset = OnScopeLeave([&] { sqlite3_free(pChangeset); });

  Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), nChangeset);
  std::memcpy(buffer->GetBackingStore()->Data(), pChangeset, nChangeset);
  Local<Uint8Array> uint8Array = Uint8Array::New(buffer, 0, nChangeset);

  args.GetReturnValue().Set(uint8Array);
}

void Session::Close(const FunctionCallbackInfo<Value>& args) {
  Session* session;
  ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
  Environment* env = Environment::GetCurrent(args);
  THROW_AND_RETURN_ON_BAD_STATE(
      env, !session->database_->IsOpen(), "database is not open");
  THROW_AND_RETURN_ON_BAD_STATE(
      env, session->session_ == nullptr, "session is not open");

  session->Delete();
}

void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  Close(args);
  if (try_catch.HasCaught()) {
    CHECK(try_catch.CanContinue());
  }
}

void Session::Delete() {
  if (!database_ || !database_->connection_ || session_ == nullptr) return;
  sqlite3session_delete(session_);
  database_->sessions_.erase(session_);
  session_ = nullptr;
}

void DefineConstants(Local<Object> target) {
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_OMIT);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_REPLACE);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_ABORT);

  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_DATA);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_NOTFOUND);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONFLICT);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONSTRAINT);
  NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_FOREIGN_KEY);

  // Authorization result codes
  NODE_DEFINE_CONSTANT(target, SQLITE_OK);
  NODE_DEFINE_CONSTANT(target, SQLITE_DENY);
  NODE_DEFINE_CONSTANT(target, SQLITE_IGNORE);

  // Authorization action codes
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_INDEX);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_INDEX);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_TABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_TRIGGER);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TEMP_VIEW);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_TRIGGER);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_VIEW);
  NODE_DEFINE_CONSTANT(target, SQLITE_DELETE);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_INDEX);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_INDEX);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_TABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_TRIGGER);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TEMP_VIEW);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_TRIGGER);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_VIEW);
  NODE_DEFINE_CONSTANT(target, SQLITE_INSERT);
  NODE_DEFINE_CONSTANT(target, SQLITE_PRAGMA);
  NODE_DEFINE_CONSTANT(target, SQLITE_READ);
  NODE_DEFINE_CONSTANT(target, SQLITE_SELECT);
  NODE_DEFINE_CONSTANT(target, SQLITE_TRANSACTION);
  NODE_DEFINE_CONSTANT(target, SQLITE_UPDATE);
  NODE_DEFINE_CONSTANT(target, SQLITE_ATTACH);
  NODE_DEFINE_CONSTANT(target, SQLITE_DETACH);
  NODE_DEFINE_CONSTANT(target, SQLITE_ALTER_TABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_REINDEX);
  NODE_DEFINE_CONSTANT(target, SQLITE_ANALYZE);
  NODE_DEFINE_CONSTANT(target, SQLITE_CREATE_VTABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_DROP_VTABLE);
  NODE_DEFINE_CONSTANT(target, SQLITE_FUNCTION);
  NODE_DEFINE_CONSTANT(target, SQLITE_SAVEPOINT);
  NODE_DEFINE_CONSTANT(target, SQLITE_COPY);
  NODE_DEFINE_CONSTANT(target, SQLITE_RECURSIVE);
}

static void Initialize(Local<Object> target,
                       Local<Value> unused,
                       Local<Context> context,
                       void* priv) {
  Environment* env = Environment::GetCurrent(context);
  Isolate* isolate = env->isolate();
  Local<FunctionTemplate> db_tmpl =
      NewFunctionTemplate(isolate, DatabaseSync::New);
  db_tmpl->InstanceTemplate()->SetInternalFieldCount(
      DatabaseSync::kInternalFieldCount);
  Local<Object> constants = Object::New(isolate);

  DefineConstants(constants);

  SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
  SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
  SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
  SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
  SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
  SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
  SetProtoMethod(
      isolate, db_tmpl, "createTagStore", DatabaseSync::CreateTagStore);
  SetProtoMethodNoSideEffect(
      isolate, db_tmpl, "location", DatabaseSync::Location);
  SetProtoMethod(
      isolate, db_tmpl, "aggregate", DatabaseSync::AggregateFunction);
  SetProtoMethod(
      isolate, db_tmpl, "createSession", DatabaseSync::CreateSession);
  SetProtoMethod(
      isolate, db_tmpl, "applyChangeset", DatabaseSync::ApplyChangeset);
  SetProtoMethod(isolate,
                 db_tmpl,
                 "enableLoadExtension",
                 DatabaseSync::EnableLoadExtension);
  SetProtoMethod(
      isolate, db_tmpl, "enableDefensive", DatabaseSync::EnableDefensive);
  SetProtoMethod(
      isolate, db_tmpl, "loadExtension", DatabaseSync::LoadExtension);
  SetProtoMethod(isolate, db_tmpl, "serialize", DatabaseSync::Serialize);
  SetProtoMethod(isolate, db_tmpl, "deserialize", DatabaseSync::Deserialize);
  SetProtoMethod(
      isolate, db_tmpl, "setAuthorizer", DatabaseSync::SetAuthorizer);
  SetSideEffectFreeGetter(isolate,
                          db_tmpl,
                          FIXED_ONE_BYTE_STRING(isolate, "isOpen"),
                          DatabaseSync::IsOpenGetter);
  SetSideEffectFreeGetter(isolate,
                          db_tmpl,
                          FIXED_ONE_BYTE_STRING(isolate, "isTransaction"),
                          DatabaseSync::IsTransactionGetter);
  SetSideEffectFreeGetter(isolate,
                          db_tmpl,
                          FIXED_ONE_BYTE_STRING(isolate, "limits"),
                          DatabaseSync::LimitsGetter);
  Local<String> sqlite_type_key = FIXED_ONE_BYTE_STRING(isolate, "sqlite-type");
  Local<v8::Symbol> sqlite_type_symbol =
      v8::Symbol::For(isolate, sqlite_type_key);
  Local<String> database_sync_string =
      FIXED_ONE_BYTE_STRING(isolate, "node:sqlite");
  db_tmpl->InstanceTemplate()->Set(sqlite_type_symbol, database_sync_string);

  SetConstructorFunction(context, target, "DatabaseSync", db_tmpl);
  SetConstructorFunction(context,
                         target,
                         "StatementSync",
                         StatementSync::GetConstructorTemplate(env));
  SetConstructorFunction(
      context, target, "Session", Session::GetConstructorTemplate(env));

  target->Set(context, env->constants_string(), constants).Check();

  Local<Function> backup_function;

  if (!Function::New(context, Backup, Local<Value>(), 2)
           .ToLocal(&backup_function)) {
    return;
  }
  backup_function->SetName(env->backup_string());

  target->Set(context, env->backup_string(), backup_function).Check();
}

}  // namespace sqlite
}  // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(sqlite, node::sqlite::Initialize)
