#ifndef SRC_NODE_SQLITE_H_ #define SRC_NODE_SQLITE_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "base_object.h" #include "lru_cache-inl.h" #include "node_mem.h" #include "sqlite3.h" #include "util.h" #include #include #include namespace node { namespace sqlite { class DatabaseOpenConfiguration { public: explicit DatabaseOpenConfiguration(std::string&& location) : location_(std::move(location)) {} inline const std::string& location() const { return location_; } inline bool get_read_only() const { return read_only_; } inline void set_read_only(bool flag) { read_only_ = flag; } inline bool get_enable_foreign_keys() const { return enable_foreign_keys_; } inline void set_enable_foreign_keys(bool flag) { enable_foreign_keys_ = flag; } inline bool get_enable_dqs() const { return enable_dqs_; } inline void set_enable_dqs(bool flag) { enable_dqs_ = flag; } inline void set_timeout(int timeout) { timeout_ = timeout; } inline int get_timeout() { return timeout_; } inline void set_use_big_ints(bool flag) { use_big_ints_ = flag; } inline bool get_use_big_ints() const { return use_big_ints_; } inline void set_return_arrays(bool flag) { return_arrays_ = flag; } inline bool get_return_arrays() const { return return_arrays_; } inline void set_allow_bare_named_params(bool flag) { allow_bare_named_params_ = flag; } inline bool get_allow_bare_named_params() const { return allow_bare_named_params_; } inline void set_allow_unknown_named_params(bool flag) { allow_unknown_named_params_ = flag; } inline bool get_allow_unknown_named_params() const { return allow_unknown_named_params_; } inline void set_enable_defensive(bool flag) { defensive_ = flag; } inline bool get_enable_defensive() const { return defensive_; } private: std::string location_; bool read_only_ = false; bool enable_foreign_keys_ = true; bool enable_dqs_ = false; int timeout_ = 0; bool use_big_ints_ = false; bool return_arrays_ = false; bool allow_bare_named_params_ = true; bool allow_unknown_named_params_ = false; bool defensive_ = false; }; class DatabaseSync; class StatementSyncIterator; class StatementSync; class BackupJob; class StatementExecutionHelper { public: static v8::MaybeLocal All(Environment* env, DatabaseSync* db, sqlite3_stmt* stmt, bool return_arrays, bool use_big_ints); static v8::MaybeLocal Run(Environment* env, DatabaseSync* db, sqlite3_stmt* stmt, bool use_big_ints); static BaseObjectPtr Iterate( Environment* env, BaseObjectPtr stmt); static v8::MaybeLocal ColumnToValue(Environment* env, sqlite3_stmt* stmt, const int column, bool use_big_ints); static v8::MaybeLocal ColumnNameToName(Environment* env, sqlite3_stmt* stmt, const int column); static v8::MaybeLocal Get(Environment* env, DatabaseSync* db, sqlite3_stmt* stmt, bool return_arrays, bool use_big_ints); }; class DatabaseSync : public BaseObject { public: enum InternalFields { kAuthorizerCallback = BaseObject::kInternalFieldCount, kInternalFieldCount }; DatabaseSync(Environment* env, v8::Local object, DatabaseOpenConfiguration&& open_config, bool open, bool allow_load_extension); void MemoryInfo(MemoryTracker* tracker) const override; static void New(const v8::FunctionCallbackInfo& args); static void Open(const v8::FunctionCallbackInfo& args); static void IsOpenGetter(const v8::FunctionCallbackInfo& args); static void IsTransactionGetter( const v8::FunctionCallbackInfo& args); static void Close(const v8::FunctionCallbackInfo& args); static void Dispose(const v8::FunctionCallbackInfo& args); static void Prepare(const v8::FunctionCallbackInfo& args); static void Exec(const v8::FunctionCallbackInfo& args); static void CreateTagStore(const v8::FunctionCallbackInfo& args); static void Location(const v8::FunctionCallbackInfo& args); static void CustomFunction(const v8::FunctionCallbackInfo& args); static void AggregateFunction( const v8::FunctionCallbackInfo& args); static void CreateSession(const v8::FunctionCallbackInfo& args); static void ApplyChangeset(const v8::FunctionCallbackInfo& args); static void EnableLoadExtension( const v8::FunctionCallbackInfo& args); static void EnableDefensive(const v8::FunctionCallbackInfo& args); static void LoadExtension(const v8::FunctionCallbackInfo& args); static void SetAuthorizer(const v8::FunctionCallbackInfo& args); static int AuthorizerCallback(void* user_data, int action_code, const char* param1, const char* param2, const char* param3, const char* param4); void FinalizeStatements(); void RemoveBackup(BackupJob* backup); void AddBackup(BackupJob* backup); void FinalizeBackups(); void UntrackStatement(StatementSync* statement); bool IsOpen(); bool use_big_ints() const { return open_config_.get_use_big_ints(); } bool return_arrays() const { return open_config_.get_return_arrays(); } bool allow_bare_named_params() const { return open_config_.get_allow_bare_named_params(); } bool allow_unknown_named_params() const { return open_config_.get_allow_unknown_named_params(); } sqlite3* Connection(); // In some situations, such as when using custom functions, it is possible // that SQLite reports an error while JavaScript already has a pending // exception. In this case, the SQLite error should be ignored. These methods // enable that use case. void SetIgnoreNextSQLiteError(bool ignore); bool ShouldIgnoreSQLiteError(); SET_MEMORY_INFO_NAME(DatabaseSync) SET_SELF_SIZE(DatabaseSync) private: bool Open(); void DeleteSessions(); ~DatabaseSync() override; DatabaseOpenConfiguration open_config_; bool allow_load_extension_; bool enable_load_extension_; sqlite3* connection_; bool ignore_next_sqlite_error_; std::set backups_; std::set sessions_; std::unordered_set statements_; friend class Session; friend class SQLTagStore; friend class StatementExecutionHelper; }; class StatementSync : public BaseObject { public: StatementSync(Environment* env, v8::Local object, BaseObjectPtr db, sqlite3_stmt* stmt); void MemoryInfo(MemoryTracker* tracker) const override; static v8::Local GetConstructorTemplate( Environment* env); static BaseObjectPtr Create(Environment* env, BaseObjectPtr db, sqlite3_stmt* stmt); static void All(const v8::FunctionCallbackInfo& args); static void Iterate(const v8::FunctionCallbackInfo& args); static void Get(const v8::FunctionCallbackInfo& args); static void Run(const v8::FunctionCallbackInfo& args); static void Columns(const v8::FunctionCallbackInfo& args); static void SourceSQLGetter(const v8::FunctionCallbackInfo& args); static void ExpandedSQLGetter( const v8::FunctionCallbackInfo& args); static void SetAllowBareNamedParameters( const v8::FunctionCallbackInfo& args); static void SetAllowUnknownNamedParameters( const v8::FunctionCallbackInfo& args); static void SetReadBigInts(const v8::FunctionCallbackInfo& args); static void SetReturnArrays(const v8::FunctionCallbackInfo& args); v8::MaybeLocal ColumnToValue(const int column); v8::MaybeLocal ColumnNameToName(const int column); void Finalize(); bool IsFinalized(); SET_MEMORY_INFO_NAME(StatementSync) SET_SELF_SIZE(StatementSync) private: ~StatementSync() override; BaseObjectPtr db_; sqlite3_stmt* statement_; bool return_arrays_ = false; bool use_big_ints_; bool allow_bare_named_params_; bool allow_unknown_named_params_; std::optional> bare_named_params_; bool BindParams(const v8::FunctionCallbackInfo& args); bool BindValue(const v8::Local& value, const int index); friend class StatementSyncIterator; friend class SQLTagStore; friend class StatementExecutionHelper; }; class StatementSyncIterator : public BaseObject { public: StatementSyncIterator(Environment* env, v8::Local object, BaseObjectPtr stmt); void MemoryInfo(MemoryTracker* tracker) const override; static v8::Local GetConstructorTemplate( Environment* env); static BaseObjectPtr Create( Environment* env, BaseObjectPtr stmt); static void Next(const v8::FunctionCallbackInfo& args); static void Return(const v8::FunctionCallbackInfo& args); SET_MEMORY_INFO_NAME(StatementSyncIterator) SET_SELF_SIZE(StatementSyncIterator) private: ~StatementSyncIterator() override; BaseObjectPtr stmt_; bool done_; }; using Sqlite3ChangesetGenFunc = int (*)(sqlite3_session*, int*, void**); class Session : public BaseObject { public: Session(Environment* env, v8::Local object, BaseObjectWeakPtr database, sqlite3_session* session); ~Session() override; template static void Changeset(const v8::FunctionCallbackInfo& args); static void Close(const v8::FunctionCallbackInfo& args); static void Dispose(const v8::FunctionCallbackInfo& args); static v8::Local GetConstructorTemplate( Environment* env); static BaseObjectPtr Create(Environment* env, BaseObjectWeakPtr database, sqlite3_session* session); void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(Session) SET_SELF_SIZE(Session) private: void Delete(); sqlite3_session* session_; BaseObjectWeakPtr database_; // The Parent Database }; class SQLTagStore : public BaseObject { public: SQLTagStore(Environment* env, v8::Local object, BaseObjectWeakPtr database, int capacity); ~SQLTagStore() override; static BaseObjectPtr Create( Environment* env, BaseObjectWeakPtr database, int capacity); static v8::Local GetConstructorTemplate( Environment* env); static void All(const v8::FunctionCallbackInfo& info); static void Get(const v8::FunctionCallbackInfo& info); static void Iterate(const v8::FunctionCallbackInfo& info); static void Run(const v8::FunctionCallbackInfo& info); static void Size(const v8::FunctionCallbackInfo& info); static void Capacity(const v8::FunctionCallbackInfo& info); static void Reset(const v8::FunctionCallbackInfo& info); static void Clear(const v8::FunctionCallbackInfo& info); static void DatabaseGetter(const v8::FunctionCallbackInfo& info); void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(SQLTagStore) SET_SELF_SIZE(SQLTagStore) private: static BaseObjectPtr PrepareStatement( const v8::FunctionCallbackInfo& args); BaseObjectWeakPtr database_; LRUCache> sql_tags_; int capacity_; friend class StatementExecutionHelper; }; class UserDefinedFunction { public: UserDefinedFunction(Environment* env, v8::Local fn, DatabaseSync* db, bool use_bigint_args); ~UserDefinedFunction(); static void xFunc(sqlite3_context* ctx, int argc, sqlite3_value** argv); static void xDestroy(void* self); private: Environment* env_; v8::Global fn_; DatabaseSync* db_; bool use_bigint_args_; }; } // namespace sqlite } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_SQLITE_H_