Skip to content

Commit

Permalink
able to produce JSON output (#15)
Browse files Browse the repository at this point in the history
[feature] [api break] listChanges now produce JSON output

added new API:

GEODIFF_hasChanges
GEODIFF_changesCount
changed API for:

GEODIFF_listChanges (returns GEODIFF status, and produces JSON)
  • Loading branch information
PeterPetrik authored Sep 26, 2019
1 parent 9afc364 commit 7530eaf
Show file tree
Hide file tree
Showing 22 changed files with 888 additions and 194 deletions.
2 changes: 2 additions & 0 deletions geodiff/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ SET(geodiff_src
src/geodiffutils.hpp
src/geodiffrebase.cpp
src/geodiffrebase.hpp
src/geodiffexporter.cpp
src/geodiffexporter.hpp
${sqlite_src}
${libgpkg_src}
)
Expand Down
133 changes: 94 additions & 39 deletions geodiff/src/geodiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
#include "geodiff.h"
#include "geodiffutils.hpp"
#include "geodiffrebase.hpp"
#include "geodiffexporter.hpp"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>

#include <gpkg.h>
#include <sqlite3.h>

#include <fcntl.h>
Expand All @@ -23,7 +23,7 @@

const char *GEODIFF_version()
{
return "0.3.0";
return "0.4.0";
}

void _errorLogCallback( void *pArg, int iErrCode, const char *zMsg )
Expand Down Expand Up @@ -134,7 +134,7 @@ static int conflict_callback( void *ctx, int conflict, sqlite3_changeset_iter *i
{
nconflicts++;
std::string s = conflict2Str( conflict );
std::string vals = Sqlite3ChangesetIter::toString( iterator );
std::string vals = GeoDiffExporter::toString( iterator );
Logger::instance().warn( "CONFLICT: " + s + ": " + vals );
return SQLITE_CHANGESET_REPLACE;
}
Expand Down Expand Up @@ -173,19 +173,14 @@ int GEODIFF_applyChangeset( const char *base, const char *patched, const char *c
std::shared_ptr<Sqlite3Db> db = std::make_shared<Sqlite3Db>();
db->open( patched );

// register GPKG functions like ST_IsEmpty
int rc = sqlite3_enable_load_extension( db->get(), 1 );
if ( rc )
{
Logger::instance().error( "Unable to enable sqlite3 extensions" );
return GEODIFF_ERROR;
}

rc = sqlite3_gpkg_auto_init( db->get(), NULL, NULL );
if ( rc )
if ( isGeoPackage( db ) )
{
Logger::instance().error( "Unable to load gpkg sqlite3 extensions" );
return GEODIFF_ERROR;
bool success = register_gpkg_extensions( db );
if ( !success )
{
Logger::instance().error( "Unable to enable sqlite3/gpkg extensions" );
return GEODIFF_ERROR;
}
}

// get all triggers sql commands
Expand All @@ -203,7 +198,7 @@ int GEODIFF_applyChangeset( const char *base, const char *patched, const char *c
}

// apply changeset
rc = sqlite3changeset_apply( db->get(), cbuf.size(), cbuf.v_buf(), NULL, conflict_callback, NULL );
int rc = sqlite3changeset_apply( db->get(), cbuf.size(), cbuf.v_buf(), NULL, conflict_callback, NULL );
if ( rc )
{
Logger::instance().error( "Unable to perform sqlite3changeset_apply" );
Expand Down Expand Up @@ -233,26 +228,82 @@ int GEODIFF_applyChangeset( const char *base, const char *patched, const char *c
}
}

int GEODIFF_listChanges( const char *changeset )
int GEODIFF_createRebasedChangeset( const char *base, const char *modified, const char *changeset_their, const char *changeset )
{
try
{
// get all triggers sql commands
// and make sure that there are only triggers we recognize
// we deny rebase changesets with unrecognized triggers
std::shared_ptr<Sqlite3Db> db = std::make_shared<Sqlite3Db>();
db->open( modified );
std::vector<std::string> triggerNames;
std::vector<std::string> triggerCmds;
triggers( db, triggerNames, triggerCmds );
if ( !triggerNames.empty() )
{
Logger::instance().error( "Unable to perform rebase for database with unknown triggers" );
return GEODIFF_ERROR;
}

std::string changeset_BASE_MODIFIED = std::string( changeset ) + "_BASE_MODIFIED";
int rc = GEODIFF_createChangeset( base, modified, changeset_BASE_MODIFIED.c_str() );
if ( rc != GEODIFF_SUCCESS )
return rc;

return rebase( changeset_their, changeset, changeset_BASE_MODIFIED );
}
catch ( GeoDiffException exc )
{
Logger::instance().error( exc );
return GEODIFF_ERROR;
}
}

int GEODIFF_hasChanges( const char *changeset )
{
try
{
int nchanges = 0;
Buffer buf;
buf.read( changeset );
if ( buf.isEmpty() )
{
Logger::instance().info( "--- no changes ---" );
return 0;
}

Sqlite3ChangesetIter pp;
pp.start( buf );
while ( SQLITE_ROW == sqlite3changeset_next( pp.get() ) )
{
std::string msg = Sqlite3ChangesetIter::toString( pp.get() );
Logger::instance().info( msg );
nchanges = nchanges + 1 ;
// ok we have at least one change
return 1;
}
return 0; // no changes
}
catch ( GeoDiffException exc )
{
Logger::instance().error( exc );
return -1;
}
}

int GEODIFF_changesCount( const char *changeset )
{
try
{
int nchanges = 0;
Buffer buf;
buf.read( changeset );
if ( buf.isEmpty() )
{
return nchanges;
}

Sqlite3ChangesetIter pp;
pp.start( buf );
while ( SQLITE_ROW == sqlite3changeset_next( pp.get() ) )
{
++nchanges;
}
return nchanges;
}
Expand All @@ -263,30 +314,34 @@ int GEODIFF_listChanges( const char *changeset )
}
}

int GEODIFF_createRebasedChangeset( const char *base, const char *modified, const char *changeset_their, const char *changeset )
int GEODIFF_listChanges( const char *changeset, const char *jsonfile )
{
try
{
// get all triggers sql commands
// and make sure that there are only triggers we recognize
// we deny rebase changesets with unrecognized triggers
std::shared_ptr<Sqlite3Db> db = std::make_shared<Sqlite3Db>();
db->open( modified );
std::vector<std::string> triggerNames;
std::vector<std::string> triggerCmds;
triggers( db, triggerNames, triggerCmds );
if ( !triggerNames.empty() )
Buffer buf;
buf.read( changeset );
if ( buf.isEmpty() )
{
Logger::instance().error( "Unable to perform rebase for database with unknown triggers" );
return GEODIFF_ERROR;
return 0;
}

std::string changeset_BASE_MODIFIED = std::string( changeset ) + "_BASE_MODIFIED";
int rc = GEODIFF_createChangeset( base, modified, changeset_BASE_MODIFIED.c_str() );
if ( rc != GEODIFF_SUCCESS )
return rc;
std::shared_ptr<Sqlite3Db> db = std::make_shared<Sqlite3Db>();
db->open( ":memory:" );
std::string cmd = "CREATE TABLE gpkg_contents (table_name TEXT NOT NULL PRIMARY KEY,data_type TEXT NOT NULL,identifier TEXT UNIQUE,description TEXT DEFAULT '',last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),min_x DOUBLE, min_y DOUBLE,max_x DOUBLE, max_y DOUBLE,srs_id INTEGER)";
Sqlite3Stmt statament;
statament.prepare( db, "%s", cmd.c_str() );
sqlite3_step( statament.get() );
statament.close();

return rebase( changeset_their, changeset, changeset_BASE_MODIFIED );
bool success = register_gpkg_extensions( db );
if ( !success )
{
throw GeoDiffException( "Unable to enable sqlite3/gpkg extensions" );
}

std::string res = GeoDiffExporter::toJSON( db, buf );
flushString( jsonfile, res );
return GEODIFF_SUCCESS;
}
catch ( GeoDiffException exc )
{
Expand Down
36 changes: 29 additions & 7 deletions geodiff/src/geodiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ GEODIFF_EXPORT const char *GEODIFF_version();
* \param changeset [output] changeset between BASE -> MODIFIED
* \returns GEODIFF_SUCCESS on success
*/
GEODIFF_EXPORT int GEODIFF_createChangeset( const char *base, const char *modified, const char *changeset );
GEODIFF_EXPORT int GEODIFF_createChangeset(
const char *base,
const char *modified,
const char *changeset );


/**
Expand All @@ -91,7 +94,11 @@ GEODIFF_EXPORT int GEODIFF_createChangeset( const char *base, const char *modifi
* \param changeset [output] changeset between MODIFIED_THEIR -> MODIFIED_THEIR_PLUS_MINE
* \returns GEODIFF_SUCCESS on success
*/
GEODIFF_EXPORT int GEODIFF_createRebasedChangeset( const char *base, const char *modified, const char *changeset_their, const char *changeset );
GEODIFF_EXPORT int GEODIFF_createRebasedChangeset(
const char *base,
const char *modified,
const char *changeset_their,
const char *changeset );

/**
* Applies changeset file (binary) to BASE and creates PATCHED.
Expand All @@ -101,15 +108,30 @@ GEODIFF_EXPORT int GEODIFF_createRebasedChangeset( const char *base, const char
* \returns GEODIFF_SUCCESS on success
* GEODIFF_CONFICTS if the changeset was applied but conflicts were found
*/
GEODIFF_EXPORT int GEODIFF_applyChangeset( const char *base,
const char *patched,
const char *changeset );
GEODIFF_EXPORT int GEODIFF_applyChangeset(
const char *base,
const char *patched,
const char *changeset );


/**
* \returns -1 on error, 0 no changes, 1 has changes
*/
GEODIFF_EXPORT int GEODIFF_hasChanges( const char *changeset );

/**
* Lists changeset content to stdout
* \returns number of changes, -1 on error
*/
GEODIFF_EXPORT int GEODIFF_listChanges( const char *changeset );
GEODIFF_EXPORT int GEODIFF_changesCount( const char *changeset );

/**
* Expand changeset to JSON
* \returns GEODIFF_SUCCESS on success
*/
GEODIFF_EXPORT int GEODIFF_listChanges(
const char *changeset,
const char *jsonfile
);

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 7530eaf

Please sign in to comment.