| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SQL_DATABASE_H_ |
| #define SQL_DATABASE_H_ |
| |
| #include<stddef.h> |
| #include<stdint.h> |
| |
| #include<memory> |
| #include<optional> |
| #include<set> |
| #include<string> |
| #include<string_view> |
| #include<utility> |
| #include<vector> |
| |
| #include"base/check.h" |
| #include"base/check_op.h" |
| #include"base/component_export.h" |
| #include"base/containers/flat_map.h" |
| #include"base/files/file_path.h" |
| #include"base/functional/callback.h" |
| #include"base/gtest_prod_util.h" |
| #include"base/location.h" |
| #include"base/memory/raw_ptr.h" |
| #include"base/memory/ref_counted.h" |
| #include"base/memory/ref_counted_memory.h" |
| #include"base/memory/scoped_refptr.h" |
| #include"base/memory/weak_ptr.h" |
| #include"base/notreached.h" |
| #include"base/sequence_checker.h" |
| #include"base/strings/cstring_view.h" |
| #include"base/threading/scoped_blocking_call.h" |
| #include"base/time/time.h" |
| #include"base/types/pass_key.h" |
| #include"sql/internal_api_token.h" |
| #include"sql/sql_name_variants.h" |
| #include"sql/sqlite_result_code.h" |
| #include"sql/sqlite_result_code_values.h" |
| #include"sql/statement_id.h" |
| #include"sql/streaming_blob_handle.h" |
| #include"third_party/perfetto/include/perfetto/tracing/traced_proto.h" |
| |
| // Forward declaration for SQLite structures. Headers in the public sql:: API |
| // must NOT include sqlite3.h. |
| struct sqlite3; |
| struct sqlite3_file; |
| struct sqlite3_stmt; |
| |
| namespacebase::trace_event{ |
| classProcessMemoryDump; |
| }// namespace base::trace_event |
| |
| namespace perfetto{ |
| classNamedTrack; |
| } |
| |
| namespace perfetto::protos::pbzero{ |
| classChromeSqlDiagnostics; |
| } |
| |
| namespace sql{ |
| |
| classDatabaseMemoryDumpProvider; |
| classStatement; |
| |
| namespace test{ |
| classScopedErrorExpecter; |
| }// namespace test |
| |
| struct COMPONENT_EXPORT(SQL)DatabaseOptions{ |
| // Default page size for newly created databases. |
| // |
| // Guaranteed to match SQLITE_DEFAULT_PAGE_SIZE. |
| staticconstexprint kDefaultPageSize=4096; |
| |
| DatabaseOptions(); |
| DatabaseOptions(constDatabaseOptions&); |
| DatabaseOptions(DatabaseOptions&&); |
| DatabaseOptions&operator=(constDatabaseOptions&); |
| DatabaseOptions&operator=(DatabaseOptions&&); |
| ~DatabaseOptions(); |
| |
| // If true, the database can only be opened by one process at a time. |
| // |
| // SQLite supports a locking protocol that allows multiple processes to safely |
| // operate on the same database at the same time. The locking protocol is used |
| // on every transaction, and comes with a small performance penalty. |
| // |
| // Setting this to true causes the locking protocol to be used once, when the |
| // database is opened. No other SQLite process will be able to access the |
| // database at the same time. Note that this uses OS-level |
| // advisory/cooperative locking, so this does not protect the database file |
| // from uncooperative processes. |
| // |
| // More details at https://www.sqlite.org/pragma.html#pragma_locking_mode |
| // |
| // SQLite's locking protocol is summarized at |
| // https://www.sqlite.org/c3ref/io_methods.html |
| // |
| // Exclusive mode is strongly recommended. It reduces the I/O cost of setting |
| // up a transaction. It also removes the need of handling transaction failures |
| // due to lock contention. |
| DatabaseOptions& set_exclusive_locking(bool exclusive_locking){ |
| exclusive_locking_= exclusive_locking; |
| return*this; |
| } |
| |
| // If true, enables exclusive=true vfs URI parameter on the database file. |
| // This is only supported on Windows. |
| // |
| // If this option is true then the database file cannot be opened by any |
| // processes on the system until the database has been closed. Note, this is |
| // not the same as `exclusive_locking` above, which refers to |
| // advisory/cooperative locks. This option sets file handle sharing attributes |
| // to prevent the database files from being opened from any process including |
| // being opened a second time by the hosting process. |
| // |
| // This option is experimental and will be merged into the `exclusive_locking` |
| // option above if proven to cause no OS compatibility issues. |
| // TODO(crbug.com/40262539): Merge into above option, if possible. |
| DatabaseOptions& set_exclusive_database_file_lock( |
| bool exclusive_database_file_lock){ |
| exclusive_database_file_lock_= exclusive_database_file_lock; |
| return*this; |
| } |
| |
| // If true, enables SQLite's Write-Ahead Logging (WAL). |
| // |
| // WAL integration is under development, and should not be used in shipping |
| // Chrome features yet. |
| // |
| // WAL mode is currently not fully supported on FuchsiaOS. It will only be |
| // turned on if the database is also using exclusive locking mode. |
| // (https://crbug.com/1082059) |
| // |
| // Note: Changing page size is not supported when in WAL mode. So running |
| // 'PRAGMA page_size = <new-size>' will result in no-ops. |
| // |
| // Note: This option is not supported in read-only mode. |
| // |
| // More details at https://www.sqlite.org/wal.html |
| DatabaseOptions& set_wal_mode(bool wal_mode){ |
| wal_mode_= wal_mode; |
| return*this; |
| } |
| |
| // If true, enables preloading the database before opening it. |
| // |
| // Hints the file system that the database will be accessed soon. |
| // |
| // This method should be called on databases that are on the critical path to |
| // Chrome startup. Informing the filesystem about our expected access pattern |
| // early on reduces the likelihood that we'll be blocked on disk I/O. This has |
| // a high impact on startup time. |
| DatabaseOptions& set_preload(bool preload){ |
| preload_= preload; |
| return*this; |
| } |
| |
| // If true, transaction commit waits for data to reach persistent media. |
| // |
| // This is currently only meaningful on macOS. All other operating systems |
| // only support flushing directly to disk. |
| // |
| // If both `flush_to_media` and `wal_mode` are false, power loss can lead to |
| // database corruption. |
| // |
| // By default, SQLite considers that transactions commit when they reach the |
| // disk controller's memory. This guarantees durability in the event of |
| // software crashes, up to and including the operating system. In the event of |
| // power loss, SQLite may lose data. If `wal_mode` is false (SQLite uses a |
| // rollback journal), power loss can lead to database corruption. |
| // |
| // When this option is enabled, committing a transaction causes SQLite to wait |
| // until the data is written to the persistent media. This guarantees |
| // durability in the event of power loss, which is needed to guarantee the |
| // integrity of non-WAL databases. |
| // |
| // Note: This option is not supported in read-only mode. |
| DatabaseOptions& set_flush_to_media(bool flush_to_media){ |
| flush_to_media_= flush_to_media; |
| return*this; |
| } |
| |
| // Database page size. |
| // |
| // The value in this option is only applied to newly created databases. In |
| // other words, changing the value doesn't impact the databases that have |
| // already been created on the users' devices. So, changing the value in the |
| // code without a lot of work (re-creating existing databases) will result in |
| // inconsistent page sizes across the fleet of user devices, which will make |
| // it (even) more difficult to reason about database performance. |
| // |
| // Larger page sizes result in shallower B-trees, because they allow an inner |
| // page to hold more keys. On the flip side, larger page sizes may result in |
| // more I/O when making small changes to existing records. |
| // |
| // Must be a power of two between 512 and 65536 inclusive. |
| DatabaseOptions& set_page_size(int page_size){ |
| page_size_= page_size; |
| return*this; |
| } |
| |
| // The size of in-memory cache, in pages. |
| // |
| // SQLite's database cache will take up at most (`page_size` * `cache_size`) |
| // bytes of RAM. |
| // |
| // 0 invokes SQLite's default, which is currently to size up the cache to use |
| // exactly 2,048,000 bytes of RAM. |
| // |
| // Note: This option is not supported in read-only mode. |
| DatabaseOptions& set_cache_size(int cache_size){ |
| cache_size_= cache_size; |
| return*this; |
| } |
| |
| // Stores mmap failures in the SQL schema, instead of the meta table. |
| // |
| // This option is strongly discouraged for new databases, and will eventually |
| // be removed. |
| // |
| // If this option is true, the mmap status is stored in the database schema. |
| // Like any other schema change, changing the mmap status invalidates all |
| // pre-compiled SQL statements. |
| DatabaseOptions& set_mmap_alt_status_discouraged( |
| bool mmap_alt_status_discouraged){ |
| mmap_alt_status_discouraged_= mmap_alt_status_discouraged; |
| return*this; |
| } |
| |
| // If true, enables SQL views (a discouraged feature) for this database. |
| // |
| // The use of views is discouraged for Chrome code. See README.md for details |
| // and recommended replacements. |
| // |
| // If this option is false, CREATE VIEW and DROP VIEW succeed, but SELECT |
| // statements targeting views fail. |
| DatabaseOptions& set_enable_views_discouraged(bool enable_views_discouraged){ |
| enable_views_discouraged_= enable_views_discouraged; |
| return*this; |
| } |
| |
| // If true, enables SQL triggers for this database. |
| // |
| // The use of triggers should be thoughtful. See README.md for details. |
| // |
| // If this option is false, CREATE TRIGGER and DROP TRIGGER succeed, but the |
| // triggers won't fire. |
| DatabaseOptions& set_enable_triggers(bool enable_triggers){ |
| enable_triggers_= enable_triggers; |
| return*this; |
| } |
| |
| // If non-null, specifies the vfs implementation for the database to look for. |
| // Most use-cases do not require the use of a |
| // VFS(https://www.sqlite.org/vfs.html). This option should only be used when |
| // there is a clear need for it. |
| DatabaseOptions& set_vfs_name_discouraged(constchar* vfs_name_discouraged){ |
| vfs_name_discouraged_= vfs_name_discouraged; |
| return*this; |
| } |
| |
| // If true database attempts using memory mapped files. True by default. Only |
| // set to false when a condition is known that prevents the use of memory |
| // mapped files. See https://www.sqlite.org/mmap.html. |
| DatabaseOptions& set_mmap_enabled(bool mmap_enabled){ |
| mmap_enabled_= mmap_enabled; |
| return*this; |
| } |
| |
| // If true, the database is opened in read-only mode. All operations requiring |
| // write access will fail, including insert statements and some pragmas. |
| // Queries on the database will fail in the presence of a hot journal since |
| // the database file can't be modified to apply it. This must be used in the |
| // VFS returns read-only file descriptors, but not otherwise. |
| DatabaseOptions& set_read_only(bool read_only){ |
| read_only_= read_only; |
| return*this; |
| } |
| |
| private: |
| friendclassDatabase; |
| FRIEND_TEST_ALL_PREFIXES(DatabaseOptionsTest, |
| EnableViewsDiscouraged_FalseByDefault); |
| FRIEND_TEST_ALL_PREFIXES(DatabaseOptionsTest,FlushToDisk_FalseByDefault); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,ReOpenWithDifferentJournalMode); |
| |
| bool exclusive_locking_=true; |
| bool exclusive_database_file_lock_=false; |
| bool wal_mode_=false; |
| bool flush_to_media_=false; |
| int page_size_= kDefaultPageSize; |
| int cache_size_=0; |
| bool preload_=false; |
| bool mmap_alt_status_discouraged_=false; |
| bool enable_views_discouraged_=false; |
| constchar* vfs_name_discouraged_=nullptr; |
| bool mmap_enabled_=true; |
| bool read_only_=false; |
| bool enable_triggers_=false; |
| }; |
| |
| // Holds database diagnostics in a structured format. |
| struct COMPONENT_EXPORT(SQL)DatabaseDiagnostics{ |
| DatabaseDiagnostics(); |
| ~DatabaseDiagnostics(); |
| |
| usingTraceProto= perfetto::protos::pbzero::ChromeSqlDiagnostics; |
| // Write a representation of this object into tracing proto. |
| voidWriteIntoTrace(perfetto::TracedProto<TraceProto> context)const; |
| |
| // This was the original error code that triggered the error callback. Should |
| // generally match `error_code`, but this isn't guaranteed by the code. |
| int reported_sqlite_error_code=0; |
| |
| // Corresponds to `Database::GetErrorCode()`. |
| int error_code=0; |
| |
| // Corresponds to `Database::GetLastErrno()`. |
| int last_errno=0; |
| |
| // Corresponds to `Statement::GetSQLStatement()` of the problematic statement. |
| // This doesn't include the bound values, and therefore is free of any PII. |
| std::string sql_statement; |
| |
| // The 'version' value stored in the user database's meta table, if it can be |
| // read. If we fail to read the version of the user database, it's left as 0. |
| int version=0; |
| |
| // Most rows in 'sql_schema' have a non-NULL 'sql' column. Those rows' 'sql' |
| // contents are logged here, one element per row. |
| std::vector<std::string> schema_sql_rows; |
| |
| // Some rows of 'sql_schema' have a NULL 'sql' column. They are typically |
| // autogenerated indices, like "sqlite_autoindex_downloads_slices_1". These |
| // are also logged here by their 'name' column, one element per row. |
| std::vector<std::string> schema_other_row_names; |
| |
| // Sanity checks used for all errors. |
| bool has_valid_header=false; |
| bool has_valid_schema=false; |
| |
| // Corresponds to `Database::GetErrorMessage()`. |
| std::string error_message; |
| }; |
| |
| // Handle to an open SQLite database. |
| // |
| // Instances of this class are not thread-safe. With few exceptions, Database |
| // instances should only be accessed from one sequence. Database instances may |
| // be constructed on one sequence and safely used/destroyed on another. Callers |
| // may explicitly use `DetachFromSequence()` before moving to another sequence. |
| // |
| // When a Database instance goes out of scope, any uncommitted transactions are |
| // rolled back. |
| class COMPONENT_EXPORT(SQL)Database{ |
| private: |
| classStatementRef;// Forward declaration, see real one below. |
| |
| public: |
| // A convenience struct to |
| // 1. Convert (often implicitly) a static const char* string to a database tag |
| // to pass to the Database constructors |
| // 2. Check that the tag is in the DatabaseTag histogram variant list, at |
| // compile time. |
| // |
| // There is nothing special to do to use this struct. For example, the |
| // following works out of the box: |
| // |
| // Database db(DatabaseOptions{}, "TagName"); |
| // |
| // However, if the database is a unique_ptr created with make_unique, |
| // explicitly invoking the constructor is necessary: |
| // |
| // auto db = std::make_unique<Database>( |
| // DatabaseOptions{}, |
| // Database::Tag("TagName")); |
| structTag{ |
| // Purposely not explicit to avoid requiring callers to wrap their tag |
| // string. |
| constevalTag(constchar* tag_value): value(tag_value){ |
| if(!sql_metrics::IsValidDatabaseTag(tag_value)){ |
| // This will never actually invoke what's under NOTREACHED(), but |
| // NOTREACHED() is invalid in a consteval context so compilation will |
| // fail iff the string is invalid. |
| NOTREACHED()<<"Invalid database tag. Did you add it to the " |
| "DatabaseTag variant in sql/histograms.xml?"; |
| } |
| } |
| |
| std::string_view value; |
| }; |
| |
| // Creates an instance that can receive Open() / OpenInMemory() calls. |
| // |
| // Some `options` members are only applied to newly created databases. |
| // |
| // Most operations on the new instance will fail until Open() / OpenInMemory() |
| // is called. |
| // |
| // `tag` is a string uniquely identifying this database for metrics. This |
| // class automatically uses `tag` to determine which histogram to record to |
| // for timing and error histograms. Tests that don't care about those |
| // histograms values can use `sql::test::kTestTag` from |
| // sql/test/test_helpers.h. |
| Database(DatabaseOptions options,Tag tag); |
| |
| // Convenience constructor for callers that use default options. |
| explicitDatabase(Tag tag); |
| |
| Database(constDatabase&)=delete; |
| Database&operator=(constDatabase&)=delete; |
| Database(Database&&)=delete; |
| Database&operator=(Database&&)=delete; |
| ~Database(); |
| |
| // Pre-init configuration ---------------------------------------------------- |
| |
| // The page size that will be used when creating a new database. |
| int page_size()const{return options_.page_size_;} |
| |
| // Returns whether a database will be opened in WAL mode. |
| boolUseWALMode()const; |
| |
| // Opt out of memory-mapped file I/O. |
| void set_mmap_disabled(){ mmap_disabled_=true;} |
| |
| // Set an error-handling callback. On errors, the error number (and |
| // statement, if available) will be passed to the callback. |
| // |
| // If no callback is set, the default error-handling behavior is invoked. The |
| // default behavior is to LOGs the error and propagate the failure. |
| // |
| // In DCHECK-enabled builds, the default error-handling behavior currently |
| // DCHECKs on errors. This is not correct, because DCHECKs are supposed to |
| // cover invariants and never fail, whereas SQLite errors can surface even on |
| // correct usage, due to I/O errors and data corruption. At some point in the |
| // future, errors will not result in DCHECKs. |
| // |
| // The callback will be called on the sequence used for database operations. |
| // The callback will never be called after the Database instance is destroyed. |
| usingErrorCallback=base::RepeatingCallback<void(int,Statement*)>; |
| void set_error_callback(ErrorCallback callback){ |
| DCHECK(!callback.is_null())<<"Use reset_error_callback() explicitly"; |
| DCHECK(error_callback_.is_null()) |
| <<"Overwriting previously set error callback"; |
| error_callback_= std::move(callback); |
| } |
| void reset_error_callback(){ error_callback_.Reset();} |
| bool has_error_callback()const{return!error_callback_.is_null();} |
| |
| const std::string& histogram_tag()const{return histogram_tag_;} |
| |
| // Asks SQLite to perform a full integrity check on the database. |
| // |
| // Returns true if the integrity check was completed successfully. Success |
| // does not necessarily entail that the database is healthy. Finding |
| // corruption and reporting it in `messages` counts as success. |
| // |
| // If the method returns true, `messages` is populated with a list of |
| // diagnostic messages. If the integrity check finds no errors, `messages` |
| // will contain exactly one "ok" string. This unusual API design is explained |
| // by the fact that SQLite exposes integrity check functionality as a PRAGMA, |
| // and the PRAGMA returns "ok" in case of success. |
| boolFullIntegrityCheck(std::vector<std::string>* messages); |
| |
| // Meant to be called from a client error callback so that it's able to |
| // get diagnostic information about the database. `diagnostics` is an optional |
| // out parameter. If `diagnostics` is defined, this method populates all of |
| // its fields. |
| std::stringGetDiagnosticInfo(int extended_error, |
| Statement* statement, |
| DatabaseDiagnostics* diagnostics=nullptr); |
| |
| // Reports memory usage into provided memory dump with the given name. |
| boolReportMemoryUsage(base::trace_event::ProcessMemoryDump* pmd, |
| const std::string& dump_name); |
| |
| // Initialization ------------------------------------------------------------ |
| |
| // Opens or creates a database on disk. |
| // |
| // `db_file_path` points to the file storing database pages. Other files |
| // associated with the database (rollback journal, write-ahead log, |
| // shared-memory file) may be created. |
| // |
| // Returns true in case of success, false in case of failure. If an error |
| // occurs, this function will invoke the error callback if it is present and |
| // then may attempt to open the database a second time. If the second attempt |
| // succeeds, it will return true. |
| [[nodiscard]]boolOpen(constbase::FilePath& db_file_path); |
| |
| // Alternative to Open() that creates an in-memory database. |
| // |
| // Returns true in case of success, false in case of failure. |
| // |
| // The memory associated with the database will be released when the database |
| // is closed. |
| [[nodiscard]]boolOpenInMemory(); |
| |
| // Returns true if the database has been successfully opened. |
| bool is_open()const; |
| |
| // Detach from the currently-attached sequence. If already attached to a |
| // sequence, this method must be called from that sequence. |
| voidDetachFromSequence(); |
| |
| // Closes the database. This is automatically performed on destruction for |
| // you, but this allows you to close the database early. You must not call |
| // any other functions after closing it. It is permissable to call Close on |
| // an uninitialized or already-closed database. |
| voidClose(); |
| |
| // Release all non-essential memory associated with this database connection. |
| voidTrimMemory(); |
| |
| // Raze the database to the ground. This approximates creating a |
| // fresh database from scratch, within the constraints of SQLite's |
| // locking protocol (locks and open handles can make doing this with |
| // filesystem operations problematic). Returns true if the database |
| // was razed. |
| // |
| // false is returned if the database is locked by some other |
| // process. |
| // |
| // NOTE(shess): Raze() will DCHECK in the following situations: |
| // - database is not open. |
| // - the database has a transaction open. |
| // - a SQLite issue occurs which is structural in nature (like the |
| // statements used are broken). |
| // Since Raze() is expected to be called in unexpected situations, |
| // these all return false, since it is unlikely that the caller |
| // could fix them. |
| // |
| // The database's page size is taken from |options_.page_size|. The |
| // existing database's |auto_vacuum| setting is lost (the |
| // possibility of corruption makes it unreliable to pull it from the |
| // existing database). To re-enable on the empty database requires |
| // running "PRAGMA auto_vacuum = 1;" then "VACUUM". |
| // |
| // NOTE(shess): For Android, SQLITE_DEFAULT_AUTOVACUUM is set to 1, |
| // so Raze() sets auto_vacuum to 1. |
| // |
| // TODO(shess): Raze() needs a database so cannot clear SQLITE_NOTADB. |
| // TODO(shess): Bake auto_vacuum into Database's API so it can |
| // just pick up the default. |
| boolRaze(); |
| |
| // Breaks all outstanding transactions (as initiated by |
| // BeginTransaction()), closes the SQLite database, and poisons the |
| // object so that all future operations against the Database (or |
| // its Statements) fail safely, without side effects. |
| // |
| // This is intended as an alternative to Close() in error callbacks. |
| // Close() should still be called at some point. |
| voidPoison(); |
| |
| // `Raze()` the database and `Poison()` the handle. Returns the return |
| // value from `Raze()`. |
| boolRazeAndPoison(); |
| |
| // Delete the underlying database files associated with |path|. This should be |
| // used on a database which is not opened by any Database instance. Open |
| // Database instances pointing to the database can cause odd results or |
| // corruption (for instance if a hot journal is deleted but the associated |
| // database is not). |
| // |
| // Returns true if the database file and associated journals no |
| // longer exist, false otherwise. If the database has never |
| // existed, this will return true. |
| staticboolDelete(constbase::FilePath& path); |
| |
| // Transactions -------------------------------------------------------------- |
| |
| // Transaction management. We maintain a virtual transaction stack to emulate |
| // nested transactions since sqlite can't do nested transactions. The |
| // limitation is you can't roll back a sub transaction: if any transaction |
| // fails, all transactions open will also be rolled back. Any nested |
| // transactions after one has rolled back will return fail for Begin(). If |
| // Begin() fails, you must not call Commit or Rollback(). |
| // |
| // Normally you should use sql::Transaction to manage a transaction, which |
| // will scope it to a C++ context. |
| [[nodiscard]]boolBeginTransaction(InternalApiToken); |
| voidRollbackTransaction(InternalApiToken); |
| [[nodiscard]]boolCommitTransaction(InternalApiToken); |
| |
| // These methods are deprecated and will be removed in the future: The |
| // `Transaction` class should be used instead. |
| boolBeginTransactionDeprecated(); |
| voidRollbackTransactionDeprecated(); |
| boolCommitTransactionDeprecated(); |
| |
| // Rollback all outstanding transactions. Use with care, there may |
| // be scoped transactions on the stack. |
| voidRollbackAllTransactions(); |
| |
| boolHasActiveTransactions()const{ |
| DCHECK_GE(transaction_nesting_,0); |
| return is_open()&& transaction_nesting_>0; |
| } |
| |
| // Deprecated in favor of HasActiveTransactions(). |
| // |
| // Returns the current transaction nesting, which will be 0 if there are |
| // no open transactions. |
| int transaction_nesting()const{return transaction_nesting_;} |
| |
| // Attached databases--------------------------------------------------------- |
| |
| // Attaches an existing database to this connection. |
| // |
| // `attachment_point` must only contain lowercase letters. |
| // |
| // Use is generally discouraged in production code. The README has more |
| // details. |
| // |
| // On the SQLite version shipped with Chrome (3.21+, Oct 2017), databases can |
| // be attached while a transaction is opened. However, these databases cannot |
| // be detached until the transaction is committed or aborted. |
| boolAttachDatabase(constbase::FilePath& other_db_path, |
| std::string_view attachment_point); |
| |
| // Detaches a database that was previously attached with AttachDatabase(). |
| // |
| // `attachment_point` must match the argument of a previously successsful |
| // AttachDatabase() call. |
| // |
| // Attachment APIs are only exposed for use in recovery. General use is |
| // discouraged in Chrome. The README has more details. |
| boolDetachDatabase(std::string_view attachment_point); |
| |
| // Statements ---------------------------------------------------------------- |
| |
| // Executes a SQL statement. Returns true for success, and false for failure. |
| // |
| // `sql` should be a single SQL statement. Production code should not execute |
| // multiple SQL statements at once, to facilitate crash debugging. Test code |
| // should use ExecuteScriptForTesting(). |
| // |
| // `sql` cannot have parameters. Statements with parameters can be handled by |
| // sql::Statement. See GetCachedStatement() and GetUniqueStatement(). |
| [[nodiscard]]boolExecute(base::cstring_view sql); |
| |
| // Executes a sequence of SQL statements. |
| // |
| // Returns true if all statements execute successfully. If a statement fails, |
| // stops and returns false. Calls should be wrapped in ASSERT_TRUE(). |
| // |
| // The database's error handler is not invoked when errors occur. This method |
| // is a convenience for setting up a complex on-disk database state, such as |
| // an old schema version with test contents. |
| [[nodiscard]]boolExecuteScriptForTesting(base::cstring_view sql_script); |
| |
| // Returns a statement for the given SQL using the statement cache. It can |
| // take a nontrivial amount of work to parse and compile a statement, so |
| // keeping commonly-used ones around for future use is important for |
| // performance. |
| // |
| // The SQL_FROM_HERE macro is the recommended way of generating a StatementID. |
| // Code that generates custom IDs must ensure that a StatementID is never used |
| // for different SQL statements. Failing to meet this requirement results in |
| // incorrect behavior, and should be caught by a DCHECK. |
| // |
| // The SQL statement passed in |sql| must match the SQL statement reported |
| // back by SQLite. Mismatches are caught by a DCHECK, so any code that has |
| // automated test coverage or that was manually tested on a DCHECK build will |
| // not exhibit this problem. Mismatches generally imply that the statement |
| // passed in has extra whitespace or comments surrounding it, which waste |
| // storage and CPU cycles. |
| // |
| // If the |sql| has an error, an invalid, inert StatementRef is returned (and |
| // the code will crash in debug). The caller must deal with this eventuality, |
| // either by checking validity of the |sql| before calling, by correctly |
| // handling the return of an inert statement, or both. |
| // |
| // Example: |
| // sql::Statement stmt(database_.GetCachedStatement( |
| // SQL_FROM_HERE, "SELECT * FROM foo")); |
| // if (!stmt) |
| // return false; // Error creating statement. |
| scoped_refptr<StatementRef>GetCachedStatement(StatementID id, |
| base::cstring_view sql); |
| |
| // Used to check a |sql| statement for syntactic validity. If the statement is |
| // valid SQL, returns true. |
| boolIsSQLValid(base::cstring_view sql); |
| |
| // Returns a non-cached statement for the given SQL. Use this for SQL that |
| // is only executed once or only rarely (there is overhead associated with |
| // keeping a statement cached). |
| // |
| // See GetCachedStatement above for examples and error information. |
| scoped_refptr<StatementRef>GetUniqueStatement(base::cstring_view sql); |
| |
| // Returns a non-cached statement same as `GetUniqueStatement()`, except |
| // returns an invalid statement if the statement makes direct changes to the |
| // database file. This readonly check does not include changes made by |
| // application-defined functions. See more at: |
| // https://www.sqlite.org/c3ref/stmt_readonly.html. |
| scoped_refptr<Database::StatementRef>GetReadonlyStatement( |
| base::cstring_view sql); |
| |
| // Opens a blob for streaming. Returns nullopt on failure. Note that this |
| // should only be called if the given table, column, and row is known to |
| // exist --- everything else is an error. For a list of failure modes, see |
| // https://www.sqlite.org/c3ref/blob_open.html |
| // |
| // See `StreamingBlobHandle` docs for notes on lifetime. |
| std::optional<StreamingBlobHandle>GetStreamingBlob(base::cstring_view table, |
| base::cstring_view column, |
| int64_t row_id, |
| boolreadonly); |
| |
| // Performs a passive checkpoint on the main attached database if it is in |
| // WAL mode. Returns true if the checkpoint was successful and false in case |
| // of an error. It is a no-op if the database is not in WAL mode. |
| // |
| // Note: Checkpointing is a very slow operation and will block any writes |
| // until it is finished. Please use with care. |
| boolCheckpointDatabase(); |
| |
| // Info querying ------------------------------------------------------------- |
| |
| // Returns true if the given structure exists. Instead of test-then-create, |
| // callers should almost always prefer the "IF NOT EXISTS" version of the |
| // CREATE statement. |
| // TODO(https://crbug.com/341639215): these should take a `base::cstring`. |
| boolDoesIndexExist(std::string_view index_name); |
| boolDoesTableExist(std::string_view table_name); |
| boolDoesViewExist(std::string_view table_name); |
| |
| // Returns true if a column with the given name exists in the given table. |
| // |
| // Calling this method on a VIEW returns an unspecified result. |
| // |
| // This should only be used by migration code for legacy features that do not |
| // use MetaTable, and need an alternative way of figuring out the database's |
| // current version. |
| boolDoesColumnExist(base::cstring_view table_name, |
| base::cstring_view column_name); |
| |
| // Returns sqlite's internal ID for the last inserted row. Valid only |
| // immediately after an insert. |
| int64_tGetLastInsertRowId()const; |
| |
| // Returns sqlite's count of the number of rows modified by the last |
| // statement executed. Will be 0 if no statement has executed or the database |
| // is closed. |
| int64_tGetLastChangeCount(); |
| |
| // Approximates the amount of memory used by SQLite for this database. |
| // |
| // This measures the memory used for the page cache (most likely the biggest |
| // consumer), database schema, and prepared statements. |
| // |
| // The memory used by the page cache can be recovered by calling TrimMemory(), |
| // which will cause SQLite to drop the page cache. |
| intGetMemoryUsage(); |
| |
| // Errors -------------------------------------------------------------------- |
| |
| // Returns the error code associated with the last sqlite operation. |
| intGetErrorCode()const; |
| |
| // Returns the errno associated with GetErrorCode(). See <errno.h>. |
| intGetLastErrno()const; |
| |
| // Returns a pointer to a statically allocated string associated with the |
| // last sqlite operation. |
| constchar*GetErrorMessage()const; |
| |
| // Return a reproducible representation of the schema equivalent to |
| // running the following statement at a sqlite3 command-line: |
| // SELECT type, name, tbl_name, sql FROM sqlite_schema ORDER BY 1, 2, 3, 4; |
| std::stringGetSchema(); |
| |
| // Returns |true| if there is an error expecter (see SetErrorExpecter), and |
| // that expecter returns |true| when passed |error|. Clients which provide an |
| // |error_callback| should use IsExpectedSqliteError() to check for unexpected |
| // errors; if one is detected, DLOG(FATAL) is generally appropriate (see |
| // OnSqliteError implementation). |
| staticboolIsExpectedSqliteError(int sqlite_error_code); |
| |
| // Computes the path of a database's rollback journal. |
| // |
| // The journal file is created at the beginning of the database's first |
| // transaction. The file may be removed and re-created between transactions, |
| // depending on whether the database is opened in exclusive mode, and on |
| // configuration options. The journal file does not exist when the database |
| // operates in WAL mode. |
| // |
| // This is intended for internal use and tests. To preserve our ability to |
| // iterate on our SQLite configuration, features must avoid relying on |
| // the existence of specific files. |
| staticbase::FilePathJournalPath(constbase::FilePath& db_path); |
| |
| // Computes the path of a database's write-ahead log (WAL). |
| // |
| // The WAL file exists while a database is opened in WAL mode. |
| // |
| // This is intended for internal use and tests. To preserve our ability to |
| // iterate on our SQLite configuration, features must avoid relying on |
| // the existence of specific files. |
| staticbase::FilePathWriteAheadLogPath(constbase::FilePath& db_path); |
| |
| // Computes the path of a database's shared memory (SHM) file. |
| // |
| // The SHM file is used to coordinate between multiple processes using the |
| // same database in WAL mode. Thus, this file only exists for databases using |
| // WAL and not opened in exclusive mode. |
| // |
| // This is intended for internal use and tests. To preserve our ability to |
| // iterate on our SQLite configuration, features must avoid relying on |
| // the existence of specific files. |
| staticbase::FilePathSharedMemoryFilePath(constbase::FilePath& db_path); |
| |
| // Internal state accessed by other classes in //sql. |
| base::WeakPtr<Database>GetWeakPtr(InternalApiToken); |
| sqlite3* db(InternalApiToken)const{return db_;} |
| bool poisoned(InternalApiToken)const{return poisoned_;} |
| base::FilePathDbPath(InternalApiToken)const{returnDbPath();} |
| |
| // Interface with sql::test::ScopedErrorExpecter. |
| usingScopedErrorExpecterCallback=base::RepeatingCallback<bool(int)>; |
| staticvoidSetScopedErrorExpecter(ScopedErrorExpecterCallback* expecter, |
| base::PassKey<test::ScopedErrorExpecter>); |
| staticvoidResetScopedErrorExpecter( |
| base::PassKey<test::ScopedErrorExpecter>); |
| |
| private: |
| // Statement accesses StatementRef which we don't want to expose to everybody |
| // (they should go through Statement). |
| friendclassStatement; |
| |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,CachedStatement); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,CollectDiagnosticInfo); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,ComputeMmapSizeForOpen); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,ComputeMmapSizeForOpenAltStatus); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,OnMemoryDump); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest, |
| RazeAndPoison_ComputeMmapSizeForOpen); |
| FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest,RegisterIntentToUpload); |
| FRIEND_TEST_ALL_PREFIXES(SQLiteFeaturesTest,WALNoClose); |
| FRIEND_TEST_ALL_PREFIXES(SQLEmptyPathDatabaseTest,EmptyPathTest); |
| FRIEND_TEST_ALL_PREFIXES(StreamingBlobHandleTest,Basic); |
| |
| // A scoped utility to setup error reporting during the `Open()` operation |
| classScopedOpenErrorReporter{ |
| public: |
| // db: the database to instrument. Must outlive `this` |
| // histogram: the histogram to record the error code into. Will |
| // automatically be suffixed with `Database::histogram_tag()` if it's |
| // specified, "NoTag" otherwise. |
| ScopedOpenErrorReporter(Database* db, std::string_view histogram); |
| ~ScopedOpenErrorReporter(); |
| |
| private: |
| // The callback that will be invoked by the database in case of an error. |
| voidOnErrorDuringOpen(SqliteResultCode code); |
| |
| raw_ptr<Database> db_; |
| std::string_view histogram_; |
| }; |
| |
| // Invoke `open_error_reporting_callback_` if it's set. |
| voidMaybeReportErrorDuringOpen(SqliteResultCode code); |
| |
| // Implements Open(), OpenInMemory(). |
| // |
| // `db_file_path` is a UTF-8 path to the file storing the database pages. If |
| // `file_name` is the SQLite magic memory path :memory:, the database will be |
| // opened in-memory. |
| boolOpenInternal(const std::string& file_name); |
| |
| // Requests the operating system to preload the pages on disk into memory. |
| voidPreloadInternal(constbase::FilePath& path); |
| |
| // Configures the underlying sqlite3* object via sqlite3_db_config(). |
| // |
| // To minimize the number of possible SQLite code paths executed in Chrome, |
| // this method must be called right after the underlying sqlite3* object is |
| // obtained from sqlite3_open*(), before any other sqlite3_*() methods are |
| // called on the object. |
| voidConfigureSqliteDatabaseObject(); |
| |
| // Internal close function used by Close() and RazeAndPoison(). |
| // |forced| indicates that orderly-shutdown checks should not apply. |
| voidCloseInternal(bool forced); |
| |
| // Called when a blob opened with `GetStreamingBlob()` is closed. `result` may |
| // or may not be an error; if it is, `error_source` identifies which sqlite3 |
| // call caused the error. |
| voidOnStreamingBlobClosed(SqliteResultCode result,constchar* error_source); |
| |
| // Construct a ScopedBlockingCall to annotate IO calls, but only if |
| // database wasn't open in memory. ScopedBlockingCall uses |from_here| to |
| // declare its blocking execution scope (see https://www.crbug/934302). |
| voidInitScopedBlockingCall( |
| constbase::Location& from_here, |
| std::optional<base::ScopedBlockingCall>* scoped_blocking_call)const{ |
| if(!in_memory_) |
| scoped_blocking_call->emplace(from_here,base::BlockingType::MAY_BLOCK); |
| } |
| |
| // Internal helper for Does*Exist() functions. |
| boolDoesSchemaItemExist(std::string_view name, std::string_view type); |
| |
| // Used to implement the interface with sql::test::ScopedErrorExpecter. |
| staticScopedErrorExpecterCallback* current_expecter_cb_; |
| |
| // A StatementRef is a refcounted wrapper around a sqlite statement pointer. |
| // Refcounting allows us to give these statements out to sql::Statement |
| // objects while also optionally maintaining a cache of compiled statements |
| // by just keeping a refptr to these objects. |
| // |
| // A statement ref can be valid, in which case it can be used, or invalid to |
| // indicate that the statement hasn't been created yet, has an error, or has |
| // been destroyed. |
| // |
| // The Database may revoke a StatementRef in some error cases, so callers |
| // should always check validity before using. |
| class COMPONENT_EXPORT(SQL)StatementRef |
| :publicbase::RefCounted<StatementRef>{ |
| public: |
| REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); |
| |
| // |database| is the sql::Database instance associated with |
| // the statement, and is used for tracking outstanding statements |
| // and for error handling. Set to nullptr for invalid refs. |
| // |stmt| is the actual statement, and should only be null |
| // to create an invalid ref. |was_valid| indicates whether the |
| // statement should be considered valid for diagnostic purposes. |
| // |was_valid| can be true for a null |stmt| if the Database has |
| // been forcibly closed by an error handler. |
| StatementRef(Database* database, sqlite3_stmt* stmt,bool was_valid); |
| |
| StatementRef(constStatementRef&)=delete; |
| StatementRef&operator=(constStatementRef&)=delete; |
| StatementRef(StatementRef&&)=delete; |
| StatementRef&operator=(StatementRef&&)=delete; |
| |
| // When true, the statement can be used. |
| bool is_valid()const{return!!stmt_;} |
| |
| // When true, the statement is either currently valid, or was |
| // previously valid but the database was forcibly closed. Used |
| // for diagnostic checks. |
| bool was_valid()const{return was_valid_;} |
| |
| // If we've not been linked to a database, this will be null. |
| Database* database()const{return database_;} |
| |
| // Returns the sqlite statement if any. If the statement is not active, |
| // this will return nullptr. |
| sqlite3_stmt* stmt()const{return stmt_;} |
| |
| // Assumes ownership of `blob`. |
| // |
| // To be called BEFORE the data in `blob` will be bound to a SQLite |
| // statement SQLite. SQLite assumes the pointer will remain valid until the |
| // statement is finalized or the parameter is unbound. |
| // |
| // A span pointing to the newly owned memory is returned --- this is the |
| // pointer that should be passed to sqlite3 functions. |
| base::span<constuint8_t>TakeBlobMemory( |
| int index, |
| scoped_refptr<base::RefCountedMemory> blob); |
| |
| // Releases memory passed by `TakeBlobMemory()`, if any. The caller should |
| // also tell SQLite to unbind or rebind the parameter (i.e. update the |
| // binding that was previously set with TakeBlobMemory's output). |
| voidClearBlobMemory(int index); |
| |
| // Resets the statement and, if `clear_bound_variables` is true, drops |
| // parameter bindings, including dropping `bound_blobs_`. |
| voidReset(bool clear_bound_variables); |
| |
| // Destroys the compiled statement and sets it to nullptr. The statement |
| // will no longer be active. |forced| is used to indicate if |
| // orderly-shutdown checks should apply (see Database::RazeAndPoison()). |
| voidClose(bool forced); |
| |
| // Construct a ScopedBlockingCall to annotate IO calls, but only if |
| // database wasn't open in memory. ScopedBlockingCall uses |from_here| to |
| // declare its blocking execution scope (see https://www.crbug/934302). |
| voidInitScopedBlockingCall( |
| constbase::Location& from_here, |
| std::optional<base::ScopedBlockingCall>* scoped_blocking_call)const{ |
| if(database_) |
| database_->InitScopedBlockingCall(from_here, scoped_blocking_call); |
| } |
| |
| private: |
| friendclassbase::RefCounted<StatementRef>; |
| |
| ~StatementRef(); |
| |
| // Holds onto memory that is to be used by the statement. These blobs have |
| // been bound with `SQLITE_STATIC`, see |
| // https://www.sqlite.org/c3ref/bind_blob.html for docs. |
| // Note that value pointer stability is important, and that's granted by |
| // scoped_refptr. |
| base::flat_map<int, scoped_refptr<base::RefCountedMemory>> bound_blobs_; |
| |
| raw_ptr<Database> database_; |
| raw_ptr<sqlite3_stmt> stmt_; |
| bool was_valid_; |
| }; |
| friendclassStatementRef; |
| |
| // Executes a rollback statement, ignoring all transaction state. Used |
| // internally in the transaction management code. |
| voidDoRollback(); |
| |
| // Called by a StatementRef when it's being created or destroyed. See |
| // open_statements_ below. |
| voidStatementRefCreated(StatementRef*ref); |
| voidStatementRefDeleted(StatementRef*ref); |
| |
| // Used by sql:: internals to report a SQLite error related to this database. |
| // |
| // `sqlite_error_code` contains the error code reported by SQLite. Possible |
| // values are documented at https://www.sqlite.org/rescode.html |
| // |
| // `statement` is non-null if the error is associated with a sql::Statement. |
| // Otherwise, `sql_statement` will be a non-null string pointing to a |
| // statically-allocated (valid for the entire duration of the process) buffer |
| // pointing to either a SQL statement or a SQL comment (starting with "-- ") |
| // pointing to a "sqlite3_" function name. |
| voidOnSqliteError(SqliteErrorCode sqlite_error_code, |
| Statement* statement, |
| constchar* sql_statement); |
| |
| // Raze the database to the ground. This is the internal version called by |
| // Raze(...). |
| boolRazeInternal(); |
| |
| // Like Execute(), but returns a SQLite result code. |
| // |
| // This method returns SqliteResultCode::kOk or a SQLite error code. In other |
| // words, it never returns SqliteResultCode::{kDone, kRow}. |
| // |
| // This method is only exposed to the Database implementation. Code that uses |
| // sql::Database should not be concerned with SQLite result codes. |
| [[nodiscard]]SqliteResultCodeExecuteAndReturnResultCode( |
| base::cstring_view sql); |
| |
| // Like |Execute()|, but retries if the database is locked. |
| [[nodiscard]]boolExecuteWithTimeout(base::cstring_view sql, |
| base::TimeDelta ms_timeout); |
| |
| // Implementation helper for GetUniqueStatement() and GetCachedStatement(). |
| scoped_refptr<StatementRef>GetStatementImpl(base::cstring_view sql, |
| bool is_readonly); |
| |
| // Release page-cache memory if memory-mapped I/O is enabled and the database |
| // was changed. Passing true for |implicit_change_performed| allows |
| // overriding the change detection for cases like DDL (CREATE, DROP, etc), |
| // which do not participate in the total-rows-changed tracking. |
| voidReleaseCacheMemoryIfNeeded(bool implicit_change_performed); |
| |
| // Returns the results of sqlite3_db_filename(), which should match the path |
| // passed to Open(). |
| base::FilePathDbPath()const; |
| |
| // Helper to collect diagnostic info for a corrupt database. |
| std::stringCollectCorruptionInfo(); |
| |
| // Helper to collect diagnostic info for errors. `diagnostics` is an optional |
| // out parameter. If `diagnostics` is defined, this method populates SOME of |
| // its fields. Some of the fields are left unmodified for the caller. |
| std::stringCollectErrorInfo(int sqlite_error_code, |
| Statement* stmt, |
| DatabaseDiagnostics* diagnostics)const; |
| |
| // The size of the memory mapping that SQLite should use for this database. |
| // |
| // The return value follows the semantics of "PRAGMA mmap_size". In |
| // particular, zero (0) means memory-mapping should be disabled, and the value |
| // is capped by SQLITE_MAX_MMAP_SIZE. More details at |
| // https://www.sqlite.org/pragma.html#pragma_mmap_size |
| // |
| // "Memory-mapped access" is usually shortened to "mmap", which is the name of |
| // the POSIX system call used to implement. The same principles apply on |
| // Windows, but its more-descriptive API names don't make for good shorthands. |
| // |
| // When mmap is enabled, SQLite attempts to use the memory-mapped area (by |
| // calling xFetch() in the VFS file API) instead of requesting a database page |
| // buffer from the pager and reading (via xRead() in the VFS API) into it. |
| // When this works out, the database page cache ends up only storing pages |
| // whose contents has been modified. More details at |
| // https://sqlite.org/mmap.html |
| // |
| // I/O errors on memory-mapped files result in crashes in Chrome. POSIX |
| // systems signal SIGSEGV or SIGBUS on I/O errors in mmap-ed files. Windows |
| // raises the EXECUTE_IN_PAGE_ERROR strucuted exception in this case. Chrome |
| // does not catch signals or structured exceptions. |
| // |
| // In order to avoid crashes, this method attempts to read the file using |
| // regular I/O, and returns 0 (no mmap) if it encounters any error. |
| size_tComputeMmapSizeForOpen(); |
| |
| // Helpers for ComputeMmapSizeForOpen(). |
| boolGetMmapAltStatus(int64_t* status); |
| boolSetMmapAltStatus(int64_t status); |
| |
| // Returns a SQLite VFS interface pointer to the file storing database pages. |
| // |
| // Returns null if the database is not backed by a VFS file. This is always |
| // the case for in-memory databases. |
| // |
| // This method must only be called while the database is successfully opened. |
| sqlite3_file*GetSqliteVfsFile(); |
| |
| // Records a histogram named `name_prefix` suffixed with this database's |
| // histogram tag. For instance, `RecordTimingHistogram("Foo.", ...)` called on |
| // a database with the tag "Bar" will record into "Foo.Bar". This function |
| // chooses reasonable bucketing parameters for typical database operations |
| // timing and reports in microseconds. |
| voidRecordTimingHistogram(std::string_view name_prefix, |
| base::TimeDelta timing)const; |
| |
| // Returns the name of the track in which to record this database's events |
| // based on its histogram tag. |
| perfetto::NamedTrackGetTracingNamedTrack()const; |
| |
| // Will eventually be checked on all methods. See https://crbug.com/1306694 |
| SEQUENCE_CHECKER(sequence_checker_); |
| |
| // The actual sqlite database. Will be null before Init has been called or if |
| // Init resulted in an error. |
| raw_ptr<sqlite3> db_=nullptr; |
| |
| // Immutable options for the database. |
| constDatabaseOptions options_; |
| |
| // Holds references to all cached statements so they remain active. |
| // |
| // flat_map is appropriate here because the codebase has ~400 cached |
| // statements, and each statement is at most one insertion in the map |
| // throughout a process' lifetime. |
| base::flat_map<StatementID, scoped_refptr<StatementRef>> statement_cache_; |
| |
| // A list of all StatementRefs we've given out. Each ref must register with |
| // us when it's created or destroyed. This allows us to potentially close |
| // any open statements when we encounter an error. |
| std::set<raw_ptr<StatementRef>> open_statements_; |
| |
| // The number of blobs open for streaming, tracked for debugging purposes. |
| size_t outstanding_blob_count_=0; |
| |
| // When non-zero, indicates that `this` is inside `OnSqliteError()`. |
| size_t handling_error_nesting_=0; |
| |
| // Number of currently-nested transactions. |
| int transaction_nesting_=0; |
| |
| // True if any of the currently nested transactions have been rolled back. |
| // When we get to the outermost transaction, this will determine if we do |
| // a rollback instead of a commit. |
| bool needs_rollback_=false; |
| |
| // True if database is open with OpenInMemory(), False if database is open |
| // with Open(). |
| bool in_memory_=false; |
| |
| // |true| if the Database was closed using RazeAndPoison(). Used |
| // to enable diagnostics to distinguish calls to never-opened |
| // databases (incorrect use of the API) from calls to once-valid |
| // databases. |
| bool poisoned_=false; |
| |
| // |true| if SQLite memory-mapped I/O is not desired for this database. |
| bool mmap_disabled_; |
| |
| // |true| if SQLite memory-mapped I/O was enabled for this database. |
| // Used by ReleaseCacheMemoryIfNeeded(). |
| bool mmap_enabled_=false; |
| |
| // Used by ReleaseCacheMemoryIfNeeded() to track if new changes have happened |
| // since memory was last released. |
| int64_t total_changes_at_last_release_=0; |
| |
| // Called when a SQLite error occurs. |
| // |
| // This callback may be null, in which case errors are handled using a default |
| // behavior. |
| // |
| // This callback must never be exposed outside this Database instance. This is |
| // a straight-forward way to guarantee that this callback will not be called |
| // after the Database instance goes out of scope. set_error_callback() makes |
| // this guarantee. |
| ErrorCallback error_callback_; |
| |
| // Developer-friendly database ID used in logging output and memory dumps. |
| std::string histogram_tag_; |
| |
| // Persist the track name as a member since perfetto needs the original string |
| // for the name to remain alive (without taking ownership of it). |
| std::string tracing_track_name_; |
| |
| // Stores the dump provider object when db is open. |
| std::unique_ptr<DatabaseMemoryDumpProvider> memory_dump_provider_; |
| |
| // If set, this callback will be invoked when an sqlite error is triggered |
| // during `OpenInternal` or `Execute`s triggered from `Open`. |
| base::RepeatingCallback<void(SqliteResultCode)> |
| open_error_reporting_callback_; |
| |
| // Weak factory for tracking lifetime of `this` (as opposed to |
| // `weak_factory_`, which will also invalidate pointers if the database is |
| // closed). |
| base::WeakPtrFactory<Database> weak_factory_lifetime_tracker_{this}; |
| |
| // Vends WeakPtr<Database> for internal scoping helpers. |
| base::WeakPtrFactory<Database> weak_factory_{this}; |
| }; |
| |
| }// namespace sql |
| |
| #endif// SQL_DATABASE_H_ |