Răsfoiți Sursa

Expose SQLite3Session to squilu scripts

mingodad 9 ani în urmă
părinte
comite
68bd457da3
1 a modificat fișierele cu 112 adăugiri și 3 ștergeri
  1. 112 3
      SquiLu-ext/sq_sqlite3.cpp

+ 112 - 3
SquiLu-ext/sq_sqlite3.cpp

@@ -13,7 +13,6 @@ static const SQChar *SQLite3_Stmt_TAG = "SQLite3Stmt";
 static const SQChar sqlite3_NULL_Name[] = _SC("sqlite3_NULL");
 static const SQChar sqlite3_NULL_Name[] = _SC("sqlite3_NULL");
 static const SQChar nullName[] = _SC("Null");
 static const SQChar nullName[] = _SC("Null");
 
 
-
 //return error if parameter exists but is not a blob
 //return error if parameter exists but is not a blob
 //return 1 if the parameter exists and is a blob
 //return 1 if the parameter exists and is a blob
 //return 0 if the parameter doesn't exists and creates a new blob
 //return 0 if the parameter doesn't exists and creates a new blob
@@ -66,11 +65,12 @@ static SQRESULT get_sqlite3_stmt_instance(HSQUIRRELVM v, SQInteger idx, sqlite3_
 //the line bellow is the fastest one, any other attempt till now was slower
 //the line bellow is the fastest one, any other attempt till now was slower
 #define push_sqlite3_null(v) {sq_pushstring(v, nullName, sizeof(nullName)-1);sq_get(v, 1);}
 #define push_sqlite3_null(v) {sq_pushstring(v, nullName, sizeof(nullName)-1);sq_get(v, 1);}
 
 
-#define GET_sqlite3_INSTANCE_AT(idx) \
+#define GET_sqlite3_INSTANCE_AT_VAR(idx, self) \
 	sq_sqlite3_sdb *sdb=NULL; \
 	sq_sqlite3_sdb *sdb=NULL; \
 	if((_rc_ = get_sqlite3_instance(v,idx,&sdb)) < 0) return _rc_;\
 	if((_rc_ = get_sqlite3_instance(v,idx,&sdb)) < 0) return _rc_;\
 	sqlite3 *self = sdb->db;
 	sqlite3 *self = sdb->db;
 
 
+#define GET_sqlite3_INSTANCE_AT(idx) GET_sqlite3_INSTANCE_AT_VAR(idx, self)
 #define GET_sqlite3_INSTANCE() GET_sqlite3_INSTANCE_AT(1)
 #define GET_sqlite3_INSTANCE() GET_sqlite3_INSTANCE_AT(1)
 
 
 //#define GET_sqlite3_INSTANCE() SQ_GET_INSTANCE(v, 1, sqlite3, SQLite3_TAG)
 //#define GET_sqlite3_INSTANCE() SQ_GET_INSTANCE(v, 1, sqlite3, SQLite3_TAG)
@@ -79,7 +79,6 @@ static SQRESULT get_sqlite3_stmt_instance(HSQUIRRELVM v, SQInteger idx, sqlite3_
 	if((_rc_ = get_sqlite3_stmt_instance(v,idx,&var_name)) < 0) return _rc_;
 	if((_rc_ = get_sqlite3_stmt_instance(v,idx,&var_name)) < 0) return _rc_;
 #define GET_sqlite3_stmt_INSTANCE() GET_sqlite3_stmt_INSTANCE_AT(1, self)
 #define GET_sqlite3_stmt_INSTANCE() GET_sqlite3_stmt_INSTANCE_AT(1, self)
 
 
-
 enum e_type_result {tr_first_row_first_col, tr_first_row, tr_all_rows, tr_ddml};
 enum e_type_result {tr_first_row_first_col, tr_first_row, tr_all_rows, tr_ddml};
 
 
 #define AS_STRING_ALWAYS 0x01
 #define AS_STRING_ALWAYS 0x01
@@ -1395,6 +1394,107 @@ static SQRegFunction sq_sqlite3_stmt_methods[] =
 };
 };
 #undef _DECL_FUNC
 #undef _DECL_FUNC
 
 
+#ifdef SQLITE_ENABLE_SESSION
+
+static const SQChar *SQLite3_Session_TAG = "SQLite3Session";
+
+static SQRESULT get_sqlite3_session_instance(HSQUIRRELVM v, SQInteger idx, sqlite3_session **session)
+{
+    SQRESULT _rc_;
+    if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)session,(void*)SQLite3_Session_TAG)) < 0) return _rc_;
+    if(!*session) return sq_throwerror(v, _SC("session is closed"));
+    return _rc_;
+}
+
+#define GET_sqlite3_session_INSTANCE_AT(idx, var_name)  \
+	sqlite3_session *var_name=NULL; \
+	if((_rc_ = get_sqlite3_session_instance(v,idx,&var_name)) < 0) return _rc_;
+#define GET_sqlite3_session_INSTANCE() GET_sqlite3_session_INSTANCE_AT(1, self)
+
+static SQRESULT sq_sqlite3_session_releasehook(SQUserPointer p, SQInteger size, void */*ep*/)
+{
+    sqlite3_session *session = ((sqlite3_session *)p);
+    if(session) sqlite3session_delete(session);
+    return 0;
+}
+
+static SQRESULT sq_sqlite3_session_constructor(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    _rc_ = SQ_ERROR;
+    GET_sqlite3_INSTANCE_AT(2);
+    SQ_OPT_STRING(v, 3, dbname, _SC("main"))
+    sqlite3_session *session = 0;
+    if(sqlite3session_create(self, dbname, &session) != SQLITE_OK)
+    {
+        _rc_ = sq_throwerror(v, sqlite3_errmsg(self));
+    }
+    else _rc_ = SQ_OK;
+    sq_setinstanceup(v, 1, session); //replace self for this instance with this new sqlite3_stmt
+    sq_setreleasehook(v,1, sq_sqlite3_session_releasehook);
+    return _rc_;
+}
+
+static SQRESULT sq_sqlite3_session_attach(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    GET_sqlite3_session_INSTANCE();
+    SQ_OPT_STRING(v, 2, tables, NULL);
+    sq_pushinteger(v, sqlite3session_attach(self, tables));
+    return 1;
+}
+
+static SQRESULT sq_sqlite3_session_delete(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_sqlite3_session_INSTANCE();
+    sqlite3session_delete(self);
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "database is closed"
+    return 0;
+}
+
+static SQRESULT sq_sqlite3_session_changeset(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_sqlite3_session_INSTANCE();
+    int nChangeset;     /* OUT: Size of changeset blob in bytes */
+    void *pChangeset;   /* OUT: Pointer to changeset blob */
+    if(sqlite3session_changeset(self, &nChangeset, &pChangeset) != SQ_OK) return SQ_ERROR;
+    sq_pushstring(v, (SQChar*)pChangeset, nChangeset);
+    sqlite3_free(pChangeset);
+    return 1;
+}
+
+static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *pIter){
+  int ret = (int)(ptrdiff_t)pCtx;
+  return ret;
+}
+
+static SQRESULT sq_sqlite3_session_apply(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_sqlite3_session_INSTANCE();
+    GET_sqlite3_INSTANCE_AT_VAR(2, db);
+    SQ_GET_STRING(v, 3, changeset);
+    if(sqlite3changeset_apply(db, changeset_size, (void*)changeset, 0, xConflict, (void*)0) != SQ_OK) return SQ_ERROR;
+    return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck, isStatic) {_SC(#name),  sq_sqlite3_session_##name,nparams,tycheck, isStatic}
+static SQRegFunction sq_sqlite3_session_methods[] =
+{
+    _DECL_FUNC(constructor,  -2, _SC("xxs"), SQFalse),
+
+    _DECL_FUNC(attach,  -1, _SC("xs"), SQFalse),
+    _DECL_FUNC(changeset,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(delete,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(apply,  3, _SC("xxs"), SQFalse),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+#endif // SQLITE_ENABLE_SESSION
+
 static SQRESULT sqlite3_exec_fmt(HSQUIRRELVM v, e_type_result type_result, int null_as_empty_str=1)
 static SQRESULT sqlite3_exec_fmt(HSQUIRRELVM v, e_type_result type_result, int null_as_empty_str=1)
 {
 {
     SQ_FUNC_VARS_NO_TOP(v);
     SQ_FUNC_VARS_NO_TOP(v);
@@ -3104,6 +3204,15 @@ extern "C" {
 
 
         sq_newslot(v,-3,SQTrue);
         sq_newslot(v,-3,SQTrue);
 
 
+#ifdef SQLITE_ENABLE_SESSION
+        sq_pushstring(v, SQLite3_Session_TAG,-1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(SQUserPointer)SQLite3_Session_TAG);
+        sq_insert_reg_funcs(v, sq_sqlite3_session_methods);
+
+        sq_newslot(v,-3,SQTrue);
+#endif // SQLITE_ENABLE_SESSION
+
         sq_pushstring(v, SQLite3_Stmt_TAG,-1);
         sq_pushstring(v, SQLite3_Stmt_TAG,-1);
         sq_newclass(v,SQFalse);
         sq_newclass(v,SQFalse);
         sq_settypetag(v,-1,(SQUserPointer)SQLite3_Stmt_TAG);
         sq_settypetag(v,-1,(SQUserPointer)SQLite3_Stmt_TAG);