modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/closure.c (about)

     1  /*
     2  ** 2013-04-16
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** 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  ** This file contains code for a virtual table that finds the transitive
    14  ** closure of a parent/child relationship in a real table.  The virtual 
    15  ** table is called "transitive_closure".
    16  **
    17  ** A transitive_closure virtual table is created like this:
    18  **
    19  **     CREATE VIRTUAL TABLE x USING transitive_closure(
    20  **        tablename=<tablename>,      -- T
    21  **        idcolumn=<columnname>,      -- X
    22  **        parentcolumn=<columnname>   -- P
    23  **     );
    24  **
    25  ** When it is created, the new transitive_closure table may be supplied 
    26  ** with default values for the name of a table T and columns T.X and T.P.
    27  ** The T.X and T.P columns must contain integers.  The ideal case is for 
    28  ** T.X to be the INTEGER PRIMARY KEY.  The T.P column should reference
    29  ** the T.X column. The row referenced by T.P is the parent of the current row.
    30  **
    31  ** The tablename, idcolumn, and parentcolumn supplied by the CREATE VIRTUAL
    32  ** TABLE statement may be overridden in individual queries by including
    33  ** terms like tablename='newtable', idcolumn='id2', or 
    34  ** parentcolumn='parent3' in the WHERE clause of the query.
    35  **
    36  ** For efficiency, it is essential that there be an index on the P column:
    37  **
    38  **    CREATE Tidx1 ON T(P)
    39  **
    40  ** Suppose a specific instance of the closure table is as follows:
    41  **
    42  **    CREATE VIRTUAL TABLE ct1 USING transitive_closure(
    43  **       tablename='group',
    44  **       idcolumn='groupId',
    45  **       parentcolumn='parentId'
    46  **    );
    47  **
    48  ** Such an instance of the transitive_closure virtual table would be
    49  ** appropriate for walking a tree defined using a table like this, for example:
    50  **
    51  **    CREATE TABLE group(
    52  **      groupId INTEGER PRIMARY KEY,
    53  **      parentId INTEGER REFERENCES group
    54  **    );
    55  **    CREATE INDEX group_idx1 ON group(parentId);
    56  **
    57  ** The group table above would presumably have other application-specific
    58  ** fields.  The key point here is that rows of the group table form a
    59  ** tree.  The purpose of the ct1 virtual table is to easily extract
    60  ** branches of that tree.
    61  **
    62  ** Once it has been created, the ct1 virtual table can be queried
    63  ** as follows:
    64  **
    65  **    SELECT * FROM element
    66  **     WHERE element.groupId IN (SELECT id FROM ct1 WHERE root=?1);
    67  **
    68  ** The above query will return all elements that are part of group ?1
    69  ** or children of group ?1 or grand-children of ?1 and so forth for all
    70  ** descendents of group ?1.  The same query can be formulated as a join:
    71  **
    72  **    SELECT element.* FROM element, ct1
    73  **     WHERE element.groupid=ct1.id
    74  **       AND ct1.root=?1;
    75  **
    76  ** The depth of the transitive_closure (the number of generations of
    77  ** parent/child relations to follow) can be limited by setting "depth"
    78  ** column in the WHERE clause.  So, for example, the following query
    79  ** finds only children and grandchildren but no further descendents:
    80  **
    81  **    SELECT element.* FROM element, ct1
    82  **     WHERE element.groupid=ct1.id
    83  **       AND ct1.root=?1
    84  **       AND ct1.depth<=2;
    85  **
    86  ** The "ct1.depth<=2" term could be a strict equality "ct1.depth=2" in
    87  ** order to find only the grandchildren of ?1, not ?1 itself or the
    88  ** children of ?1.
    89  ** 
    90  ** The root=?1 term must be supplied in WHERE clause or else the query
    91  ** of the ct1 virtual table will return an empty set.  The tablename,
    92  ** idcolumn, and parentcolumn attributes can be overridden in the WHERE
    93  ** clause if desired.  So, for example, the ct1 table could be repurposed
    94  ** to find ancestors rather than descendents by inverting the roles of
    95  ** the idcolumn and parentcolumn:
    96  **
    97  **    SELECT element.* FROM element, ct1
    98  **     WHERE element.groupid=ct1.id
    99  **       AND ct1.root=?1
   100  **       AND ct1.idcolumn='parentId'
   101  **       AND ct1.parentcolumn='groupId';
   102  **
   103  ** Multiple calls to ct1 could be combined.  For example, the following
   104  ** query finds all elements that "cousins" of groupId ?1.  That is to say
   105  ** elements where the groupId is a grandchild of the grandparent of ?1.
   106  ** (This definition of "cousins" also includes siblings and self.)
   107  **
   108  **    SELECT element.* FROM element, ct1
   109  **     WHERE element.groupId=ct1.id
   110  **       AND ct1.depth=2
   111  **       AND ct1.root IN (SELECT id FROM ct1
   112  **                         WHERE root=?1
   113  **                           AND depth=2
   114  **                           AND idcolumn='parentId'
   115  **                           AND parentcolumn='groupId');
   116  **
   117  ** In our example, the group.groupId column is unique and thus the
   118  ** subquery will return exactly one row.  For that reason, the IN
   119  ** operator could be replaced by "=" to get the same result.  But
   120  ** in the general case where the idcolumn is not unique, an IN operator
   121  ** would be required for this kind of query.
   122  **
   123  ** Note that because the tablename, idcolumn, and parentcolumn can
   124  ** all be specified in the query, it is possible for an application
   125  ** to define a single transitive_closure virtual table for use on lots
   126  ** of different hierarchy tables.  One might say:
   127  **
   128  **     CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
   129  **
   130  ** As each database connection is being opened.  Then the application
   131  ** would always have a "closure" virtual table handy to use for querying.
   132  **
   133  **    SELECT element.* FROM element, closure
   134  **     WHERE element.groupid=ct1.id
   135  **       AND closure.root=?1
   136  **       AND closure.tablename='group'
   137  **       AND closure.idname='groupId'
   138  **       AND closure.parentname='parentId';
   139  **
   140  ** See the documentation at http://www.sqlite.org/loadext.html for information
   141  ** on how to compile and use loadable extensions such as this one.
   142  */
   143  #include "sqlite3ext.h"
   144  SQLITE_EXTENSION_INIT1
   145  #include <stdlib.h>
   146  #include <string.h>
   147  #include <assert.h>
   148  #include <stdio.h>
   149  #include <ctype.h>
   150  
   151  #ifndef SQLITE_OMIT_VIRTUALTABLE
   152  
   153  /*
   154  ** Forward declaration of objects used by this implementation
   155  */
   156  typedef struct closure_vtab closure_vtab;
   157  typedef struct closure_cursor closure_cursor;
   158  typedef struct closure_queue closure_queue;
   159  typedef struct closure_avl closure_avl;
   160  
   161  /*****************************************************************************
   162  ** AVL Tree implementation
   163  */
   164  /*
   165  ** Objects that want to be members of the AVL tree should embedded an
   166  ** instance of this structure.
   167  */
   168  struct closure_avl {
   169    sqlite3_int64 id;     /* Id of this entry in the table */
   170    int iGeneration;      /* Which generation is this entry part of */
   171    closure_avl *pList;   /* A linked list of nodes */
   172    closure_avl *pBefore; /* Other elements less than id */
   173    closure_avl *pAfter;  /* Other elements greater than id */
   174    closure_avl *pUp;     /* Parent element */
   175    short int height;     /* Height of this node.  Leaf==1 */
   176    short int imbalance;  /* Height difference between pBefore and pAfter */
   177  };
   178  
   179  /* Recompute the closure_avl.height and closure_avl.imbalance fields for p.
   180  ** Assume that the children of p have correct heights.
   181  */
   182  static void closureAvlRecomputeHeight(closure_avl *p){
   183    short int hBefore = p->pBefore ? p->pBefore->height : 0;
   184    short int hAfter = p->pAfter ? p->pAfter->height : 0;
   185    p->imbalance = hBefore - hAfter;  /* -: pAfter higher.  +: pBefore higher */
   186    p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
   187  }
   188  
   189  /*
   190  **     P                B
   191  **    / \              / \
   192  **   B   Z    ==>     X   P
   193  **  / \                  / \
   194  ** X   Y                Y   Z
   195  **
   196  */
   197  static closure_avl *closureAvlRotateBefore(closure_avl *pP){
   198    closure_avl *pB = pP->pBefore;
   199    closure_avl *pY = pB->pAfter;
   200    pB->pUp = pP->pUp;
   201    pB->pAfter = pP;
   202    pP->pUp = pB;
   203    pP->pBefore = pY;
   204    if( pY ) pY->pUp = pP;
   205    closureAvlRecomputeHeight(pP);
   206    closureAvlRecomputeHeight(pB);
   207    return pB;
   208  }
   209  
   210  /*
   211  **     P                A
   212  **    / \              / \
   213  **   X   A    ==>     P   Z
   214  **      / \          / \
   215  **     Y   Z        X   Y
   216  **
   217  */
   218  static closure_avl *closureAvlRotateAfter(closure_avl *pP){
   219    closure_avl *pA = pP->pAfter;
   220    closure_avl *pY = pA->pBefore;
   221    pA->pUp = pP->pUp;
   222    pA->pBefore = pP;
   223    pP->pUp = pA;
   224    pP->pAfter = pY;
   225    if( pY ) pY->pUp = pP;
   226    closureAvlRecomputeHeight(pP);
   227    closureAvlRecomputeHeight(pA);
   228    return pA;
   229  }
   230  
   231  /*
   232  ** Return a pointer to the pBefore or pAfter pointer in the parent
   233  ** of p that points to p.  Or if p is the root node, return pp.
   234  */
   235  static closure_avl **closureAvlFromPtr(closure_avl *p, closure_avl **pp){
   236    closure_avl *pUp = p->pUp;
   237    if( pUp==0 ) return pp;
   238    if( pUp->pAfter==p ) return &pUp->pAfter;
   239    return &pUp->pBefore;
   240  }
   241  
   242  /*
   243  ** Rebalance all nodes starting with p and working up to the root.
   244  ** Return the new root.
   245  */
   246  static closure_avl *closureAvlBalance(closure_avl *p){
   247    closure_avl *pTop = p;
   248    closure_avl **pp;
   249    while( p ){
   250      closureAvlRecomputeHeight(p);
   251      if( p->imbalance>=2 ){
   252        closure_avl *pB = p->pBefore;
   253        if( pB->imbalance<0 ) p->pBefore = closureAvlRotateAfter(pB);
   254        pp = closureAvlFromPtr(p,&p);
   255        p = *pp = closureAvlRotateBefore(p);
   256      }else if( p->imbalance<=(-2) ){
   257        closure_avl *pA = p->pAfter;
   258        if( pA->imbalance>0 ) p->pAfter = closureAvlRotateBefore(pA);
   259        pp = closureAvlFromPtr(p,&p);
   260        p = *pp = closureAvlRotateAfter(p);
   261      }
   262      pTop = p;
   263      p = p->pUp;
   264    }
   265    return pTop;
   266  }
   267  
   268  /* Search the tree rooted at p for an entry with id.  Return a pointer
   269  ** to the entry or return NULL.
   270  */
   271  static closure_avl *closureAvlSearch(closure_avl *p, sqlite3_int64 id){
   272    while( p && id!=p->id ){
   273      p = (id<p->id) ? p->pBefore : p->pAfter;
   274    }
   275    return p;
   276  }
   277  
   278  /* Find the first node (the one with the smallest key).
   279  */
   280  static closure_avl *closureAvlFirst(closure_avl *p){
   281    if( p ) while( p->pBefore ) p = p->pBefore;
   282    return p;
   283  }
   284  
   285  /* Return the node with the next larger key after p.
   286  */
   287  closure_avl *closureAvlNext(closure_avl *p){
   288    closure_avl *pPrev = 0;
   289    while( p && p->pAfter==pPrev ){
   290      pPrev = p;
   291      p = p->pUp;
   292    }
   293    if( p && pPrev==0 ){
   294      p = closureAvlFirst(p->pAfter);
   295    }
   296    return p;
   297  }
   298  
   299  /* Insert a new node pNew.  Return NULL on success.  If the key is not
   300  ** unique, then do not perform the insert but instead leave pNew unchanged
   301  ** and return a pointer to an existing node with the same key.
   302  */
   303  static closure_avl *closureAvlInsert(
   304    closure_avl **ppHead,  /* Head of the tree */
   305    closure_avl *pNew      /* New node to be inserted */
   306  ){
   307    closure_avl *p = *ppHead;
   308    if( p==0 ){
   309      p = pNew;
   310      pNew->pUp = 0;
   311    }else{
   312      while( p ){
   313        if( pNew->id<p->id ){
   314          if( p->pBefore ){
   315            p = p->pBefore;
   316          }else{
   317            p->pBefore = pNew;
   318            pNew->pUp = p;
   319            break;
   320          }
   321        }else if( pNew->id>p->id ){
   322          if( p->pAfter ){
   323            p = p->pAfter;
   324          }else{
   325            p->pAfter = pNew;
   326            pNew->pUp = p;
   327            break;
   328          }
   329        }else{
   330          return p;
   331        }
   332      }
   333    }
   334    pNew->pBefore = 0;
   335    pNew->pAfter = 0;
   336    pNew->height = 1;
   337    pNew->imbalance = 0;
   338    *ppHead = closureAvlBalance(p);
   339    return 0;
   340  }
   341  
   342  /* Walk the tree can call xDestroy on each node
   343  */
   344  static void closureAvlDestroy(closure_avl *p, void (*xDestroy)(closure_avl*)){
   345    if( p ){
   346      closureAvlDestroy(p->pBefore, xDestroy);
   347      closureAvlDestroy(p->pAfter, xDestroy);
   348      xDestroy(p);
   349    }
   350  }
   351  /*
   352  ** End of the AVL Tree implementation
   353  ******************************************************************************/
   354  
   355  /* 
   356  ** A closure virtual-table object 
   357  */
   358  struct closure_vtab {
   359    sqlite3_vtab base;         /* Base class - must be first */
   360    char *zDb;                 /* Name of database.  (ex: "main") */
   361    char *zSelf;               /* Name of this virtual table */
   362    char *zTableName;          /* Name of table holding parent/child relation */
   363    char *zIdColumn;           /* Name of ID column of zTableName */
   364    char *zParentColumn;       /* Name of PARENT column in zTableName */
   365    sqlite3 *db;               /* The database connection */
   366    int nCursor;               /* Number of pending cursors */
   367  };
   368  
   369  /* A closure cursor object */
   370  struct closure_cursor {
   371    sqlite3_vtab_cursor base;  /* Base class - must be first */
   372    closure_vtab *pVtab;       /* The virtual table this cursor belongs to */
   373    char *zTableName;          /* Name of table holding parent/child relation */
   374    char *zIdColumn;           /* Name of ID column of zTableName */
   375    char *zParentColumn;       /* Name of PARENT column in zTableName */
   376    closure_avl *pCurrent;     /* Current element of output */
   377    closure_avl *pClosure;     /* The complete closure tree */
   378  };
   379  
   380  /* A queue of AVL nodes */
   381  struct closure_queue {
   382    closure_avl *pFirst;       /* Oldest node on the queue */
   383    closure_avl *pLast;        /* Youngest node on the queue */
   384  };
   385  
   386  /*
   387  ** Add a node to the end of the queue
   388  */
   389  static void queuePush(closure_queue *pQueue, closure_avl *pNode){
   390    pNode->pList = 0;
   391    if( pQueue->pLast ){
   392      pQueue->pLast->pList = pNode;
   393    }else{
   394      pQueue->pFirst = pNode;
   395    }
   396    pQueue->pLast = pNode;
   397  }
   398  
   399  /*
   400  ** Extract the oldest element (the front element) from the queue.
   401  */
   402  static closure_avl *queuePull(closure_queue *pQueue){
   403    closure_avl *p = pQueue->pFirst;
   404    if( p ){
   405      pQueue->pFirst = p->pList;
   406      if( pQueue->pFirst==0 ) pQueue->pLast = 0;
   407    }
   408    return p;
   409  }
   410  
   411  /*
   412  ** This function converts an SQL quoted string into an unquoted string
   413  ** and returns a pointer to a buffer allocated using sqlite3_malloc() 
   414  ** containing the result. The caller should eventually free this buffer
   415  ** using sqlite3_free.
   416  **
   417  ** Examples:
   418  **
   419  **     "abc"   becomes   abc
   420  **     'xyz'   becomes   xyz
   421  **     [pqr]   becomes   pqr
   422  **     `mno`   becomes   mno
   423  */
   424  static char *closureDequote(const char *zIn){
   425    int nIn;                        /* Size of input string, in bytes */
   426    char *zOut;                     /* Output (dequoted) string */
   427  
   428    nIn = (int)strlen(zIn);
   429    zOut = sqlite3_malloc(nIn+1);
   430    if( zOut ){
   431      char q = zIn[0];              /* Quote character (if any ) */
   432  
   433      if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
   434        memcpy(zOut, zIn, nIn+1);
   435      }else{
   436        int iOut = 0;               /* Index of next byte to write to output */
   437        int iIn;                    /* Index of next byte to read from input */
   438  
   439        if( q=='[' ) q = ']';
   440        for(iIn=1; iIn<nIn; iIn++){
   441          if( zIn[iIn]==q ) iIn++;
   442          zOut[iOut++] = zIn[iIn];
   443        }
   444      }
   445      assert( (int)strlen(zOut)<=nIn );
   446    }
   447    return zOut;
   448  }
   449  
   450  /*
   451  ** Deallocate an closure_vtab object
   452  */
   453  static void closureFree(closure_vtab *p){
   454    if( p ){
   455      sqlite3_free(p->zDb);
   456      sqlite3_free(p->zSelf);
   457      sqlite3_free(p->zTableName);
   458      sqlite3_free(p->zIdColumn);
   459      sqlite3_free(p->zParentColumn);
   460      memset(p, 0, sizeof(*p));
   461      sqlite3_free(p);
   462    }
   463  }
   464  
   465  /*
   466  ** xDisconnect/xDestroy method for the closure module.
   467  */
   468  static int closureDisconnect(sqlite3_vtab *pVtab){
   469    closure_vtab *p = (closure_vtab*)pVtab;
   470    assert( p->nCursor==0 );
   471    closureFree(p);
   472    return SQLITE_OK;
   473  }
   474  
   475  /*
   476  ** Check to see if the argument is of the form:
   477  **
   478  **       KEY = VALUE
   479  **
   480  ** If it is, return a pointer to the first character of VALUE.
   481  ** If not, return NULL.  Spaces around the = are ignored.
   482  */
   483  static const char *closureValueOfKey(const char *zKey, const char *zStr){
   484    int nKey = (int)strlen(zKey);
   485    int nStr = (int)strlen(zStr);
   486    int i;
   487    if( nStr<nKey+1 ) return 0;
   488    if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
   489    for(i=nKey; isspace((unsigned char)zStr[i]); i++){}
   490    if( zStr[i]!='=' ) return 0;
   491    i++;
   492    while( isspace((unsigned char)zStr[i]) ){ i++; }
   493    return zStr+i;
   494  }
   495  
   496  /*
   497  ** xConnect/xCreate method for the closure module. Arguments are:
   498  **
   499  **   argv[0]    -> module name  ("transitive_closure")
   500  **   argv[1]    -> database name
   501  **   argv[2]    -> table name
   502  **   argv[3...] -> arguments
   503  */
   504  static int closureConnect(
   505    sqlite3 *db,
   506    void *pAux,
   507    int argc, const char *const*argv,
   508    sqlite3_vtab **ppVtab,
   509    char **pzErr
   510  ){
   511    int rc = SQLITE_OK;              /* Return code */
   512    closure_vtab *pNew = 0;          /* New virtual table */
   513    const char *zDb = argv[1];
   514    const char *zVal;
   515    int i;
   516  
   517    (void)pAux;
   518    *ppVtab = 0;
   519    pNew = sqlite3_malloc( sizeof(*pNew) );
   520    if( pNew==0 ) return SQLITE_NOMEM;
   521    rc = SQLITE_NOMEM;
   522    memset(pNew, 0, sizeof(*pNew));
   523    pNew->db = db;
   524    pNew->zDb = sqlite3_mprintf("%s", zDb);
   525    if( pNew->zDb==0 ) goto closureConnectError;
   526    pNew->zSelf = sqlite3_mprintf("%s", argv[2]);
   527    if( pNew->zSelf==0 ) goto closureConnectError;
   528    for(i=3; i<argc; i++){
   529      zVal = closureValueOfKey("tablename", argv[i]);
   530      if( zVal ){
   531        sqlite3_free(pNew->zTableName);
   532        pNew->zTableName = closureDequote(zVal);
   533        if( pNew->zTableName==0 ) goto closureConnectError;
   534        continue;
   535      }
   536      zVal = closureValueOfKey("idcolumn", argv[i]);
   537      if( zVal ){
   538        sqlite3_free(pNew->zIdColumn);
   539        pNew->zIdColumn = closureDequote(zVal);
   540        if( pNew->zIdColumn==0 ) goto closureConnectError;
   541        continue;
   542      }
   543      zVal = closureValueOfKey("parentcolumn", argv[i]);
   544      if( zVal ){
   545        sqlite3_free(pNew->zParentColumn);
   546        pNew->zParentColumn = closureDequote(zVal);
   547        if( pNew->zParentColumn==0 ) goto closureConnectError;
   548        continue;
   549      }
   550      *pzErr = sqlite3_mprintf("unrecognized argument: [%s]\n", argv[i]);
   551      closureFree(pNew);
   552      *ppVtab = 0;
   553      return SQLITE_ERROR;
   554    }
   555    rc = sqlite3_declare_vtab(db,
   556           "CREATE TABLE x(id,depth,root HIDDEN,tablename HIDDEN,"
   557                          "idcolumn HIDDEN,parentcolumn HIDDEN)"
   558         );
   559  #define CLOSURE_COL_ID              0
   560  #define CLOSURE_COL_DEPTH           1
   561  #define CLOSURE_COL_ROOT            2
   562  #define CLOSURE_COL_TABLENAME       3
   563  #define CLOSURE_COL_IDCOLUMN        4
   564  #define CLOSURE_COL_PARENTCOLUMN    5
   565    if( rc!=SQLITE_OK ){
   566      closureFree(pNew);
   567    }
   568    *ppVtab = &pNew->base;
   569    return rc;
   570  
   571  closureConnectError:
   572    closureFree(pNew);
   573    return rc;
   574  }
   575  
   576  /*
   577  ** Open a new closure cursor.
   578  */
   579  static int closureOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
   580    closure_vtab *p = (closure_vtab*)pVTab;
   581    closure_cursor *pCur;
   582    pCur = sqlite3_malloc( sizeof(*pCur) );
   583    if( pCur==0 ) return SQLITE_NOMEM;
   584    memset(pCur, 0, sizeof(*pCur));
   585    pCur->pVtab = p;
   586    *ppCursor = &pCur->base;
   587    p->nCursor++;
   588    return SQLITE_OK;
   589  }
   590  
   591  /*
   592  ** Free up all the memory allocated by a cursor.  Set it rLimit to 0
   593  ** to indicate that it is at EOF.
   594  */
   595  static void closureClearCursor(closure_cursor *pCur){
   596    closureAvlDestroy(pCur->pClosure, (void(*)(closure_avl*))sqlite3_free);
   597    sqlite3_free(pCur->zTableName);
   598    sqlite3_free(pCur->zIdColumn);
   599    sqlite3_free(pCur->zParentColumn);
   600    pCur->zTableName = 0;
   601    pCur->zIdColumn = 0;
   602    pCur->zParentColumn = 0;
   603    pCur->pCurrent = 0;
   604    pCur->pClosure = 0;
   605  }
   606  
   607  /*
   608  ** Close a closure cursor.
   609  */
   610  static int closureClose(sqlite3_vtab_cursor *cur){
   611    closure_cursor *pCur = (closure_cursor *)cur;
   612    closureClearCursor(pCur);
   613    pCur->pVtab->nCursor--;
   614    sqlite3_free(pCur);
   615    return SQLITE_OK;
   616  }
   617  
   618  /*
   619  ** Advance a cursor to its next row of output
   620  */
   621  static int closureNext(sqlite3_vtab_cursor *cur){
   622    closure_cursor *pCur = (closure_cursor*)cur;
   623    pCur->pCurrent = closureAvlNext(pCur->pCurrent);
   624    return SQLITE_OK;
   625  }
   626  
   627  /*
   628  ** Allocate and insert a node
   629  */
   630  static int closureInsertNode(
   631    closure_queue *pQueue,  /* Add new node to this queue */
   632    closure_cursor *pCur,   /* The cursor into which to add the node */
   633    sqlite3_int64 id,       /* The node ID */
   634    int iGeneration         /* The generation number for this node */
   635  ){
   636    closure_avl *pNew = sqlite3_malloc( sizeof(*pNew) );
   637    if( pNew==0 ) return SQLITE_NOMEM;
   638    memset(pNew, 0, sizeof(*pNew));
   639    pNew->id = id;
   640    pNew->iGeneration = iGeneration;
   641    closureAvlInsert(&pCur->pClosure, pNew);
   642    queuePush(pQueue, pNew);
   643    return SQLITE_OK;
   644  }
   645  
   646  /*
   647  ** Called to "rewind" a cursor back to the beginning so that
   648  ** it starts its output over again.  Always called at least once
   649  ** prior to any closureColumn, closureRowid, or closureEof call.
   650  **
   651  ** This routine actually computes the closure.
   652  **
   653  ** See the comment at the beginning of closureBestIndex() for a 
   654  ** description of the meaning of idxNum.  The idxStr parameter is
   655  ** not used.
   656  */
   657  static int closureFilter(
   658    sqlite3_vtab_cursor *pVtabCursor, 
   659    int idxNum, const char *idxStr,
   660    int argc, sqlite3_value **argv
   661  ){
   662    closure_cursor *pCur = (closure_cursor *)pVtabCursor;
   663    closure_vtab *pVtab = pCur->pVtab;
   664    sqlite3_int64 iRoot;
   665    int mxGen = 999999999;
   666    char *zSql;
   667    sqlite3_stmt *pStmt;
   668    closure_avl *pAvl;
   669    int rc = SQLITE_OK;
   670    const char *zTableName = pVtab->zTableName;
   671    const char *zIdColumn = pVtab->zIdColumn;
   672    const char *zParentColumn = pVtab->zParentColumn;
   673    closure_queue sQueue;
   674  
   675    (void)idxStr;  /* Unused parameter */
   676    (void)argc;    /* Unused parameter */
   677    closureClearCursor(pCur);
   678    memset(&sQueue, 0, sizeof(sQueue));
   679    if( (idxNum & 1)==0 ){
   680      /* No root=$root in the WHERE clause.  Return an empty set */
   681      return SQLITE_OK;
   682    }
   683    iRoot = sqlite3_value_int64(argv[0]);
   684    if( (idxNum & 0x000f0)!=0 ){
   685      mxGen = sqlite3_value_int(argv[(idxNum>>4)&0x0f]);
   686      if( (idxNum & 0x00002)!=0 ) mxGen--;
   687    }
   688    if( (idxNum & 0x00f00)!=0 ){
   689      zTableName = (const char*)sqlite3_value_text(argv[(idxNum>>8)&0x0f]);
   690      pCur->zTableName = sqlite3_mprintf("%s", zTableName);
   691    }
   692    if( (idxNum & 0x0f000)!=0 ){
   693      zIdColumn = (const char*)sqlite3_value_text(argv[(idxNum>>12)&0x0f]);
   694      pCur->zIdColumn = sqlite3_mprintf("%s", zIdColumn);
   695    }
   696    if( (idxNum & 0x0f0000)!=0 ){
   697      zParentColumn = (const char*)sqlite3_value_text(argv[(idxNum>>16)&0x0f]);
   698      pCur->zParentColumn = sqlite3_mprintf("%s", zParentColumn);
   699    }
   700  
   701    zSql = sqlite3_mprintf(
   702         "SELECT \"%w\".\"%w\" FROM \"%w\" WHERE \"%w\".\"%w\"=?1",
   703         zTableName, zIdColumn, zTableName, zTableName, zParentColumn);
   704    if( zSql==0 ){
   705      return SQLITE_NOMEM;
   706    }else{
   707      rc = sqlite3_prepare_v2(pVtab->db, zSql, -1, &pStmt, 0);
   708      sqlite3_free(zSql);
   709      if( rc ){
   710        sqlite3_free(pVtab->base.zErrMsg);
   711        pVtab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pVtab->db));
   712        return rc;
   713      }
   714    }
   715    if( rc==SQLITE_OK ){
   716      rc = closureInsertNode(&sQueue, pCur, iRoot, 0);
   717    }
   718    while( (pAvl = queuePull(&sQueue))!=0 ){
   719      if( pAvl->iGeneration>=mxGen ) continue;
   720      sqlite3_bind_int64(pStmt, 1, pAvl->id);
   721      while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
   722        if( sqlite3_column_type(pStmt,0)==SQLITE_INTEGER ){
   723          sqlite3_int64 iNew = sqlite3_column_int64(pStmt, 0);
   724          if( closureAvlSearch(pCur->pClosure, iNew)==0 ){
   725            rc = closureInsertNode(&sQueue, pCur, iNew, pAvl->iGeneration+1);
   726          }
   727        }
   728      }
   729      sqlite3_reset(pStmt);
   730    }
   731    sqlite3_finalize(pStmt);
   732    if( rc==SQLITE_OK ){
   733      pCur->pCurrent = closureAvlFirst(pCur->pClosure);
   734    }
   735  
   736    return rc;
   737  }
   738  
   739  /*
   740  ** Only the word and distance columns have values.  All other columns
   741  ** return NULL
   742  */
   743  static int closureColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
   744    closure_cursor *pCur = (closure_cursor*)cur;
   745    switch( i ){
   746      case CLOSURE_COL_ID: {
   747        sqlite3_result_int64(ctx, pCur->pCurrent->id);
   748        break;
   749      }
   750      case CLOSURE_COL_DEPTH: {
   751        sqlite3_result_int(ctx, pCur->pCurrent->iGeneration);
   752        break;
   753      }
   754      case CLOSURE_COL_ROOT: {
   755        sqlite3_result_null(ctx);
   756        break;
   757      }
   758      case CLOSURE_COL_TABLENAME: {
   759        sqlite3_result_text(ctx,
   760           pCur->zTableName ? pCur->zTableName : pCur->pVtab->zTableName,
   761           -1, SQLITE_TRANSIENT);
   762        break;
   763      }
   764      case CLOSURE_COL_IDCOLUMN: {
   765        sqlite3_result_text(ctx,
   766           pCur->zIdColumn ? pCur->zIdColumn : pCur->pVtab->zIdColumn,
   767           -1, SQLITE_TRANSIENT);
   768        break;
   769      }
   770      case CLOSURE_COL_PARENTCOLUMN: {
   771        sqlite3_result_text(ctx,
   772           pCur->zParentColumn ? pCur->zParentColumn : pCur->pVtab->zParentColumn,
   773           -1, SQLITE_TRANSIENT);
   774        break;
   775      }
   776    }
   777    return SQLITE_OK;
   778  }
   779  
   780  /*
   781  ** The rowid.  For the closure table, this is the same as the "id" column.
   782  */
   783  static int closureRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   784    closure_cursor *pCur = (closure_cursor*)cur;
   785    *pRowid = pCur->pCurrent->id;
   786    return SQLITE_OK;
   787  }
   788  
   789  /*
   790  ** EOF indicator
   791  */
   792  static int closureEof(sqlite3_vtab_cursor *cur){
   793    closure_cursor *pCur = (closure_cursor*)cur;
   794    return pCur->pCurrent==0;
   795  }
   796  
   797  /*
   798  ** Search for terms of these forms:
   799  **
   800  **   (A)    root = $root
   801  **   (B1)   depth < $depth
   802  **   (B2)   depth <= $depth
   803  **   (B3)   depth = $depth
   804  **   (C)    tablename = $tablename
   805  **   (D)    idcolumn = $idcolumn
   806  **   (E)    parentcolumn = $parentcolumn
   807  **
   808  ** 
   809  **
   810  **   idxNum       meaning
   811  **   ----------   ------------------------------------------------------
   812  **   0x00000001   Term of the form (A) found
   813  **   0x00000002   The term of bit-2 is like (B1)
   814  **   0x000000f0   Index in filter.argv[] of $depth.  0 if not used.
   815  **   0x00000f00   Index in filter.argv[] of $tablename.  0 if not used.
   816  **   0x0000f000   Index in filter.argv[] of $idcolumn.  0 if not used
   817  **   0x000f0000   Index in filter.argv[] of $parentcolumn.  0 if not used.
   818  **
   819  ** There must be a term of type (A).  If there is not, then the index type
   820  ** is 0 and the query will return an empty set.
   821  */
   822  static int closureBestIndex(
   823    sqlite3_vtab *pTab,             /* The virtual table */
   824    sqlite3_index_info *pIdxInfo    /* Information about the query */
   825  ){
   826    int iPlan = 0;
   827    int i;
   828    int idx = 1;
   829    int seenMatch = 0;
   830    const struct sqlite3_index_constraint *pConstraint;
   831    closure_vtab *pVtab = (closure_vtab*)pTab;
   832    double rCost = 10000000.0;
   833  
   834    pConstraint = pIdxInfo->aConstraint;
   835    for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
   836      if( pConstraint->iColumn==CLOSURE_COL_ROOT
   837       && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
   838        seenMatch = 1;
   839      }
   840      if( pConstraint->usable==0 ) continue;
   841      if( (iPlan & 1)==0 
   842       && pConstraint->iColumn==CLOSURE_COL_ROOT
   843       && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
   844      ){
   845        iPlan |= 1;
   846        pIdxInfo->aConstraintUsage[i].argvIndex = 1;
   847        pIdxInfo->aConstraintUsage[i].omit = 1;
   848        rCost /= 100.0;
   849      }
   850      if( (iPlan & 0x0000f0)==0
   851       && pConstraint->iColumn==CLOSURE_COL_DEPTH
   852       && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
   853             || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE
   854             || pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ)
   855      ){
   856        iPlan |= idx<<4;
   857        pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
   858        if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ) iPlan |= 0x000002;
   859        rCost /= 5.0;
   860      }
   861      if( (iPlan & 0x000f00)==0
   862       && pConstraint->iColumn==CLOSURE_COL_TABLENAME
   863       && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
   864      ){
   865        iPlan |= idx<<8;
   866        pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
   867        pIdxInfo->aConstraintUsage[i].omit = 1;
   868        rCost /= 5.0;
   869      }
   870      if( (iPlan & 0x00f000)==0
   871       && pConstraint->iColumn==CLOSURE_COL_IDCOLUMN
   872       && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
   873      ){
   874        iPlan |= idx<<12;
   875        pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
   876        pIdxInfo->aConstraintUsage[i].omit = 1;
   877      }
   878      if( (iPlan & 0x0f0000)==0
   879       && pConstraint->iColumn==CLOSURE_COL_PARENTCOLUMN
   880       && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
   881      ){
   882        iPlan |= idx<<16;
   883        pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
   884        pIdxInfo->aConstraintUsage[i].omit = 1;
   885      }
   886    }
   887    if( (pVtab->zTableName==0    && (iPlan & 0x000f00)==0)
   888     || (pVtab->zIdColumn==0     && (iPlan & 0x00f000)==0)
   889     || (pVtab->zParentColumn==0 && (iPlan & 0x0f0000)==0)
   890    ){
   891      /* All of tablename, idcolumn, and parentcolumn must be specified
   892      ** in either the CREATE VIRTUAL TABLE or in the WHERE clause constraints
   893      ** or else the result is an empty set. */
   894      iPlan = 0;
   895    }
   896    pIdxInfo->idxNum = iPlan;
   897    if( pIdxInfo->nOrderBy==1
   898     && pIdxInfo->aOrderBy[0].iColumn==CLOSURE_COL_ID
   899     && pIdxInfo->aOrderBy[0].desc==0
   900    ){
   901      pIdxInfo->orderByConsumed = 1;
   902    }
   903    if( seenMatch && (iPlan&1)==0 ) rCost *= 1e30;
   904    pIdxInfo->estimatedCost = rCost;
   905     
   906    return SQLITE_OK;
   907  }
   908  
   909  /*
   910  ** A virtual table module that implements the "transitive_closure".
   911  */
   912  static sqlite3_module closureModule = {
   913    0,                      /* iVersion */
   914    closureConnect,         /* xCreate */
   915    closureConnect,         /* xConnect */
   916    closureBestIndex,       /* xBestIndex */
   917    closureDisconnect,      /* xDisconnect */
   918    closureDisconnect,      /* xDestroy */
   919    closureOpen,            /* xOpen - open a cursor */
   920    closureClose,           /* xClose - close a cursor */
   921    closureFilter,          /* xFilter - configure scan constraints */
   922    closureNext,            /* xNext - advance a cursor */
   923    closureEof,             /* xEof - check for end of scan */
   924    closureColumn,          /* xColumn - read data */
   925    closureRowid,           /* xRowid - read data */
   926    0,                      /* xUpdate */
   927    0,                      /* xBegin */
   928    0,                      /* xSync */
   929    0,                      /* xCommit */
   930    0,                      /* xRollback */
   931    0,                      /* xFindMethod */
   932    0,                      /* xRename */
   933    0,                      /* xSavepoint */
   934    0,                      /* xRelease */
   935    0                       /* xRollbackTo */
   936  };
   937  
   938  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   939  
   940  /*
   941  ** Register the closure virtual table
   942  */
   943  #ifdef _WIN32
   944  __declspec(dllexport)
   945  #endif
   946  int sqlite3_closure_init(
   947    sqlite3 *db, 
   948    char **pzErrMsg, 
   949    const sqlite3_api_routines *pApi
   950  ){
   951    int rc = SQLITE_OK;
   952    SQLITE_EXTENSION_INIT2(pApi);
   953    (void)pzErrMsg;
   954  #ifndef SQLITE_OMIT_VIRTUALTABLE
   955    rc = sqlite3_create_module(db, "transitive_closure", &closureModule, 0);
   956  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   957    return rc;
   958  }