mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Reprocess: added -track_changes option. Added rtabmap-dpupdate.
This commit is contained in:
@@ -21,8 +21,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
|
|||||||
# VERSION
|
# VERSION
|
||||||
#######################
|
#######################
|
||||||
SET(RTABMAP_MAJOR_VERSION 0)
|
SET(RTABMAP_MAJOR_VERSION 0)
|
||||||
SET(RTABMAP_MINOR_VERSION 23)
|
SET(RTABMAP_MINOR_VERSION 24)
|
||||||
SET(RTABMAP_PATCH_VERSION 8)
|
SET(RTABMAP_PATCH_VERSION 0)
|
||||||
SET(RTABMAP_VERSION
|
SET(RTABMAP_VERSION
|
||||||
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
|
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ public:
|
|||||||
const std::string & getUrl() const {return _url;}
|
const std::string & getUrl() const {return _url;}
|
||||||
const std::string & getTargetVersion() const {return _targetVersion;}
|
const std::string & getTargetVersion() const {return _targetVersion;}
|
||||||
|
|
||||||
|
// Start recording changes made to the database until it is closed, then write a compact
|
||||||
|
// delta of those changes to outputUrl (empty disables). Returns true if recording is
|
||||||
|
// active. Only the SQLite backend supports it (session extension + database version
|
||||||
|
// >= 0.24); other backends return false.
|
||||||
|
// NOTE: recorded changes are held in RAM until the database is closed, so only enable
|
||||||
|
// this when the expected set of changes is small.
|
||||||
|
virtual bool trackDatabaseChanges(const std::string & outputUrl) {(void)outputUrl; return false;}
|
||||||
|
|
||||||
void beginTransaction() const;
|
void beginTransaction() const;
|
||||||
void commit() const;
|
void commit() const;
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
typedef struct sqlite3_stmt sqlite3_stmt;
|
typedef struct sqlite3_stmt sqlite3_stmt;
|
||||||
typedef struct sqlite3 sqlite3;
|
typedef struct sqlite3 sqlite3;
|
||||||
|
typedef struct sqlite3_session sqlite3_session;
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
@@ -49,6 +50,26 @@ public:
|
|||||||
void setCacheSize(unsigned int cacheSize);
|
void setCacheSize(unsigned int cacheSize);
|
||||||
void setSynchronous(int synchronous);
|
void setSynchronous(int synchronous);
|
||||||
void setTempStore(int tempStore);
|
void setTempStore(int tempStore);
|
||||||
|
// Start recording changes made to the database from now until it is closed, then write
|
||||||
|
// a compact patchset delta to outputUrl (empty disables). Can be called before the
|
||||||
|
// connection is opened or on an already-open connection (e.g. after init(), so the
|
||||||
|
// baseline is the current content). Returns true if recording is active. Only effective
|
||||||
|
// if the build/runtime SQLite has the session extension and the database is version >= 0.24.
|
||||||
|
// NOTE: the SQLite session extension holds ALL recorded changes in RAM until the database
|
||||||
|
// is closed (there is no incremental spill to disk), so only enable this when the expected
|
||||||
|
// set of changes is small (e.g. appending a few sessions), not for rewriting a whole map.
|
||||||
|
virtual bool trackDatabaseChanges(const std::string & outputUrl);
|
||||||
|
|
||||||
|
// Apply a change delta previously written by setTrackChangesOutput() onto the database
|
||||||
|
// at databasePath (which must be the same database, at the same state, the delta was
|
||||||
|
// generated from). The file is decompressed (same codec as the other rtabmap blobs) then
|
||||||
|
// applied with the SQLite session extension. Returns true on success; on failure returns
|
||||||
|
// false and, if errorMsg is not null, sets a human-readable message. Requires a SQLite
|
||||||
|
// library built with the session extension (both at build and runtime).
|
||||||
|
static bool applyChangesFromFile(
|
||||||
|
const std::string & databasePath,
|
||||||
|
const std::string & patchsetPath,
|
||||||
|
std::string * errorMsg = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false);
|
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false);
|
||||||
@@ -197,6 +218,7 @@ private:
|
|||||||
void loadWordIdsQuery(std::list<Signature *> & signatures) const;
|
void loadWordIdsQuery(std::list<Signature *> & signatures) const;
|
||||||
void loadLinksQuery(std::list<Signature *> & signatures) const;
|
void loadLinksQuery(std::list<Signature *> & signatures) const;
|
||||||
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
|
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
|
||||||
|
void startChangeTracking(); // attach the change-tracking session on the open connection
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
sqlite3 * _ppDb;
|
sqlite3 * _ppDb;
|
||||||
@@ -209,6 +231,12 @@ private:
|
|||||||
int _journalMode;
|
int _journalMode;
|
||||||
int _synchronous;
|
int _synchronous;
|
||||||
int _tempStore;
|
int _tempStore;
|
||||||
|
|
||||||
|
// DB change tracking (SQLite session extension). Members are always present to keep
|
||||||
|
// the class layout stable regardless of RTABMAP_WITH_SQLITE3_SESSION; the session is
|
||||||
|
// only created/used when the feature is compiled in and enabled.
|
||||||
|
sqlite3_session * _session;
|
||||||
|
std::string _trackChangesOutput;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ public:
|
|||||||
int getDatabaseMemoryUsed() const; // in bytes
|
int getDatabaseMemoryUsed() const; // in bytes
|
||||||
std::string getDatabaseVersion() const;
|
std::string getDatabaseVersion() const;
|
||||||
std::string getDatabaseUrl() const;
|
std::string getDatabaseUrl() const;
|
||||||
|
// Record changes made to the database until it is closed, then write a compact delta
|
||||||
|
// to outputUrl (empty disables). Returns true if recording started. See DBDriver.
|
||||||
|
bool trackDatabaseChanges(const std::string & outputUrl);
|
||||||
double getDbSavingTime() const;
|
double getDbSavingTime() const;
|
||||||
int getMapId(int id, bool lookInDatabase = false) const;
|
int getMapId(int id, bool lookInDatabase = false) const;
|
||||||
Transform getOdomPose(int signatureId, bool lookInDatabase = false) const;
|
Transform getOdomPose(int signatureId, bool lookInDatabase = false) const;
|
||||||
|
|||||||
@@ -146,6 +146,13 @@ public:
|
|||||||
Transform getPose(int locationId) const;
|
Transform getPose(int locationId) const;
|
||||||
Transform getMapCorrection() const {return _mapCorrection;}
|
Transform getMapCorrection() const {return _mapCorrection;}
|
||||||
const Memory * getMemory() const {return _memory;}
|
const Memory * getMemory() const {return _memory;}
|
||||||
|
// Record changes made to the working database from now until it is closed, then write a
|
||||||
|
// compact delta to outputUrl (empty disables). Call after init(), so the delta reflects
|
||||||
|
// only what is added/modified afterwards. Returns true if recording started (requires the
|
||||||
|
// SQLite session extension and a database version >= 0.24). See DBDriver.
|
||||||
|
// NOTE: recorded changes are held in RAM until the database is closed, so only enable this
|
||||||
|
// when the expected set of changes is small (e.g. appending a few sessions).
|
||||||
|
bool trackDatabaseChanges(const std::string & outputUrl);
|
||||||
float getGoalReachedRadius() const {return _goalReachedRadius;}
|
float getGoalReachedRadius() const {return _goalReachedRadius;}
|
||||||
float getLocalRadius() const {return _localRadius;}
|
float getLocalRadius() const {return _localRadius;}
|
||||||
const Transform & getLastLocalizationPose() const {return _lastLocalizationPose;}
|
const Transform & getLastLocalizationPose() const {return _lastLocalizationPose;}
|
||||||
|
|||||||
@@ -196,6 +196,16 @@ IF(SQLite3_FOUND)
|
|||||||
${LIBRARIES}
|
${LIBRARIES}
|
||||||
${SQLite3_LIBRARIES}
|
${SQLite3_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
# The SQLite session extension (used to track DB diffs) needs SQLite >= 3.13.0.
|
||||||
|
# Defining SQLITE_ENABLE_SESSION here only exposes the session declarations in the
|
||||||
|
# system sqlite3.h; whether the linked library was actually built with the extension
|
||||||
|
# is verified at runtime with sqlite3_compileoption_used("ENABLE_SESSION").
|
||||||
|
IF(SQLite3_VERSION VERSION_GREATER_EQUAL "3.13.0")
|
||||||
|
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
|
||||||
|
MESSAGE(STATUS " With SQLite3 session ext = YES (system SQLite3 ${SQLite3_VERSION}, verified at runtime)")
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS " With SQLite3 session ext = NO (system SQLite3 ${SQLite3_VERSION} < 3.13.0)")
|
||||||
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
${SRC_FILES}
|
${SRC_FILES}
|
||||||
@@ -205,6 +215,9 @@ ELSE()
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/sqlite3
|
${CMAKE_CURRENT_SOURCE_DIR}/sqlite3
|
||||||
${INCLUDE_DIRS}
|
${INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
# We compile the bundled amalgamation ourselves, so enable the session extension in it.
|
||||||
|
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
|
||||||
|
MESSAGE(STATUS " With SQLite3 session ext = YES (bundled SQLite3)")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(TORCH_FOUND)
|
IF(TORCH_FOUND)
|
||||||
@@ -830,6 +843,7 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql.in ${CMA
|
|||||||
|
|
||||||
SET(RESOURCES
|
SET(RESOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_23_0.sql
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_22_0.sql
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_22_0.sql
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql
|
||||||
@@ -893,6 +907,13 @@ TARGET_LINK_LIBRARIES(rtabmap_core
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
${LIBRARIES})
|
${LIBRARIES})
|
||||||
|
|
||||||
|
# Enable the SQLite session extension for the core sources (bundled sqlite3.c and
|
||||||
|
# DBDriverSqlite3.cpp). Kept PRIVATE so it only affects rtabmap_core's own TUs and
|
||||||
|
# never changes the public header layout for downstream consumers.
|
||||||
|
IF(SQLITE3_SESSION_DEFINITIONS)
|
||||||
|
target_compile_definitions(rtabmap_core PRIVATE ${SQLITE3_SESSION_DEFINITIONS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(
|
SET_TARGET_PROPERTIES(
|
||||||
rtabmap_core
|
rtabmap_core
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/util3d.h"
|
#include "rtabmap/core/util3d.h"
|
||||||
#include "rtabmap/core/Compression.h"
|
#include "rtabmap/core/Compression.h"
|
||||||
#include "DatabaseSchema_sql.h"
|
#include "DatabaseSchema_sql.h"
|
||||||
|
#include "DatabaseSchema_0_23_0_sql.h"
|
||||||
#include "DatabaseSchema_0_22_0_sql.h"
|
#include "DatabaseSchema_0_22_0_sql.h"
|
||||||
#include "DatabaseSchema_0_20_0_sql.h"
|
#include "DatabaseSchema_0_20_0_sql.h"
|
||||||
#include "DatabaseSchema_0_18_3_sql.h"
|
#include "DatabaseSchema_0_18_3_sql.h"
|
||||||
@@ -45,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "rtabmap/utilite/UtiLite.h"
|
#include "rtabmap/utilite/UtiLite.h"
|
||||||
|
|
||||||
@@ -59,7 +61,8 @@ DBDriverSqlite3::DBDriverSqlite3(const ParametersMap & parameters) :
|
|||||||
_cacheSize(Parameters::defaultDbSqlite3CacheSize()),
|
_cacheSize(Parameters::defaultDbSqlite3CacheSize()),
|
||||||
_journalMode(Parameters::defaultDbSqlite3JournalMode()),
|
_journalMode(Parameters::defaultDbSqlite3JournalMode()),
|
||||||
_synchronous(Parameters::defaultDbSqlite3Synchronous()),
|
_synchronous(Parameters::defaultDbSqlite3Synchronous()),
|
||||||
_tempStore(Parameters::defaultDbSqlite3TempStore())
|
_tempStore(Parameters::defaultDbSqlite3TempStore()),
|
||||||
|
_session(0)
|
||||||
{
|
{
|
||||||
ULOGGER_DEBUG("treadSafe=%d", sqlite3_threadsafe());
|
ULOGGER_DEBUG("treadSafe=%d", sqlite3_threadsafe());
|
||||||
this->parseParameters(parameters);
|
this->parseParameters(parameters);
|
||||||
@@ -218,6 +221,149 @@ void DBDriverSqlite3::setDbInMemory(bool dbInMemory)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DBDriverSqlite3::startChangeTracking()
|
||||||
|
{
|
||||||
|
#ifdef RTABMAP_WITH_SQLITE3_SESSION
|
||||||
|
if(_session != 0 || _trackChangesOutput.empty() || _ppDb == 0)
|
||||||
|
{
|
||||||
|
// Already tracking, nothing requested, or not connected yet.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(uStrNumCmp(_version, "0.24.0") < 0)
|
||||||
|
{
|
||||||
|
UWARN("Database change tracking to \"%s\" was requested but the database "
|
||||||
|
"version is %s (< 0.24.0). Older schemas lack the primary keys required "
|
||||||
|
"by the SQLite session extension, so change tracking is disabled.",
|
||||||
|
_trackChangesOutput.c_str(), _version.c_str());
|
||||||
|
}
|
||||||
|
else if(!sqlite3_compileoption_used("ENABLE_SESSION"))
|
||||||
|
{
|
||||||
|
UWARN("Database change tracking to \"%s\" was requested but the linked SQLite "
|
||||||
|
"library was not built with the session extension (ENABLE_SESSION); "
|
||||||
|
"change tracking is disabled.", _trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
else if(sqlite3session_create(_ppDb, "main", &_session) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
sqlite3session_attach(_session, 0); // 0 = track all tables
|
||||||
|
UINFO("Tracking database changes; a patchset will be written to \"%s\" on close.",
|
||||||
|
_trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UWARN("Could not create a SQLite session to track database changes to \"%s\".",
|
||||||
|
_trackChangesOutput.c_str());
|
||||||
|
_session = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DBDriverSqlite3::trackDatabaseChanges(const std::string & outputUrl)
|
||||||
|
{
|
||||||
|
UDEBUG("outputUrl=%s", outputUrl.c_str());
|
||||||
|
_trackChangesOutput = outputUrl;
|
||||||
|
#ifdef RTABMAP_WITH_SQLITE3_SESSION
|
||||||
|
// If the connection is already open (e.g. set after connect(), as rtabmap-reprocess
|
||||||
|
// does after init()), start tracking now on the current baseline state. Otherwise it
|
||||||
|
// will start automatically when the connection is opened.
|
||||||
|
if(!outputUrl.empty() && _ppDb != 0)
|
||||||
|
{
|
||||||
|
this->startChangeTracking();
|
||||||
|
}
|
||||||
|
return _session != 0;
|
||||||
|
#else
|
||||||
|
if(!outputUrl.empty())
|
||||||
|
{
|
||||||
|
UWARN("Database change tracking to \"%s\" was requested but rtabmap was built "
|
||||||
|
"against a SQLite library without the session extension; it is disabled.",
|
||||||
|
outputUrl.c_str());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RTABMAP_WITH_SQLITE3_SESSION
|
||||||
|
static int rtabmapChangesetConflict(void * pCtx, int eConflict, sqlite3_changeset_iter * pIter)
|
||||||
|
{
|
||||||
|
// A patchset upgrade must apply cleanly onto the exact database it was generated from.
|
||||||
|
// Any conflict means the wrong base database (or an already-applied delta), so abort
|
||||||
|
// rather than silently produce an inconsistent result.
|
||||||
|
return SQLITE_CHANGESET_ABORT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool DBDriverSqlite3::applyChangesFromFile(
|
||||||
|
const std::string & databasePath,
|
||||||
|
const std::string & patchsetPath,
|
||||||
|
std::string * errorMsg)
|
||||||
|
{
|
||||||
|
#ifdef RTABMAP_WITH_SQLITE3_SESSION
|
||||||
|
if(!sqlite3_compileoption_used("ENABLE_SESSION"))
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = "The linked SQLite library was not built with the session extension.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the compressed patchset file.
|
||||||
|
FILE * fp = fopen(patchsetPath.c_str(), "rb");
|
||||||
|
if(!fp)
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Could not open patchset file \"%s\".", patchsetPath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long fileSize = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
if(fileSize <= 0)
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Patchset file \"%s\" is empty or unreadable.", patchsetPath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> fileBytes((size_t)fileSize);
|
||||||
|
size_t bytesRead = fread(fileBytes.data(), 1, (size_t)fileSize, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if((long)bytesRead != fileSize)
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Could not read patchset file \"%s\".", patchsetPath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompress to the raw patchset (same codec used to write it).
|
||||||
|
cv::Mat patch = uncompressData(fileBytes.data(), (unsigned long)fileSize);
|
||||||
|
if(patch.empty())
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Could not decompress patchset file \"%s\".", patchsetPath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply onto the target database.
|
||||||
|
sqlite3 * db = 0;
|
||||||
|
int rc = sqlite3_open_v2(databasePath.c_str(), &db, SQLITE_OPEN_READWRITE, 0);
|
||||||
|
if(rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Could not open database \"%s\": %s", databasePath.c_str(), sqlite3_errmsg(db));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nPatch = (int)(patch.total()*patch.elemSize());
|
||||||
|
rc = sqlite3changeset_apply(db, nPatch, patch.data, 0, rtabmapChangesetConflict, 0);
|
||||||
|
if(rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
if(errorMsg) *errorMsg = uFormat("Failed to apply patchset to \"%s\" (SQLite error %d: %s). Make "
|
||||||
|
"sure it is applied to the exact database state the delta was generated from.",
|
||||||
|
databasePath.c_str(), rc, sqlite3_errstr(rc));
|
||||||
|
sqlite3_close(db);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sqlite3_close(db);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if(errorMsg) *errorMsg = "rtabmap was built without SQLite session support.";
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is used to load the contents of a database file on disk
|
** This function is used to load the contents of a database file on disk
|
||||||
** into the "main" database of open database connection pInMemory, or
|
** into the "main" database of open database connection pInMemory, or
|
||||||
@@ -406,6 +552,7 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
|
|||||||
schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL));
|
schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL));
|
||||||
schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL));
|
schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL));
|
||||||
schemas.push_back(std::make_pair("0.22.0", DATABASESCHEMA_0_22_0_SQL));
|
schemas.push_back(std::make_pair("0.22.0", DATABASESCHEMA_0_22_0_SQL));
|
||||||
|
schemas.push_back(std::make_pair("0.23.0", DATABASESCHEMA_0_23_0_SQL));
|
||||||
schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL));
|
schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL));
|
||||||
for(size_t i=0; i<schemas.size(); ++i)
|
for(size_t i=0; i<schemas.size(); ++i)
|
||||||
{
|
{
|
||||||
@@ -446,6 +593,14 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
|
|||||||
this->setSynchronous(_synchronous); // this will call the SQL
|
this->setSynchronous(_synchronous); // this will call the SQL
|
||||||
this->setTempStore(_tempStore); // this will call the SQL
|
this->setTempStore(_tempStore); // this will call the SQL
|
||||||
|
|
||||||
|
// Start tracking database changes if a recording path was already set (before the
|
||||||
|
// connection was opened). Done here, after any initial load and once the version is
|
||||||
|
// known, so the delta reflects only the changes made between open and close.
|
||||||
|
if(!readOnly)
|
||||||
|
{
|
||||||
|
this->startChangeTracking();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & outputUrl)
|
void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & outputUrl)
|
||||||
@@ -489,6 +644,56 @@ void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & out
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RTABMAP_WITH_SQLITE3_SESSION
|
||||||
|
// If change tracking is active, emit the accumulated patchset before closing.
|
||||||
|
if(_session)
|
||||||
|
{
|
||||||
|
int nBuf = 0;
|
||||||
|
void * pBuf = 0;
|
||||||
|
int rcp = sqlite3session_patchset(_session, &nBuf, &pBuf);
|
||||||
|
if(rcp == SQLITE_OK && pBuf && nBuf > 0)
|
||||||
|
{
|
||||||
|
// Compress the patchset with the same zlib-based codec used for every other
|
||||||
|
// rtabmap blob, so the delta is compact for transfer. To apply it later,
|
||||||
|
// uncompressData() the file and pass the bytes to sqlite3changeset_apply().
|
||||||
|
cv::Mat compressed = compressData2(cv::Mat(1, nBuf, CV_8UC1, pBuf));
|
||||||
|
FILE * fp = fopen(_trackChangesOutput.c_str(), "wb");
|
||||||
|
if(fp)
|
||||||
|
{
|
||||||
|
size_t toWrite = compressed.total()*compressed.elemSize();
|
||||||
|
size_t written = fwrite(compressed.data, 1, toWrite, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if(written == toWrite)
|
||||||
|
{
|
||||||
|
UINFO("Wrote compressed database patchset (%d -> %d bytes) to \"%s\".",
|
||||||
|
nBuf, (int)toWrite, _trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Could only write %d/%d bytes of the database patchset to \"%s\".",
|
||||||
|
(int)written, (int)toWrite, _trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Could not open \"%s\" to write the database patchset.", _trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(rcp != SQLITE_OK)
|
||||||
|
{
|
||||||
|
UERROR("Could not generate the database patchset for \"%s\" (SQLite error %d).",
|
||||||
|
_trackChangesOutput.c_str(), rcp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINFO("No database changes to write; \"%s\" was not created.", _trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
sqlite3_free(pBuf);
|
||||||
|
sqlite3session_delete(_session);
|
||||||
|
_session = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Then close (delete) the database connection
|
// Then close (delete) the database connection
|
||||||
UINFO("Disconnecting database %s...", this->getUrl().c_str());
|
UINFO("Disconnecting database %s...", this->getUrl().c_str());
|
||||||
sqlite3_close(_ppDb);
|
sqlite3_close(_ppDb);
|
||||||
|
|||||||
@@ -1994,6 +1994,11 @@ double Memory::getDbSavingTime() const
|
|||||||
return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
|
return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Memory::trackDatabaseChanges(const std::string & outputUrl)
|
||||||
|
{
|
||||||
|
return _dbDriver?_dbDriver->trackDatabaseChanges(outputUrl):false;
|
||||||
|
}
|
||||||
|
|
||||||
std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const
|
std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const
|
||||||
{
|
{
|
||||||
std::set<int> ids;
|
std::set<int> ids;
|
||||||
|
|||||||
@@ -885,6 +885,11 @@ Transform Rtabmap::getPose(int locationId) const
|
|||||||
return uValue(_optimizedPoses, locationId, Transform());
|
return uValue(_optimizedPoses, locationId, Transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Rtabmap::trackDatabaseChanges(const std::string & outputUrl)
|
||||||
|
{
|
||||||
|
return _memory?_memory->trackDatabaseChanges(outputUrl):false;
|
||||||
|
}
|
||||||
|
|
||||||
void Rtabmap::setInitialPose(const Transform & initialPose)
|
void Rtabmap::setInitialPose(const Transform & initialPose)
|
||||||
{
|
{
|
||||||
if(_memory)
|
if(_memory)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ CREATE TABLE Data (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE Link (
|
CREATE TABLE Link (
|
||||||
|
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking); (from_id,to_id) is not unique (a node pair can have several links)
|
||||||
from_id INTEGER NOT NULL,
|
from_id INTEGER NOT NULL,
|
||||||
to_id INTEGER NOT NULL,
|
to_id INTEGER NOT NULL,
|
||||||
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
|
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
|
||||||
@@ -72,6 +73,7 @@ CREATE TABLE Word (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE Feature (
|
CREATE TABLE Feature (
|
||||||
|
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
|
||||||
node_id INTEGER NOT NULL,
|
node_id INTEGER NOT NULL,
|
||||||
word_id INTEGER NOT NULL,
|
word_id INTEGER NOT NULL,
|
||||||
pos_x FLOAT NOT NULL,
|
pos_x FLOAT NOT NULL,
|
||||||
@@ -89,6 +91,7 @@ CREATE TABLE Feature (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE GlobalDescriptor (
|
CREATE TABLE GlobalDescriptor (
|
||||||
|
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
|
||||||
node_id INTEGER NOT NULL,
|
node_id INTEGER NOT NULL,
|
||||||
type INTEGER NOT NULL,
|
type INTEGER NOT NULL,
|
||||||
info BLOB,
|
info BLOB,
|
||||||
@@ -99,6 +102,7 @@ CREATE TABLE GlobalDescriptor (
|
|||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE Info (
|
CREATE TABLE Info (
|
||||||
|
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
|
||||||
STM_size INTEGER,
|
STM_size INTEGER,
|
||||||
last_sign_added INTEGER,
|
last_sign_added INTEGER,
|
||||||
process_mem_used INTEGER,
|
process_mem_used INTEGER,
|
||||||
@@ -113,11 +117,12 @@ CREATE TABLE Statistics (
|
|||||||
stamp FLOAT,
|
stamp FLOAT,
|
||||||
data BLOB, -- compressed string
|
data BLOB, -- compressed string
|
||||||
wm_state BLOB, -- compressed data
|
wm_state BLOB, -- compressed data
|
||||||
|
PRIMARY KEY (id),
|
||||||
FOREIGN KEY (id) REFERENCES Node(id)
|
FOREIGN KEY (id) REFERENCES Node(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE Admin (
|
CREATE TABLE Admin (
|
||||||
version TEXT,
|
version TEXT PRIMARY KEY,
|
||||||
preview_image BLOB, -- compressed image
|
preview_image BLOB, -- compressed image
|
||||||
|
|
||||||
opt_cloud BLOB, -- compressed data
|
opt_cloud BLOB, -- compressed data
|
||||||
@@ -176,7 +181,6 @@ CREATE INDEX IDX_Feature_node_id on Feature (node_id);
|
|||||||
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
|
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
|
||||||
CREATE INDEX IDX_Link_from_id on Link (from_id);
|
CREATE INDEX IDX_Link_from_id on Link (from_id);
|
||||||
CREATE UNIQUE INDEX IDX_node_label on Node (label);
|
CREATE UNIQUE INDEX IDX_node_label on Node (label);
|
||||||
CREATE UNIQUE INDEX IDX_Statistics_id on Statistics (id);
|
|
||||||
|
|
||||||
-- *******************************************************************
|
-- *******************************************************************
|
||||||
-- VERSION
|
-- VERSION
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
-- *******************************************************************
|
||||||
|
-- DatabaseSchema: Script for creating the database
|
||||||
|
-- Usage:
|
||||||
|
-- $ sqlite3 LTM.db < DatabaseSchema.sql
|
||||||
|
--
|
||||||
|
-- *******************************************************************
|
||||||
|
|
||||||
|
-- *******************************************************************
|
||||||
|
-- CLEAN
|
||||||
|
-- *******************************************************************
|
||||||
|
/*DROP TABLE Node;*/
|
||||||
|
|
||||||
|
-- *******************************************************************
|
||||||
|
-- CREATE
|
||||||
|
-- *******************************************************************
|
||||||
|
CREATE TABLE Node (
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
map_id INTEGER NOT NULL,
|
||||||
|
weight INTEGER,
|
||||||
|
stamp FLOAT,
|
||||||
|
pose BLOB, -- 3x4 float
|
||||||
|
ground_truth_pose BLOB, -- 3x4 float
|
||||||
|
velocity BLOB, -- 6 float (vx,vy,vz,vroll,vpitch,vyaw) m/s and rad/s
|
||||||
|
label TEXT,
|
||||||
|
gps BLOB, -- 1x6 double: stamp, longitude (DD), latitude (DD), altitude (m), accuracy (m), bearing (North 0->360 deg clockwise)
|
||||||
|
env_sensors BLOB, -- Variable 3xdouble: (sensorId1, value, stamp, sensorId2, value, stamp, ...)
|
||||||
|
time_enter DATE,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Data (
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
image BLOB, -- compressed image (Grayscale or RGB)
|
||||||
|
depth BLOB, -- compressed image (Depth or Right image)
|
||||||
|
depth_confidence BLOB, -- compressed data (low=0 high=100)
|
||||||
|
calibration BLOB, -- fx, fy, cx, cy, [baseline,] width, height, local_transform
|
||||||
|
|
||||||
|
scan BLOB, -- compressed data (Laser scan)
|
||||||
|
scan_info BLOB, -- scan_max_pts, scan_max_range, scan_format, local_transform
|
||||||
|
|
||||||
|
ground_cells BLOB, -- compressed data (occupancy grid)
|
||||||
|
obstacle_cells BLOB, -- compressed data (occupancy grid)
|
||||||
|
empty_cells BLOB, -- compressed data (occupancy grid)
|
||||||
|
cell_size FLOAT,
|
||||||
|
view_point_x FLOAT,
|
||||||
|
view_point_y FLOAT,
|
||||||
|
view_point_z FLOAT,
|
||||||
|
|
||||||
|
user_data BLOB, -- compressed data (User data)
|
||||||
|
time_enter DATE,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Link (
|
||||||
|
from_id INTEGER NOT NULL,
|
||||||
|
to_id INTEGER NOT NULL,
|
||||||
|
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
|
||||||
|
information_matrix BLOB NOT NULL, -- 6x6 double (inverse covariance)
|
||||||
|
transform BLOB, -- 3x4 float
|
||||||
|
user_data BLOB, -- compressed data (User data)
|
||||||
|
FOREIGN KEY (from_id) REFERENCES Node(id),
|
||||||
|
FOREIGN KEY (to_id) REFERENCES Node(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
--
|
||||||
|
CREATE TABLE Word (
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
descriptor_size INTEGER NOT NULL,
|
||||||
|
descriptor BLOB NOT NULL,
|
||||||
|
time_enter DATE,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Feature (
|
||||||
|
node_id INTEGER NOT NULL,
|
||||||
|
word_id INTEGER NOT NULL,
|
||||||
|
pos_x FLOAT NOT NULL,
|
||||||
|
pos_y FLOAT NOT NULL,
|
||||||
|
size INTEGER NOT NULL,
|
||||||
|
dir FLOAT NOT NULL,
|
||||||
|
response FLOAT NOT NULL,
|
||||||
|
octave INTEGER NOT NULL,
|
||||||
|
depth_x FLOAT,
|
||||||
|
depth_y FLOAT,
|
||||||
|
depth_z FLOAT,
|
||||||
|
descriptor_size INTEGER,
|
||||||
|
descriptor BLOB,
|
||||||
|
FOREIGN KEY (node_id) REFERENCES Node(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE GlobalDescriptor (
|
||||||
|
node_id INTEGER NOT NULL,
|
||||||
|
type INTEGER NOT NULL,
|
||||||
|
info BLOB,
|
||||||
|
data BLOB NOT NULL,
|
||||||
|
FOREIGN KEY (node_id) REFERENCES Node(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE Info (
|
||||||
|
STM_size INTEGER,
|
||||||
|
last_sign_added INTEGER,
|
||||||
|
process_mem_used INTEGER,
|
||||||
|
database_mem_used INTEGER,
|
||||||
|
dictionary_size INTEGER,
|
||||||
|
parameters TEXT,
|
||||||
|
time_enter DATE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Statistics (
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
stamp FLOAT,
|
||||||
|
data BLOB, -- compressed string
|
||||||
|
wm_state BLOB, -- compressed data
|
||||||
|
FOREIGN KEY (id) REFERENCES Node(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Admin (
|
||||||
|
version TEXT,
|
||||||
|
preview_image BLOB, -- compressed image
|
||||||
|
|
||||||
|
opt_cloud BLOB, -- compressed data
|
||||||
|
opt_ids BLOB, -- Node ids used to generate the optimized cloud/mesh
|
||||||
|
opt_poses BLOB, -- compressed N*3x4 float
|
||||||
|
opt_last_localization BLOB, -- 3x4 float
|
||||||
|
opt_polygons_size INTEGER, -- e.g., 3
|
||||||
|
opt_polygons BLOB, -- compressed data [length_v0, i0,i1,i3, length_v1, i0,i1,i3]
|
||||||
|
opt_tex_coords BLOB, -- compressed data [length_v0, u0,v0,u1,v1,u2,v2, length_v1, u0,v0,u1,v1,u2,v2]
|
||||||
|
opt_tex_materials BLOB, -- compressed image
|
||||||
|
opt_map BLOB, -- compressed CV_8SC1 occupancy grid
|
||||||
|
opt_map_x_min FLOAT,
|
||||||
|
opt_map_y_min FLOAT,
|
||||||
|
opt_map_resolution FLOAT,
|
||||||
|
|
||||||
|
dictionary_index BLOB, -- serialized dictionary index
|
||||||
|
|
||||||
|
time_enter DATE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- *******************************************************************
|
||||||
|
-- TRIGGERS
|
||||||
|
-- *******************************************************************
|
||||||
|
CREATE TRIGGER insert_Feature BEFORE INSERT ON Feature
|
||||||
|
WHEN NOT EXISTS (SELECT Node.id FROM Node WHERE Node.id = NEW.node_id)
|
||||||
|
BEGIN
|
||||||
|
SELECT RAISE(ABORT, 'Foreign key constraint failed in Feature table');
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- Creating a trigger for time_enter
|
||||||
|
CREATE TRIGGER insert_Node_timeEnter AFTER INSERT ON Node
|
||||||
|
BEGIN
|
||||||
|
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER insert_Data_timeEnter AFTER INSERT ON Data
|
||||||
|
BEGIN
|
||||||
|
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER insert_Word_timeEnter AFTER INSERT ON Word
|
||||||
|
BEGIN
|
||||||
|
UPDATE Word SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER insert_Info_timeEnter AFTER INSERT ON Info
|
||||||
|
BEGIN
|
||||||
|
UPDATE Info SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- *******************************************************************
|
||||||
|
-- INDEXES
|
||||||
|
-- *******************************************************************
|
||||||
|
CREATE UNIQUE INDEX IDX_Node_id on Node (id);
|
||||||
|
CREATE INDEX IDX_Feature_node_id on Feature (node_id);
|
||||||
|
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
|
||||||
|
CREATE INDEX IDX_Link_from_id on Link (from_id);
|
||||||
|
CREATE UNIQUE INDEX IDX_node_label on Node (label);
|
||||||
|
CREATE UNIQUE INDEX IDX_Statistics_id on Statistics (id);
|
||||||
|
|
||||||
|
-- *******************************************************************
|
||||||
|
-- VERSION
|
||||||
|
-- *******************************************************************
|
||||||
|
INSERT INTO Admin(version) VALUES('0.23.0');
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
|
Version 3.53.3
|
||||||
Info: https://www.sqlite.org/
|
Info: https://www.sqlite.org/
|
||||||
License: Public domain (https://www.sqlite.org/copyright.html)
|
License: Public domain (https://www.sqlite.org/copyright.html)
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,12 +15,10 @@
|
|||||||
** as extensions by SQLite should #include this file instead of
|
** as extensions by SQLite should #include this file instead of
|
||||||
** sqlite3.h.
|
** sqlite3.h.
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE3EXT_H_
|
#ifndef SQLITE3EXT_H
|
||||||
#define _SQLITE3EXT_H_
|
#define SQLITE3EXT_H
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
|
|
||||||
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following structure holds pointers to all of the SQLite API
|
** The following structure holds pointers to all of the SQLite API
|
||||||
** routines.
|
** routines.
|
||||||
@@ -28,7 +26,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
|
|||||||
** WARNING: In order to maintain backwards compatibility, add new
|
** WARNING: In order to maintain backwards compatibility, add new
|
||||||
** interfaces to the end of this structure only. If you insert new
|
** interfaces to the end of this structure only. If you insert new
|
||||||
** interfaces in the middle of this structure, then older different
|
** interfaces in the middle of this structure, then older different
|
||||||
** versions of SQLite will not be able to load each others' shared
|
** versions of SQLite will not be able to load each other's shared
|
||||||
** libraries!
|
** libraries!
|
||||||
*/
|
*/
|
||||||
struct sqlite3_api_routines {
|
struct sqlite3_api_routines {
|
||||||
@@ -136,7 +134,7 @@ struct sqlite3_api_routines {
|
|||||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||||
const char*,const char*),void*);
|
const char*,const char*),void*);
|
||||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||||
char * (*snprintf)(int,char*,const char*,...);
|
char * (*xsnprintf)(int,char*,const char*,...);
|
||||||
int (*step)(sqlite3_stmt*);
|
int (*step)(sqlite3_stmt*);
|
||||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||||
char const**,char const**,int*,int*,int*);
|
char const**,char const**,int*,int*,int*);
|
||||||
@@ -248,13 +246,151 @@ struct sqlite3_api_routines {
|
|||||||
int (*uri_boolean)(const char*,const char*,int);
|
int (*uri_boolean)(const char*,const char*,int);
|
||||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||||
const char *(*uri_parameter)(const char*,const char*);
|
const char *(*uri_parameter)(const char*,const char*);
|
||||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
char *(*xvsnprintf)(int,char*,const char*,va_list);
|
||||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||||
|
/* Version 3.8.7 and later */
|
||||||
|
int (*auto_extension)(void(*)(void));
|
||||||
|
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
||||||
|
void(*)(void*));
|
||||||
|
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
||||||
|
void(*)(void*),unsigned char);
|
||||||
|
int (*cancel_auto_extension)(void(*)(void));
|
||||||
|
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
||||||
|
void *(*malloc64)(sqlite3_uint64);
|
||||||
|
sqlite3_uint64 (*msize)(void*);
|
||||||
|
void *(*realloc64)(void*,sqlite3_uint64);
|
||||||
|
void (*reset_auto_extension)(void);
|
||||||
|
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
||||||
|
void(*)(void*));
|
||||||
|
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||||
|
void(*)(void*), unsigned char);
|
||||||
|
int (*strglob)(const char*,const char*);
|
||||||
|
/* Version 3.8.11 and later */
|
||||||
|
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
||||||
|
void (*value_free)(sqlite3_value*);
|
||||||
|
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
||||||
|
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
||||||
|
/* Version 3.9.0 and later */
|
||||||
|
unsigned int (*value_subtype)(sqlite3_value*);
|
||||||
|
void (*result_subtype)(sqlite3_context*,unsigned int);
|
||||||
|
/* Version 3.10.0 and later */
|
||||||
|
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
||||||
|
int (*strlike)(const char*,const char*,unsigned int);
|
||||||
|
int (*db_cacheflush)(sqlite3*);
|
||||||
|
/* Version 3.12.0 and later */
|
||||||
|
int (*system_errno)(sqlite3*);
|
||||||
|
/* Version 3.14.0 and later */
|
||||||
|
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
||||||
|
char *(*expanded_sql)(sqlite3_stmt*);
|
||||||
|
/* Version 3.18.0 and later */
|
||||||
|
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
||||||
|
/* Version 3.20.0 and later */
|
||||||
|
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
|
||||||
|
sqlite3_stmt**,const char**);
|
||||||
|
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
|
||||||
|
sqlite3_stmt**,const void**);
|
||||||
|
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
||||||
|
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
||||||
|
void *(*value_pointer)(sqlite3_value*,const char*);
|
||||||
|
int (*vtab_nochange)(sqlite3_context*);
|
||||||
|
int (*value_nochange)(sqlite3_value*);
|
||||||
|
const char *(*vtab_collation)(sqlite3_index_info*,int);
|
||||||
|
/* Version 3.24.0 and later */
|
||||||
|
int (*keyword_count)(void);
|
||||||
|
int (*keyword_name)(int,const char**,int*);
|
||||||
|
int (*keyword_check)(const char*,int);
|
||||||
|
sqlite3_str *(*str_new)(sqlite3*);
|
||||||
|
char *(*str_finish)(sqlite3_str*);
|
||||||
|
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
|
||||||
|
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
|
||||||
|
void (*str_append)(sqlite3_str*, const char *zIn, int N);
|
||||||
|
void (*str_appendall)(sqlite3_str*, const char *zIn);
|
||||||
|
void (*str_appendchar)(sqlite3_str*, int N, char C);
|
||||||
|
void (*str_reset)(sqlite3_str*);
|
||||||
|
int (*str_errcode)(sqlite3_str*);
|
||||||
|
int (*str_length)(sqlite3_str*);
|
||||||
|
char *(*str_value)(sqlite3_str*);
|
||||||
|
/* Version 3.25.0 and later */
|
||||||
|
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*),
|
||||||
|
void (*xValue)(sqlite3_context*),
|
||||||
|
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void(*xDestroy)(void*));
|
||||||
|
/* Version 3.26.0 and later */
|
||||||
|
const char *(*normalized_sql)(sqlite3_stmt*);
|
||||||
|
/* Version 3.28.0 and later */
|
||||||
|
int (*stmt_isexplain)(sqlite3_stmt*);
|
||||||
|
int (*value_frombind)(sqlite3_value*);
|
||||||
|
/* Version 3.30.0 and later */
|
||||||
|
int (*drop_modules)(sqlite3*,const char**);
|
||||||
|
/* Version 3.31.0 and later */
|
||||||
|
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
||||||
|
const char *(*uri_key)(const char*,int);
|
||||||
|
const char *(*filename_database)(const char*);
|
||||||
|
const char *(*filename_journal)(const char*);
|
||||||
|
const char *(*filename_wal)(const char*);
|
||||||
|
/* Version 3.32.0 and later */
|
||||||
|
const char *(*create_filename)(const char*,const char*,const char*,
|
||||||
|
int,const char**);
|
||||||
|
void (*free_filename)(const char*);
|
||||||
|
sqlite3_file *(*database_file_object)(const char*);
|
||||||
|
/* Version 3.34.0 and later */
|
||||||
|
int (*txn_state)(sqlite3*,const char*);
|
||||||
|
/* Version 3.36.1 and later */
|
||||||
|
sqlite3_int64 (*changes64)(sqlite3*);
|
||||||
|
sqlite3_int64 (*total_changes64)(sqlite3*);
|
||||||
|
/* Version 3.37.0 and later */
|
||||||
|
int (*autovacuum_pages)(sqlite3*,
|
||||||
|
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||||
|
void*, void(*)(void*));
|
||||||
|
/* Version 3.38.0 and later */
|
||||||
|
int (*error_offset)(sqlite3*);
|
||||||
|
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
|
||||||
|
int (*vtab_distinct)(sqlite3_index_info*);
|
||||||
|
int (*vtab_in)(sqlite3_index_info*,int,int);
|
||||||
|
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
|
||||||
|
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
|
||||||
|
/* Version 3.39.0 and later */
|
||||||
|
int (*deserialize)(sqlite3*,const char*,unsigned char*,
|
||||||
|
sqlite3_int64,sqlite3_int64,unsigned);
|
||||||
|
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
|
||||||
|
unsigned int);
|
||||||
|
const char *(*db_name)(sqlite3*,int);
|
||||||
|
/* Version 3.40.0 and later */
|
||||||
|
int (*value_encoding)(sqlite3_value*);
|
||||||
|
/* Version 3.41.0 and later */
|
||||||
|
int (*is_interrupted)(sqlite3*);
|
||||||
|
/* Version 3.43.0 and later */
|
||||||
|
int (*stmt_explain)(sqlite3_stmt*,int);
|
||||||
|
/* Version 3.44.0 and later */
|
||||||
|
void *(*get_clientdata)(sqlite3*,const char*);
|
||||||
|
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
|
||||||
|
/* Version 3.50.0 and later */
|
||||||
|
int (*setlk_timeout)(sqlite3*,int,int);
|
||||||
|
/* Version 3.51.0 and later */
|
||||||
|
int (*set_errmsg)(sqlite3*,int,const char*);
|
||||||
|
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
|
||||||
|
/* Version 3.52.0 and later */
|
||||||
|
void (*str_truncate)(sqlite3_str*,int);
|
||||||
|
void (*str_free)(sqlite3_str*);
|
||||||
|
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
|
||||||
|
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This is the function signature used for all extension entry points. It
|
||||||
|
** is also defined in the file "loadext.c".
|
||||||
|
*/
|
||||||
|
typedef int (*sqlite3_loadext_entry)(
|
||||||
|
sqlite3 *db, /* Handle to the database. */
|
||||||
|
char **pzErrMsg, /* Used to set error string on failure. */
|
||||||
|
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following macros redefine the API routines so that they are
|
** The following macros redefine the API routines so that they are
|
||||||
** redirected throught the global sqlite3_api structure.
|
** redirected through the global sqlite3_api structure.
|
||||||
**
|
**
|
||||||
** This header file is also used by the loadext.c source file
|
** This header file is also used by the loadext.c source file
|
||||||
** (part of the main SQLite library - not an extension) so that
|
** (part of the main SQLite library - not an extension) so that
|
||||||
@@ -263,7 +399,7 @@ struct sqlite3_api_routines {
|
|||||||
** the API. So the redefinition macros are only valid if the
|
** the API. So the redefinition macros are only valid if the
|
||||||
** SQLITE_CORE macros is undefined.
|
** SQLITE_CORE macros is undefined.
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_CORE
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
#ifndef SQLITE_OMIT_DEPRECATED
|
||||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||||
@@ -366,7 +502,7 @@ struct sqlite3_api_routines {
|
|||||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||||
#define sqlite3_snprintf sqlite3_api->snprintf
|
#define sqlite3_snprintf sqlite3_api->xsnprintf
|
||||||
#define sqlite3_step sqlite3_api->step
|
#define sqlite3_step sqlite3_api->step
|
||||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||||
@@ -390,6 +526,7 @@ struct sqlite3_api_routines {
|
|||||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||||
#define sqlite3_value_type sqlite3_api->value_type
|
#define sqlite3_value_type sqlite3_api->value_type
|
||||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||||
|
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
|
||||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||||
@@ -465,11 +602,126 @@ struct sqlite3_api_routines {
|
|||||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
|
||||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||||
#endif /* SQLITE_CORE */
|
/* Version 3.8.7 and later */
|
||||||
|
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
||||||
|
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
||||||
|
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
||||||
|
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
||||||
|
#define sqlite3_load_extension sqlite3_api->load_extension
|
||||||
|
#define sqlite3_malloc64 sqlite3_api->malloc64
|
||||||
|
#define sqlite3_msize sqlite3_api->msize
|
||||||
|
#define sqlite3_realloc64 sqlite3_api->realloc64
|
||||||
|
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
||||||
|
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
||||||
|
#define sqlite3_result_text64 sqlite3_api->result_text64
|
||||||
|
#define sqlite3_strglob sqlite3_api->strglob
|
||||||
|
/* Version 3.8.11 and later */
|
||||||
|
#define sqlite3_value_dup sqlite3_api->value_dup
|
||||||
|
#define sqlite3_value_free sqlite3_api->value_free
|
||||||
|
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
||||||
|
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
||||||
|
/* Version 3.9.0 and later */
|
||||||
|
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||||
|
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||||
|
/* Version 3.10.0 and later */
|
||||||
|
#define sqlite3_status64 sqlite3_api->status64
|
||||||
|
#define sqlite3_strlike sqlite3_api->strlike
|
||||||
|
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
||||||
|
/* Version 3.12.0 and later */
|
||||||
|
#define sqlite3_system_errno sqlite3_api->system_errno
|
||||||
|
/* Version 3.14.0 and later */
|
||||||
|
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
||||||
|
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
||||||
|
/* Version 3.18.0 and later */
|
||||||
|
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
||||||
|
/* Version 3.20.0 and later */
|
||||||
|
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
||||||
|
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
||||||
|
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||||
|
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||||
|
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||||
|
/* Version 3.22.0 and later */
|
||||||
|
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
||||||
|
#define sqlite3_value_nochange sqlite3_api->value_nochange
|
||||||
|
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
|
||||||
|
/* Version 3.24.0 and later */
|
||||||
|
#define sqlite3_keyword_count sqlite3_api->keyword_count
|
||||||
|
#define sqlite3_keyword_name sqlite3_api->keyword_name
|
||||||
|
#define sqlite3_keyword_check sqlite3_api->keyword_check
|
||||||
|
#define sqlite3_str_new sqlite3_api->str_new
|
||||||
|
#define sqlite3_str_finish sqlite3_api->str_finish
|
||||||
|
#define sqlite3_str_appendf sqlite3_api->str_appendf
|
||||||
|
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
|
||||||
|
#define sqlite3_str_append sqlite3_api->str_append
|
||||||
|
#define sqlite3_str_appendall sqlite3_api->str_appendall
|
||||||
|
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
|
||||||
|
#define sqlite3_str_reset sqlite3_api->str_reset
|
||||||
|
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
||||||
|
#define sqlite3_str_length sqlite3_api->str_length
|
||||||
|
#define sqlite3_str_value sqlite3_api->str_value
|
||||||
|
/* Version 3.25.0 and later */
|
||||||
|
#define sqlite3_create_window_function sqlite3_api->create_window_function
|
||||||
|
/* Version 3.26.0 and later */
|
||||||
|
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
||||||
|
/* Version 3.28.0 and later */
|
||||||
|
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
||||||
|
#define sqlite3_value_frombind sqlite3_api->value_frombind
|
||||||
|
/* Version 3.30.0 and later */
|
||||||
|
#define sqlite3_drop_modules sqlite3_api->drop_modules
|
||||||
|
/* Version 3.31.0 and later */
|
||||||
|
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
||||||
|
#define sqlite3_uri_key sqlite3_api->uri_key
|
||||||
|
#define sqlite3_filename_database sqlite3_api->filename_database
|
||||||
|
#define sqlite3_filename_journal sqlite3_api->filename_journal
|
||||||
|
#define sqlite3_filename_wal sqlite3_api->filename_wal
|
||||||
|
/* Version 3.32.0 and later */
|
||||||
|
#define sqlite3_create_filename sqlite3_api->create_filename
|
||||||
|
#define sqlite3_free_filename sqlite3_api->free_filename
|
||||||
|
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
||||||
|
/* Version 3.34.0 and later */
|
||||||
|
#define sqlite3_txn_state sqlite3_api->txn_state
|
||||||
|
/* Version 3.36.1 and later */
|
||||||
|
#define sqlite3_changes64 sqlite3_api->changes64
|
||||||
|
#define sqlite3_total_changes64 sqlite3_api->total_changes64
|
||||||
|
/* Version 3.37.0 and later */
|
||||||
|
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
|
||||||
|
/* Version 3.38.0 and later */
|
||||||
|
#define sqlite3_error_offset sqlite3_api->error_offset
|
||||||
|
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
|
||||||
|
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
|
||||||
|
#define sqlite3_vtab_in sqlite3_api->vtab_in
|
||||||
|
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
|
||||||
|
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
|
||||||
|
/* Version 3.39.0 and later */
|
||||||
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||||
|
#define sqlite3_deserialize sqlite3_api->deserialize
|
||||||
|
#define sqlite3_serialize sqlite3_api->serialize
|
||||||
|
#endif
|
||||||
|
#define sqlite3_db_name sqlite3_api->db_name
|
||||||
|
/* Version 3.40.0 and later */
|
||||||
|
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
||||||
|
/* Version 3.41.0 and later */
|
||||||
|
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
||||||
|
/* Version 3.43.0 and later */
|
||||||
|
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
|
||||||
|
/* Version 3.44.0 and later */
|
||||||
|
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
|
||||||
|
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
|
||||||
|
/* Version 3.50.0 and later */
|
||||||
|
#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
|
||||||
|
/* Version 3.51.0 and later */
|
||||||
|
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
|
||||||
|
#define sqlite3_db_status64 sqlite3_api->db_status64
|
||||||
|
/* Version 3.52.0 and later */
|
||||||
|
#define sqlite3_str_truncate sqlite3_api->str_truncate
|
||||||
|
#define sqlite3_str_free sqlite3_api->str_free
|
||||||
|
#define sqlite3_carray_bind sqlite3_api->carray_bind
|
||||||
|
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
|
||||||
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||||
|
|
||||||
#ifndef SQLITE_CORE
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||||
/* This case when the file really is being compiled as a loadable
|
/* This case when the file really is being compiled as a loadable
|
||||||
** extension */
|
** extension */
|
||||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||||
@@ -484,4 +736,4 @@ struct sqlite3_api_routines {
|
|||||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _SQLITE3EXT_H_ */
|
#endif /* SQLITE3EXT_H */
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ ADD_SUBDIRECTORY( EurocDataset )
|
|||||||
ADD_SUBDIRECTORY( CidSimsDataset )
|
ADD_SUBDIRECTORY( CidSimsDataset )
|
||||||
ADD_SUBDIRECTORY( Recovery )
|
ADD_SUBDIRECTORY( Recovery )
|
||||||
ADD_SUBDIRECTORY( Reprocess )
|
ADD_SUBDIRECTORY( Reprocess )
|
||||||
|
ADD_SUBDIRECTORY( DatabaseUpdate )
|
||||||
ADD_SUBDIRECTORY( DetectMoreLoopClosures )
|
ADD_SUBDIRECTORY( DetectMoreLoopClosures )
|
||||||
ADD_SUBDIRECTORY( Export )
|
ADD_SUBDIRECTORY( Export )
|
||||||
ADD_SUBDIRECTORY( Report )
|
ADD_SUBDIRECTORY( Report )
|
||||||
|
|||||||
11
tools/DatabaseUpdate/CMakeLists.txt
Normal file
11
tools/DatabaseUpdate/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
ADD_EXECUTABLE(dbupdate main.cpp)
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(dbupdate rtabmap_core)
|
||||||
|
|
||||||
|
SET_TARGET_PROPERTIES( dbupdate
|
||||||
|
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-dbupdate)
|
||||||
|
|
||||||
|
INSTALL(TARGETS dbupdate
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
|
||||||
|
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
|
||||||
87
tools/DatabaseUpdate/main.cpp
Normal file
87
tools/DatabaseUpdate/main.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Universite de Sherbrooke nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtabmap/core/DBDriverSqlite3.h>
|
||||||
|
#include <rtabmap/utilite/ULogger.h>
|
||||||
|
#include <rtabmap/utilite/UFile.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace rtabmap;
|
||||||
|
|
||||||
|
void showUsage()
|
||||||
|
{
|
||||||
|
printf("\nUpdate a database with a set of changes recorded while another database was opened with\n"
|
||||||
|
"change tracking enabled (i.e. DBDriverSqlite3::setTrackChangesOutput()). This applies the\n"
|
||||||
|
"data changes only; it does NOT upgrade the database schema/version.\n"
|
||||||
|
"\n"
|
||||||
|
"Usage:\n"
|
||||||
|
" rtabmap-dbupdate \"database.db\" \"changes.update\"\n"
|
||||||
|
"\n"
|
||||||
|
"The changes must be applied to the exact database state they were recorded from; otherwise\n"
|
||||||
|
"the operation is aborted and the database is left unchanged.\n"
|
||||||
|
"\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
ULogger::setType(ULogger::kTypeConsole);
|
||||||
|
ULogger::setLevel(ULogger::kWarning);
|
||||||
|
|
||||||
|
if(argc < 3)
|
||||||
|
{
|
||||||
|
showUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string databasePath = argv[argc-2];
|
||||||
|
std::string updatePath = argv[argc-1];
|
||||||
|
|
||||||
|
if(!UFile::exists(databasePath))
|
||||||
|
{
|
||||||
|
printf("Database \"%s\" does not exist.\n", databasePath.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(!UFile::exists(updatePath))
|
||||||
|
{
|
||||||
|
printf("Update file \"%s\" does not exist.\n", updatePath.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Updating database \"%s\" with changes from \"%s\"...\n", databasePath.c_str(), updatePath.c_str());
|
||||||
|
|
||||||
|
std::string error;
|
||||||
|
if(DBDriverSqlite3::applyChangesFromFile(databasePath, updatePath, &error))
|
||||||
|
{
|
||||||
|
printf("Done! Database \"%s\" was updated successfully.\n", databasePath.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Error: %s\n", error.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -85,6 +85,11 @@ void showUsage()
|
|||||||
" -stop_loop Stop after the first loop closure is detected.\n"
|
" -stop_loop Stop after the first loop closure is detected.\n"
|
||||||
" -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n"
|
" -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n"
|
||||||
" then next databases are reprocessed on top of the first one.\n"
|
" then next databases are reprocessed on top of the first one.\n"
|
||||||
|
" --track-changes \"changes.update\"\n"
|
||||||
|
" Only with append mode (-a): record the changes made on top of the first (copied) database and\n"
|
||||||
|
" write a compact delta to the given file. Apply it later on the original database with\n"
|
||||||
|
" rtabmap-dbupdate. Requires the database to be version 0.24 or newer. Note: the recorded\n"
|
||||||
|
" changes are held in memory until closing, so use this only when appending a small amount.\n"
|
||||||
" -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data. Can also be multiple \n"
|
" -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data. Can also be multiple \n"
|
||||||
" indices split by spaces in a string like \"0 2\" to stream cameras 0 and 2 only.\n"
|
" indices split by spaces in a string like \"0 2\" to stream cameras 0 and 2 only.\n"
|
||||||
" -cam_tf \"x y z roll pitch yaw\" Camera local transform override(s) without optical rotation. For multi-cameras, \n"
|
" -cam_tf \"x y z roll pitch yaw\" Camera local transform override(s) without optical rotation. For multi-cameras, \n"
|
||||||
@@ -274,6 +279,7 @@ int main(int argc, char * argv[])
|
|||||||
int stopMapId = -1;
|
int stopMapId = -1;
|
||||||
bool stopOnLoopClosure = false;
|
bool stopOnLoopClosure = false;
|
||||||
bool appendMode = false;
|
bool appendMode = false;
|
||||||
|
std::string trackChangesOutput;
|
||||||
std::vector<unsigned int> cameraIndices;
|
std::vector<unsigned int> cameraIndices;
|
||||||
std::vector<Transform> cameraLocalTransformOverrides;
|
std::vector<Transform> cameraLocalTransformOverrides;
|
||||||
std::vector<float> cameraLocalTransformOffsetOverrides;
|
std::vector<float> cameraLocalTransformOffsetOverrides;
|
||||||
@@ -430,6 +436,20 @@ int main(int argc, char * argv[])
|
|||||||
appendMode = true;
|
appendMode = true;
|
||||||
printf("Append mode enabled (initialize with first database then reprocess next ones)\n");
|
printf("Append mode enabled (initialize with first database then reprocess next ones)\n");
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[i], "--track-changes") == 0)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
if(i < argc - 2)
|
||||||
|
{
|
||||||
|
trackChangesOutput = argv[i];
|
||||||
|
printf("Change tracking enabled, delta will be written to \"%s\" (apply later with rtabmap-dbupdate).\n", trackChangesOutput.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Missing value for --track-changes option!\n");
|
||||||
|
showUsage();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strcmp(argv[i], "-cam") == 0 || strcmp(argv[i], "--cam") == 0)
|
else if (strcmp(argv[i], "-cam") == 0 || strcmp(argv[i], "--cam") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
@@ -886,6 +906,22 @@ int main(int argc, char * argv[])
|
|||||||
Rtabmap rtabmap;
|
Rtabmap rtabmap;
|
||||||
rtabmap.init(parameters, outputDatabasePath);
|
rtabmap.init(parameters, outputDatabasePath);
|
||||||
|
|
||||||
|
// Start change tracking now, after init loaded the copied baseline database, so the
|
||||||
|
// delta captures only what reprocessing appends. Only meaningful in append mode, where
|
||||||
|
// the output starts as a copy of the first input database.
|
||||||
|
if(!trackChangesOutput.empty())
|
||||||
|
{
|
||||||
|
if(appendMode)
|
||||||
|
{
|
||||||
|
rtabmap.trackDatabaseChanges(trackChangesOutput);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Warning: --track-changes requires append mode (-a); it is ignored because "
|
||||||
|
"append mode is not enabled.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!incrementalMemory && locNull)
|
if(!incrementalMemory && locNull)
|
||||||
{
|
{
|
||||||
rtabmap.setInitialPose(Transform());
|
rtabmap.setInitialPose(Transform());
|
||||||
|
|||||||
Reference in New Issue
Block a user