Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
test_window.c350 linesDownload Raw Back to src
1/*2** 2018 June 173**4** The author disclaims copyright to this source code.  In place of5** a legal notice, here is a blessing:6**7**    May you do good and not evil.8**    May you find forgiveness for yourself and forgive others.9**    May you share freely, never taking more than you give.10**11*************************************************************************12*/13 14#include "sqlite3.h"15 16#ifdef SQLITE_TEST17 18#include "sqliteInt.h"19#include "tclsqlite.h"20 21extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);22extern const char *sqlite3ErrName(int);23 24typedef struct TestWindow TestWindow;25struct TestWindow {26  Tcl_Obj *xStep;27  Tcl_Obj *xFinal;28  Tcl_Obj *xValue;29  Tcl_Obj *xInverse;30  Tcl_Interp *interp;31};32 33typedef struct TestWindowCtx TestWindowCtx;34struct TestWindowCtx {35  Tcl_Obj *pVal;36};37 38static void doTestWindowStep(39  int bInverse,40  sqlite3_context *ctx, 41  int nArg, 42  sqlite3_value **apArg43){44  int i;45  TestWindow *p = (TestWindow*)sqlite3_user_data(ctx);46  Tcl_Obj *pEval = Tcl_DuplicateObj(bInverse ? p->xInverse : p->xStep);47  TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx));48 49  Tcl_IncrRefCount(pEval);50  if( pCtx ){51    const char *zResult;52    int rc;53    if( pCtx->pVal ){54      Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal));55    }else{56      Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1));57    }58    for(i=0; i<nArg; i++){59      Tcl_Obj *pArg;60      pArg = Tcl_NewStringObj((const char*)sqlite3_value_text(apArg[i]), -1);61      Tcl_ListObjAppendElement(p->interp, pEval, pArg);62    }63    rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);64    if( rc!=TCL_OK ){65      zResult = Tcl_GetStringResult(p->interp);66      sqlite3_result_error(ctx, zResult, -1);67    }else{68      if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal);69      pCtx->pVal = Tcl_DuplicateObj(Tcl_GetObjResult(p->interp));70      Tcl_IncrRefCount(pCtx->pVal);71    }72  }73  Tcl_DecrRefCount(pEval);74}75 76static void doTestWindowFinalize(int bValue, sqlite3_context *ctx){77  TestWindow *p = (TestWindow*)sqlite3_user_data(ctx);78  Tcl_Obj *pEval = Tcl_DuplicateObj(bValue ? p->xValue : p->xFinal);79  TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx));80 81  Tcl_IncrRefCount(pEval);82  if( pCtx ){83    const char *zResult;84    int rc;85    if( pCtx->pVal ){86      Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal));87    }else{88      Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1));89    }90 91    rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);92    zResult = Tcl_GetStringResult(p->interp);93    if( rc!=TCL_OK ){94      sqlite3_result_error(ctx, zResult, -1);95    }else{96      sqlite3_result_text(ctx, zResult, -1, SQLITE_TRANSIENT);97    }98 99    if( bValue==0 ){100      if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal);101      pCtx->pVal = 0;102    }103  }104  Tcl_DecrRefCount(pEval);105}106 107static void testWindowStep(108  sqlite3_context *ctx, 109  int nArg, 110  sqlite3_value **apArg111){112  doTestWindowStep(0, ctx, nArg, apArg);113}114static void testWindowInverse(115  sqlite3_context *ctx, 116  int nArg, 117  sqlite3_value **apArg118){119  doTestWindowStep(1, ctx, nArg, apArg);120}121 122static void testWindowFinal(sqlite3_context *ctx){123  doTestWindowFinalize(0, ctx);124}125static void testWindowValue(sqlite3_context *ctx){126  doTestWindowFinalize(1, ctx);127}128 129static void testWindowDestroy(void *pCtx){130  ckfree(pCtx);131}132 133/*134** Usage: sqlite3_create_window_function DB NAME XSTEP XFINAL XVALUE XINVERSE135*/136static int SQLITE_TCLAPI test_create_window(137  void * clientData,138  Tcl_Interp *interp,139  int objc,140  Tcl_Obj *CONST objv[]141){142  TestWindow *pNew;143  sqlite3 *db;144  const char *zName;145  int rc;146 147  if( objc!=7 ){148    Tcl_WrongNumArgs(interp, 1, objv, "DB NAME XSTEP XFINAL XVALUE XINVERSE");149    return TCL_ERROR;150  }151 152  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;153  zName = Tcl_GetString(objv[2]);154  pNew = (TestWindow*)ckalloc(sizeof(TestWindow));155  memset(pNew, 0, sizeof(TestWindow));156  pNew->xStep = Tcl_DuplicateObj(objv[3]);157  pNew->xFinal = Tcl_DuplicateObj(objv[4]);158  pNew->xValue = Tcl_DuplicateObj(objv[5]);159  pNew->xInverse = Tcl_DuplicateObj(objv[6]);160  pNew->interp = interp;161 162  Tcl_IncrRefCount(pNew->xStep);163  Tcl_IncrRefCount(pNew->xFinal);164  Tcl_IncrRefCount(pNew->xValue);165  Tcl_IncrRefCount(pNew->xInverse);166 167  rc = sqlite3_create_window_function(db, zName, -1, SQLITE_UTF8, (void*)pNew,168      testWindowStep, testWindowFinal, testWindowValue, testWindowInverse,169      testWindowDestroy170  );171  if( rc!=SQLITE_OK ){172    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));173    return TCL_ERROR;174  }175 176  return TCL_OK;177}178 179static int SQLITE_TCLAPI test_create_window_misuse(180  void * clientData,181  Tcl_Interp *interp,182  int objc,183  Tcl_Obj *CONST objv[]184){185  sqlite3 *db;186  int rc;187 188  if( objc!=2 ){189    Tcl_WrongNumArgs(interp, 1, objv, "DB");190    return TCL_ERROR;191  }192  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;193 194  rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,195      0, testWindowFinal, testWindowValue, testWindowInverse,196      0197  );198  if( rc!=SQLITE_MISUSE ) goto error;199  rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,200      testWindowStep, 0, testWindowValue, testWindowInverse,201      0202  );203  if( rc!=SQLITE_MISUSE ) goto error;204  rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,205      testWindowStep, testWindowFinal, 0, testWindowInverse,206      0207  );208  if( rc!=SQLITE_MISUSE ) goto error;209  rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,210      testWindowStep, testWindowFinal, testWindowValue, 0,211      0212  );213  if( rc!=SQLITE_MISUSE ) goto error;214 215  return TCL_OK;216 217 error:218  Tcl_SetObjResult(interp, Tcl_NewStringObj("misuse test error", -1));219  return TCL_ERROR;220}221 222/*223** xStep for sumint().224*/225static void sumintStep(226  sqlite3_context *ctx, 227  int nArg, 228  sqlite3_value *apArg[]229){230  sqlite3_int64 *pInt;231 232  assert( nArg==1 );233  if( sqlite3_value_type(apArg[0])!=SQLITE_INTEGER ){234    sqlite3_result_error(ctx, "invalid argument", -1);235    return;236  }237  pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64));238  if( pInt ){239    *pInt += sqlite3_value_int64(apArg[0]);240  }241}242 243/*244** xInverse for sumint().245*/246static void sumintInverse(247  sqlite3_context *ctx, 248  int nArg, 249  sqlite3_value *apArg[]250){251  sqlite3_int64 *pInt;252  pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64));253  *pInt -= sqlite3_value_int64(apArg[0]);254}255 256/*257** xFinal for sumint().258*/259static void sumintFinal(sqlite3_context *ctx){260  sqlite3_int64 res = 0;261  sqlite3_int64 *pInt;262  pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0);263  if( pInt ) res = *pInt;264  sqlite3_result_int64(ctx, res);265}266 267/*268** xValue for sumint().269*/270static void sumintValue(sqlite3_context *ctx){271  sqlite3_int64 res = 0;272  sqlite3_int64 *pInt;273  pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0);274  if( pInt ) res = *pInt;275  sqlite3_result_int64(ctx, res);276}277 278static int SQLITE_TCLAPI test_create_sumint(279  void * clientData,280  Tcl_Interp *interp,281  int objc,282  Tcl_Obj *CONST objv[]283){284  sqlite3 *db;285  int rc;286 287  if( objc!=2 ){288    Tcl_WrongNumArgs(interp, 1, objv, "DB");289    return TCL_ERROR;290  }291  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;292 293  rc = sqlite3_create_window_function(db, "sumint", 1, SQLITE_UTF8, 0,294      sumintStep, sumintFinal, sumintValue, sumintInverse,295      0296  );297 298  if( rc!=SQLITE_OK ){299    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));300    return TCL_ERROR;301  }302  return TCL_OK;303}304 305static int SQLITE_TCLAPI test_override_sum(306  void * clientData,307  Tcl_Interp *interp,308  int objc,309  Tcl_Obj *CONST objv[]310){311  sqlite3 *db;312  int rc;313 314  if( objc!=2 ){315    Tcl_WrongNumArgs(interp, 1, objv, "DB");316    return TCL_ERROR;317  }318  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;319 320  rc = sqlite3_create_function(db, "sum", -1, SQLITE_UTF8, 0,321      0, sumintStep, sumintFinal322  );323 324  if( rc!=SQLITE_OK ){325    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));326    return TCL_ERROR;327  }328  return TCL_OK;329}330 331int Sqlitetest_window_Init(Tcl_Interp *interp){332  static struct {333     char *zName;334     Tcl_ObjCmdProc *xProc;335     int clientData;336  } aObjCmd[] = {337     { "sqlite3_create_window_function", test_create_window, 0 },338     { "test_create_window_function_misuse", test_create_window_misuse, 0 },339     { "test_create_sumint", test_create_sumint, 0 },340     { "test_override_sum", test_override_sum, 0 },341  };342  int i;343  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){344    ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);345    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);346  }347  return TCL_OK;348}349#endif350