Sfoglia il codice sorgente

Start adding prepared statement.

mingodad 13 anni fa
parent
commit
9f02a2c92b
1 ha cambiato i file con 86 aggiunte e 0 eliminazioni
  1. 86 0
      ext/sq_postgresql.cpp

+ 86 - 0
ext/sq_postgresql.cpp

@@ -446,6 +446,59 @@ static SQRegFunction sq_pgsql_result_methods[] =
 };
 #undef _DECL_FUNC
 
+struct PgSqlStatement {
+    PGconn *db;
+    PGresult *result;
+    char name[64];
+};
+
+static const SQChar *PostgreSQL_Statement_TAG = _SC("PostgreSQL_Statement");
+
+static SQRESULT get_pgsql_statement_instance(HSQUIRRELVM v, SQInteger idx, PgSqlStatement **self){
+    SQRESULT _rc_;
+	if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)PostgreSQL_Statement_TAG)) < 0) return _rc_;
+	if(!*self) return sq_throwerror(v, _SC("PGstatement is closed"));
+	return _rc_;
+}
+
+#define GET_pgsql_statement_INSTANCE_AT(idx) \
+	PgSqlStatement *self=NULL; \
+	if((_rc_ = get_pgsql_statement_instance(v,idx,&self)) < 0) return _rc_;
+
+#define GET_pgsql_statement_INSTANCE() GET_pgsql_statement_INSTANCE_AT(1)
+
+static SQRESULT sq_pgsql_statement_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	PgSqlStatement *self = ((PgSqlStatement *)p);
+	if (self && self->result){
+        char sql[128];
+        snprintf(sql, sizeof(sql), "DEALLOCATE '%s'", self->name);
+        PGresult *qres = dlPQexec(self->db, sql);
+        bool is_ok = dlPQresultStatus(qres) != PGRES_BAD_RESPONSE;
+        dlPQclear(qres);
+        if(is_ok) dlPQclear(self->result);
+        sq_free(self, sizeof(PgSqlStatement));
+	}
+	return 0;
+}
+
+static SQRESULT sq_pgsql_statement_close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_statement_INSTANCE();
+	sq_pgsql_statement_releasehook(self, 0, v);
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "Pgstatement is closed"
+	return 0;
+}
+
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_pgsql_statement_##name,nparams,tycheck}
+static SQRegFunction sq_pgsql_statement_methods[] =
+{
+	_DECL_FUNC(close,  1, _SC("x")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
 static SQRESULT sq_pgsql_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
 {
 	PGconn *self = ((PGconn *)p);
@@ -548,6 +601,32 @@ static SQRESULT sq_pgsql_exec_query(HSQUIRRELVM v){
     return sq_throwerror(v, dlPQerrorMessage(self));
 }
 
+static SQRESULT sq_pgsql_prepare(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_STRING(v, 2, szSQL);
+
+    PgSqlStatement *stmt = (PgSqlStatement*)sq_malloc(sizeof(PgSqlStatement));
+    stmt->db = self;
+    snprintf(stmt->name, sizeof(stmt->name), "sq_pg_preared_stmt_%p", stmt);
+
+    stmt->result = dlPQprepare(self, stmt->name, szSQL, 0, NULL);
+
+    if(dlPQresultStatus(stmt->result) == PGRES_COMMAND_OK){
+        sq_pushroottable(v);
+        sq_pushstring(v, PostgreSQL_Statement_TAG, -1);
+        if(sq_get(v, -2) == SQ_OK){
+            if(sq_createinstance(v, -1) == SQ_OK){
+                sq_setinstanceup(v, -1, stmt);
+                sq_setreleasehook(v, -1, sq_pgsql_statement_releasehook);
+                return 1;
+            }
+        }
+    }
+    sq_free(stmt, sizeof(PgSqlStatement));
+    return sq_throwerror(v, dlPQerrorMessage(self));
+}
+
 static SQRESULT sq_pgsql_error_message(HSQUIRRELVM v){
 	SQ_FUNC_VARS_NO_TOP(v);
 	GET_pgsql_INSTANCE();
@@ -696,6 +775,7 @@ static SQRegFunction sq_pgsql_methods[] =
 	_DECL_FUNC(exec_dml,  2, _SC("xs")),
 	_DECL_FUNC(exec_scalar,  2, _SC("xs")),
 	_DECL_FUNC(exec_query,  2, _SC("xs")),
+	_DECL_FUNC(prepare,  2, _SC("xs")),
 	_DECL_FUNC(error_message,  1, _SC("x")),
 	_DECL_FUNC(version,  1, _SC("x")),
 	_DECL_FUNC(get_blob_field,  2, _SC("xi")),
@@ -719,6 +799,12 @@ SQRESULT sqext_register_PostgreSQL(HSQUIRRELVM v)
     sq_insert_reg_funcs(v, sq_pgsql_methods);
     sq_newslot(v,-3,SQTrue);
 
+    sq_pushstring(v,PostgreSQL_Statement_TAG,-1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)PostgreSQL_Statement_TAG);
+    sq_insert_reg_funcs(v, sq_pgsql_statement_methods);
+    sq_newslot(v,-3,SQTrue);
+
     sq_pushstring(v,PostgreSQL_Result_TAG,-1);
     sq_newclass(v,SQFalse);
     sq_settypetag(v,-1,(void*)PostgreSQL_Result_TAG);