veil_interface.c

Go to the documentation of this file.
00001 /**
00002  * @file   veil_interface.c
00003  * \code
00004  *     Author:       Marc Munro
00005  *     Copyright (c) 2005 - 20010 Marc Munro
00006  *     License:      BSD
00007  * $Id: veil_interface.c,v 1.14 2008/08/25 23:46:22 bloodnok Exp $
00008  * \endcode
00009  * @brief  
00010  * Functions providing the SQL interface to veil, and utility functions
00011  * to support them.
00012  */
00013 
00014 #include "postgres.h"
00015 #include "executor/spi.h"
00016 #include "funcapi.h"
00017 #include "utils/hsearch.h"
00018 #include "utils/memutils.h"
00019 
00020 #include "veil_version.h"
00021 #include "veil_funcs.h"
00022 #include "veil_datatypes.h"
00023 
00024 
00025 # if PG_VERSION_GE(8, 2)
00026 PG_MODULE_MAGIC;
00027 # endif
00028 
00029 # if PG_VERSION_GE(8, 3)
00030 #define VEIL_SET_VARSIZE(new_t,t) \
00031   SET_VARSIZE(new_t, t);
00032 #else
00033 #define VEIL_SET_VARSIZE(new_t,t) \
00034   VARATT_SIZEP(new_t) = t;
00035 # endif
00036 
00037 
00038 
00039 // TODO: Check for keylen being exceeded in hash entries.
00040 // TODO: Look for memory leaks, particularly in bitmap hash operations.
00041 // TODO: CONSIDER CHECKING ALL ARGS FOR NULL!
00042 
00043 
00044 /** 
00045  * Create a dynamically allocated C string as a copy of a text value.
00046  * 
00047  * @param in text value from which the copy is made.
00048  * @return Dynamically allocated (by palloc()) copy of in.
00049  */
00050 static char *
00051 strfromtext(text *in)
00052 {
00053     char *out = palloc(VARSIZE(in) - VARHDRSZ + 1);
00054     memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
00055     out[VARSIZE(in) - VARHDRSZ] = '\0';
00056 
00057     return out;
00058 }
00059 
00060 /** 
00061  * Create a dynamically allocated text value as a copy of a C string.
00062  * 
00063  * @param in String to be copied
00064  * @return Dynamically allocated (by palloc()) copy of in.
00065  */
00066 static text *
00067 textfromstr(char *in)
00068 {
00069     int   len = strlen(in);
00070     text *out = palloc(len + VARHDRSZ);
00071     memcpy(VARDATA(out), in, len);
00072     VEIL_SET_VARSIZE(out, (len + VARHDRSZ));
00073 
00074     return out;
00075 }
00076 
00077 /** 
00078  * Create a dynamically allocated text value as a copy of a C string,
00079  * applying a limit to the length.
00080  * 
00081  * @param in String to be copied
00082  * @param limit Maximum length of string to be copied.
00083  * @return Dynamically allocated (by palloc()) copy of in.
00084  */
00085 static text *
00086 textfromstrn(char *in, int limit)
00087 {
00088     int   len = strlen(in);
00089     text *out;
00090 
00091     if (limit < len) {
00092         len = limit;
00093     }
00094 
00095     out = palloc(len + VARHDRSZ);
00096     memcpy(VARDATA(out), in, len);
00097     VEIL_SET_VARSIZE(out, (len + VARHDRSZ));
00098 
00099     return out;
00100 }
00101 
00102 /** 
00103  * Create a dynamically allocated text value as a copy of a C string,
00104  * applying a limit to the length.
00105  * 
00106  * @param str String to be copied
00107  * @return Dynamically allocated (by palloc()) copy of str.
00108  */
00109 static char *
00110 copystr(char *str)
00111 {
00112     char *new = palloc((sizeof(char) * strlen(str) + 1));
00113     strcpy(new, str);
00114     return new;
00115 }
00116 
00117 /** 
00118  * Create a dynamically allocated C string as a copy of an integer value.
00119  * 
00120  * @param val value to be stringified
00121  * @return Dynamically allocated string.
00122  */
00123 static char *
00124 strfromint(int4 val)
00125 {
00126     char *new = palloc((sizeof(char) * 17)); // Large enough for any 32
00127                                              // bit number
00128     sprintf(new, "%d", val);
00129     return new;
00130 }
00131 
00132 /** 
00133  * Create a dynamically allocated C string as a copy of a boolean value.
00134  * 
00135  * @param val value to be stringified
00136  * @return Dynamically allocated string.
00137  */
00138 static char *
00139 strfrombool(bool val)
00140 {
00141     char *new = palloc((sizeof(char) * 2));
00142     if (val) {
00143         strcpy(new, "t");
00144     }
00145     else {
00146         strcpy(new, "f");
00147     }
00148     return new;
00149 }
00150 
00151 /** 
00152  * Perform session initialisation once for the session.  This calls the
00153  * user-defined function veil_init which should create and possibly
00154  * initialise all session and, maybe, shared variables.  This function
00155  * may be safely called any number of times - it will only perform the
00156  * initialisation on the first call.
00157  * 
00158  */
00159 static void
00160 ensure_init()
00161 {
00162     bool  success = false;
00163     TransactionId this_xid;
00164     int   ok;
00165     HTAB *hash;
00166     static bool done = false;
00167     static TransactionId xid = 0;
00168 
00169     if (!done) {
00170         this_xid =  GetCurrentTransactionId();
00171         if (xid == this_xid) {
00172             // We must have been called recursively, so just return
00173             return;
00174         }
00175         xid = this_xid;       // Record our xid in case we recurse
00176         ok = vl_spi_connect();
00177         if (ok != SPI_OK_CONNECT) {
00178             ereport(ERROR,
00179                     (errcode(ERRCODE_INTERNAL_ERROR),
00180                      errmsg("failed to initialise session (1)"),
00181                      errdetail("SPI_connect() failed, returning %d.", ok)));
00182         }
00183 
00184         hash = vl_get_shared_hash();  // Init all shared memory constructs
00185         (void) vl_bool_from_query("select veil_init(FALSE)", &success);
00186 
00187         if (!success) {
00188             ereport(ERROR,
00189                     (errcode(ERRCODE_INTERNAL_ERROR),
00190                      errmsg("failed to initialise session (2)"),
00191                      errdetail("veil_init() did not return true.")));
00192         }
00193         
00194         ok = vl_spi_finish();
00195         if (ok != SPI_OK_FINISH) {
00196             ereport(ERROR,
00197                     (errcode(ERRCODE_INTERNAL_ERROR),
00198                      errmsg("failed to initialise session (3)"),
00199                      errdetail("SPI_finish() failed, returning %d.", ok)));
00200         }
00201         done = true;    // init is done, we don't need to do it again.
00202     }
00203 }
00204 
00205 /** 
00206  * Report, by raising an error, a type mismatch between the expected and
00207  * actual type of a VarEntry variable.
00208  * 
00209  * @param name The name of the variable
00210  * @param expected The expected type.
00211  * @param got The actual type
00212  */
00213 extern void
00214 vl_type_mismatch(char *name,
00215                  ObjType expected,
00216                  ObjType got)
00217 {
00218     ereport(ERROR,
00219             (errcode(ERRCODE_INTERNAL_ERROR),
00220              errmsg("type mismatch in %s: expected %s, got %s",
00221                     name, vl_ObjTypeName(expected), vl_ObjTypeName(got)),
00222              errdetail("Variable %s is not of the expected type.", name)));
00223 }
00224 
00225 /** 
00226  * Return the Int4Var variable matching the name parameter, possibly
00227  * creating the variable.  Raise an error if the named variable already
00228  * exists and is of the wrong type.
00229  * 
00230  * @param name The name of the variable.
00231  * @param create Whether to create the variable if it does not exist.
00232  * @return Pointer to the variable or null if the variable does not
00233  * exist and create was false.
00234  */
00235 static Int4Var *
00236 GetInt4Var(char *name,
00237            bool  create)
00238 {
00239     VarEntry *var;
00240     Int4Var  *i4v;
00241     
00242     var = vl_lookup_variable(name);
00243     i4v = (Int4Var *) var->obj;
00244 
00245     if (i4v) {
00246         if (i4v->type != OBJ_INT4) {
00247             vl_type_mismatch(name, OBJ_INT4, i4v->type);
00248         }
00249     }
00250     else {
00251         if (create) {
00252             var->obj = (Object *) vl_NewInt4(var->shared);
00253             i4v = (Int4Var *) var->obj;
00254         }
00255         else {
00256             vl_type_mismatch(name, OBJ_INT4, OBJ_UNDEFINED);
00257         }
00258     }
00259     return i4v;
00260 }
00261 
00262 /** 
00263  * Return the Range variable matching the name parameter, possibly
00264  * creating the variable.  Raise an error if the named variable already
00265  * exists and is of the wrong type.
00266  * 
00267  * @param name The name of the variable.
00268  * @param create Whether to create the variable if it does not exist.
00269  * @return Pointer to the variable or null if the variable does not
00270  * exist and create was false.
00271  */
00272 static Range *
00273 GetRange(char *name,
00274          bool  create)
00275 {
00276     VarEntry *var;
00277     Range    *range;
00278     
00279     var = vl_lookup_variable(name);
00280     range = (Range *) var->obj;
00281 
00282     if (range) {
00283         if (range->type != OBJ_RANGE) {
00284             vl_type_mismatch(name, OBJ_RANGE, range->type);
00285         }
00286     }
00287     else {
00288         if (create) {
00289             var->obj = (Object *) vl_NewRange(var->shared);
00290             range = (Range *) var->obj;
00291         }
00292         else {
00293             vl_type_mismatch(name, OBJ_RANGE, OBJ_UNDEFINED);
00294         }
00295     }
00296     return range;
00297 }
00298 
00299 /** 
00300  * Return the Bitmap from a bitmap variable.  This function exists
00301  * primarily to perform type checking, and to raise an error if the
00302  * variable is not a bitmap.
00303  * 
00304  * @param var The VarEntry that should contain a bitmap.
00305  * @param allow_empty Whether to raise an error if the variable has not
00306  * yet been initialised.
00307  * @param allow_ref Whether to (not) raise an error if the variable is a
00308  * bitmap_ref rather than a bitmap.
00309  * @return Pointer to the variable or null if the variable is undefined 
00310  * and allow_empty was true.
00311  */
00312 static Bitmap *
00313 GetBitmapFromVar(VarEntry *var,
00314                  bool allow_empty,
00315                  bool allow_ref)
00316 {
00317     Bitmap *bitmap = (Bitmap *) var->obj;
00318 
00319     if (bitmap) {
00320         if (bitmap->type != OBJ_BITMAP) {
00321             if (allow_ref && (bitmap->type == OBJ_BITMAP_REF)) {
00322                 BitmapRef *bmref = (BitmapRef *) bitmap;
00323                 if (bmref->xid == GetCurrentTransactionId()) {
00324                     bitmap = bmref->bitmap;
00325                 }
00326                 else {
00327                     ereport(ERROR,
00328                             (errcode(ERRCODE_INTERNAL_ERROR),
00329                              errmsg("BitmapRef %s is not defined",
00330                                     var->key),
00331                              errhint("Perhaps the name is mis-spelled, or its "
00332                                      "definition is missing from "
00333                                      "veil_init().")));
00334                 }
00335             }
00336             else {
00337                 vl_type_mismatch(var->key, OBJ_BITMAP, bitmap->type);
00338             }
00339         }
00340     }
00341     else {
00342         if (!allow_empty) {
00343             vl_type_mismatch(var->key, OBJ_BITMAP, OBJ_UNDEFINED);
00344         }
00345     }
00346     return bitmap;
00347 }
00348 
00349 /** 
00350  * Return the Bitmap matching the name parameter, possibly creating the
00351  * VarEntry (variable) for it.  Raise an error if the named variable
00352  * already exists and is of the wrong type.
00353  * 
00354  * @param name The name of the variable.
00355  * @param allow_empty Whether to raise an error if the variable has not
00356  * been defined.
00357  * @param allow_ref Whether to (not) raise an error if the variable is a
00358  * bitmap_ref rather than a bitmap.
00359  * @return Pointer to the variable or null if the variable does not
00360  * exist and allow_empty was false.
00361  */
00362 static Bitmap *
00363 GetBitmap(char *name,
00364           bool allow_empty,
00365           bool allow_ref)
00366 {
00367     VarEntry *var;
00368     Bitmap   *bitmap;
00369 
00370     var = vl_lookup_variable(name);
00371     bitmap = GetBitmapFromVar(var, allow_empty, allow_ref);
00372 
00373     return bitmap;
00374 }
00375 
00376 /** 
00377  * Return the BitmapRef from a bitmap ref variable.  This function exists
00378  * primarily to perform type checking, and to raise an error if the
00379  * variable is not a bitmap ref.  Note that BitmapRef variables may not
00380  * be shared as they can contain references to non-shared objects.
00381  * 
00382  * @param var The VarEntry that should contain a bitmap ref.
00383  * @return Pointer to the variable.
00384  */
00385 static BitmapRef *
00386 GetBitmapRefFromVar(VarEntry *var)
00387 {
00388     BitmapRef *bmref = (BitmapRef *) var->obj;
00389 
00390     if (bmref) {
00391         if (bmref->type != OBJ_BITMAP_REF) {
00392             vl_type_mismatch(var->key, OBJ_BITMAP_REF, bmref->type);
00393         }
00394     }
00395     else {
00396         if (var->shared) {
00397             ereport(ERROR,
00398                     (errcode(ERRCODE_INTERNAL_ERROR),
00399                      errmsg("illegal attempt to define shared BitmapRef %s",
00400                             var->key),
00401                      errhint("BitmapRefs may only be defined as session, "
00402                              "not shared, variables.")));
00403         }
00404         /* Create a new bmref (these are always session variables. */
00405         bmref = vl_malloc(sizeof(BitmapRef));
00406         bmref->type = OBJ_BITMAP_REF;
00407         bmref->bitmap = NULL;
00408         var->obj = (Object *) bmref;
00409     }
00410 
00411     return bmref;
00412 }
00413 
00414 /** 
00415  * Return the BitmapRef matching the name parameter, possibly creating the
00416  * VarEntry (variable) for it.  Raise an error if the named variable
00417  * already exists and is of the wrong type.
00418  * 
00419  * @param name The name of the variable.
00420  * @return Pointer to the variable
00421  */
00422 static BitmapRef *
00423 GetBitmapRef(char *name)
00424 {
00425     VarEntry  *var;
00426     BitmapRef *bmref;
00427 
00428     var = vl_lookup_variable(name);
00429     bmref = GetBitmapRefFromVar(var);
00430 
00431     return bmref;
00432 }
00433 
00434 /** 
00435  * Return the BitmapArray from a bitmap array variable.  This function
00436  * exists primarily to perform type checking, and to raise an error if
00437  * the variable is not a bitmap array.
00438  * 
00439  * @param var The VarEntry that should contain a bitmap array.
00440  * @param allow_empty Whether to raise an error if the variable has not
00441  * yet been initialised.
00442  * @return Pointer to the variable or null if the variable is undefined 
00443  * and allow_empty was true.
00444  */
00445 static BitmapArray *
00446 GetBitmapArrayFromVar(VarEntry *var,
00447                       bool allow_empty)
00448 {
00449     BitmapArray *bmarray;
00450     bmarray = (BitmapArray *) var->obj;
00451 
00452     if (bmarray) {
00453         if (bmarray->type != OBJ_BITMAP_ARRAY) {
00454             vl_type_mismatch(var->key, OBJ_BITMAP_ARRAY, bmarray->type);
00455         }
00456     }
00457     else {
00458         if (!allow_empty) {
00459             vl_type_mismatch(var->key, OBJ_BITMAP_ARRAY, OBJ_UNDEFINED);
00460         }
00461     }
00462 
00463     return bmarray;
00464 }
00465 
00466 /** 
00467  * Return the BitmapArray matching the name parameter, possibly creating
00468  * the (VarEntry) variable.  Raise an error if the named variable
00469  * already exists and is of the wrong type.
00470  * 
00471  * @param name The name of the variable.
00472  * @param allow_empty Whether to raise an error if the variable has not
00473  * been defined
00474  * @return Pointer to the variable or null if the variable does not
00475  * exist and create was false.
00476  */
00477 static BitmapArray *
00478 GetBitmapArray(char *name,
00479                bool allow_empty)
00480 {
00481     VarEntry    *var;
00482     BitmapArray *bmarray;
00483 
00484     var = vl_lookup_variable(name);
00485     bmarray = GetBitmapArrayFromVar(var, allow_empty);
00486 
00487     return bmarray;
00488 }
00489 
00490 /** 
00491  * Return the BitmapHash from a bitmap hash variable.  This function
00492  * exists primarily to perform type checking, and to raise an error if
00493  * the variable is not a bitmap hash.
00494  * 
00495  * @param var The VarEntry that should contain a bitmap hash.
00496  * @param allow_empty Whether to raise an error if the variable has not
00497  * yet been initialised.
00498  * @return Pointer to the variable or null if the variable is undefined 
00499  * and allow_empty was true.
00500  */
00501 static BitmapHash *
00502 GetBitmapHashFromVar(VarEntry *var,
00503                       bool allow_empty)
00504 {
00505     BitmapHash *bmhash;
00506     bmhash = (BitmapHash *) var->obj;
00507 
00508     if (bmhash) {
00509         if (bmhash->type != OBJ_BITMAP_HASH) {
00510             vl_type_mismatch(var->key, OBJ_BITMAP_HASH, bmhash->type);
00511         }
00512     }
00513     else {
00514         if (!allow_empty) {
00515             vl_type_mismatch(var->key, OBJ_BITMAP_HASH, OBJ_UNDEFINED);
00516         }
00517     }
00518 
00519     return bmhash;
00520 }
00521 
00522 /** 
00523  * Return the BitmapHash matching the name parameter, possibly creating
00524  * the VarEntry (variable) for it.  Raise an error if the named variable
00525  * already exists and is of the wrong type.
00526  * 
00527  * @param name The name of the variable.
00528  * @param allow_empty Whether to raise an error if the variable has not
00529  * been defined.
00530  * @return Pointer to the variable or null if the variable does not
00531  * exist and create was false.
00532  */
00533 static BitmapHash *
00534 GetBitmapHash(char *name,
00535               bool allow_empty)
00536 {
00537     VarEntry   *var;
00538     BitmapHash *bmhash;
00539     
00540     var = vl_lookup_variable(name);
00541     bmhash = GetBitmapHashFromVar(var, allow_empty);
00542 
00543     return bmhash;
00544 }
00545 
00546 /** 
00547  * Return the Int4Array from an Int4Array variable.  This function
00548  * exists primarily to perform type checking, and to raise an error if
00549  * the variable is not an Int4Array.
00550  * 
00551  * @param var The VarEntry that should contain an Int4Array.
00552  * @param allow_empty Whether to raise an error if the variable has not
00553  * yet been initialised.
00554  * @return Pointer to the variable or null if the variable is undefined 
00555  * and allow_empty was true.
00556  */
00557 static Int4Array *
00558 GetInt4ArrayFromVar(VarEntry *var,
00559                     bool allow_empty)
00560 {
00561     Int4Array *array;
00562     array = (Int4Array *) var->obj;
00563 
00564     if (array) {
00565         if (array->type != OBJ_INT4_ARRAY) {
00566             vl_type_mismatch(var->key, OBJ_INT4_ARRAY, array->type);
00567         }
00568     }
00569     else {
00570         if (!allow_empty) {
00571             vl_type_mismatch(var->key, OBJ_INT4_ARRAY, OBJ_UNDEFINED);
00572         }
00573     }
00574 
00575     return array;
00576 }
00577 
00578 /** 
00579  * Return the Int4Array matching the name parameter, possibly creating
00580  * the VarEntry (variable) for it.  Raise an error if the named variable
00581  * already exists and is of the wrong type.
00582  * 
00583  * @param name The name of the variable.
00584  * @param allow_empty Whether to raise an error if the variable has not
00585  * been defined.
00586  * @return Pointer to the variable or null if the variable does not
00587  * exist and create was false.
00588  */
00589 static Int4Array *
00590 GetInt4Array(char *name,
00591              bool allow_empty)
00592 {
00593     VarEntry  *var;
00594     Int4Array *array;
00595     
00596     var = vl_lookup_variable(name);
00597     array = GetInt4ArrayFromVar(var, allow_empty);
00598 
00599     return array;
00600 }
00601 
00602 PG_FUNCTION_INFO_V1(veil_share);
00603 /** 
00604  * <code>veil_share(text) returns bool</code>
00605  * Define a shared variable returning true if the variable is already
00606  * defined.  If the variable is already defined as a session variable an
00607  * ERROR will be raised.
00608  *
00609  * Session variables are simply defined by their first usage.  Shared
00610  * variables must be defined using this function.  They may then be used
00611  * in exactly the same way as session variables.  Shared variables are
00612  * shared by all backends and so need only be initialised once.  The
00613  * result of this function tells the caller whether the variable needs
00614  * to be initialised.  The caller that first defines a shared variable
00615  * will get a false result and from this will know that the variable
00616  * must be initialised.  All subsequent callers will get a true result
00617  * and so will know that the variable is already initialised.
00618  * 
00619  * @param fcinfo <code>text</code> name of variable.
00620  * @return <code>bool</code> true if the variable already exists
00621  */
00622 Datum
00623 veil_share(PG_FUNCTION_ARGS)
00624 {
00625     char     *name;
00626     VarEntry *var;
00627 
00628     ensure_init();
00629     name = strfromtext(PG_GETARG_TEXT_P(0));
00630 
00631     var = vl_lookup_shared_variable(name);
00632 
00633     PG_RETURN_BOOL((var->obj != NULL));
00634 }
00635 
00636 PG_FUNCTION_INFO_V1(veil_variables);
00637 /** 
00638  * <code>veil_variables() returns setof veil_variable_t</code>
00639  * Return a <code>veil_variable_t</code> record for each defined
00640  * variable.  This includes both session and shared variables.
00641  *
00642  * @param fcinfo None
00643  * @return <code>setof veil_variable_t</code>
00644  */
00645 Datum
00646 veil_variables(PG_FUNCTION_ARGS)
00647 {
00648     TupleDesc tupdesc;
00649     TupleTableSlot *slot;
00650     AttInMetadata *attinmeta;
00651     FuncCallContext *funcctx;
00652 
00653     veil_variable_t *var;
00654     char **values;
00655     HeapTuple tuple;
00656     Datum datum;
00657 
00658     if (SRF_IS_FIRSTCALL())
00659     {
00660         /* Only do this on first call for this result set */
00661         MemoryContext   oldcontext;
00662 
00663         ensure_init();
00664         funcctx = SRF_FIRSTCALL_INIT();
00665         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
00666 
00667         tupdesc = RelationNameGetTupleDesc("veil_variable_t");
00668         slot = TupleDescGetSlot(tupdesc);
00669         funcctx->slot = slot;
00670         attinmeta = TupleDescGetAttInMetadata(tupdesc);
00671         funcctx->attinmeta = attinmeta;
00672 
00673         MemoryContextSwitchTo(oldcontext);
00674         funcctx->user_fctx = NULL;
00675     }
00676     
00677     funcctx = SRF_PERCALL_SETUP();
00678     var = vl_next_variable(funcctx->user_fctx);
00679     funcctx->user_fctx = var;
00680 
00681     if (var) {
00682         values = (char **) palloc(3 * sizeof(char *));
00683         values[0] = copystr(var->name);
00684         values[1] = copystr(var->type);
00685         values[2] = strfrombool(var->shared);
00686 
00687         slot = funcctx->slot;
00688         attinmeta = funcctx->attinmeta;
00689         
00690         tuple = BuildTupleFromCStrings(attinmeta, values);
00691         datum = TupleGetDatum(slot, tuple);
00692         SRF_RETURN_NEXT(funcctx, datum);
00693 
00694     }
00695     else {
00696         SRF_RETURN_DONE(funcctx);
00697     }
00698 }
00699 
00700 
00701 PG_FUNCTION_INFO_V1(veil_init_range);
00702 /** 
00703  * veil_init_range(text, int4, int4) returns int4
00704  * Initialise a Range variable, returning the number of elements in the
00705  * range.  Ranges contain a min value and a max value.  They may be
00706  * examined using the veil_range() function.
00707  *
00708  * @param fcinfo <code>text</code> The name of the variable to
00709  * initialise.
00710  * <br><code>int4</code> The min value of the range.
00711  * <br><code>int4</code> The max value of the range.
00712  * @return <code>int4</code> The size of the range ((max - min) + 1).
00713  */
00714 Datum
00715 veil_init_range(PG_FUNCTION_ARGS)
00716 {
00717     int32     min;
00718     int32     max;
00719     Range    *range;
00720     char     *name;
00721 
00722     ensure_init();
00723     name = strfromtext(PG_GETARG_TEXT_P(0));
00724     min = PG_GETARG_INT32(1);
00725     max = PG_GETARG_INT32(2);
00726 
00727     range = GetRange(name, true);
00728 
00729     range->min = min;
00730     range->max = max;
00731     PG_RETURN_INT32(max + 1 - min);
00732 }
00733 
00734 
00735 /** 
00736  * Create a datum containing the values of a veil_range_t composite
00737  * type.
00738  * 
00739  * @param min Min value of range
00740  * @param max Max value of range
00741  * @return Composite (row) type datum containing the range elements.
00742  */
00743 Datum 
00744 datum_from_range(int32 min, int32 max)
00745 {
00746     static init_done = false;
00747     static TupleDesc tupdesc;
00748     static AttInMetadata *attinmeta;
00749     TupleTableSlot *slot;
00750     HeapTuple tuple;
00751     char **values;
00752 
00753     if (!init_done) {
00754         // Keep all static data in top memory context where it will
00755         // safely remain during the session. 
00756         MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext);
00757         
00758         init_done = true;
00759         tupdesc = RelationNameGetTupleDesc("veil_range_t");
00760         slot = TupleDescGetSlot(tupdesc);
00761         attinmeta = TupleDescGetAttInMetadata(tupdesc);
00762         
00763         MemoryContextSwitchTo(oldcontext);
00764     }
00765 
00766     // Create value strings to be returned to caller.
00767     values = (char **) palloc(2 * sizeof(char *));
00768     values[0] = strfromint(min);
00769     values[1] = strfromint(max);
00770     
00771     tuple = BuildTupleFromCStrings(attinmeta, values);
00772     slot = TupleDescGetSlot(tupdesc);
00773 
00774     /* make the tuple into a datum */
00775     return TupleGetDatum(slot, tuple);
00776 }
00777 
00778 
00779 PG_FUNCTION_INFO_V1(veil_range);
00780 /** 
00781  * <code>veil_range(text) returns veil_range_t</code>
00782  * Return the range (as a SQL veil_range_t composite type) from the
00783  * named variable.
00784  * An Error will be raised if the variable is not defined or is of the
00785  * wrong type.
00786  *
00787  * @param fcinfo <code>text</code> The name of the range variable.
00788  * @return <code>veil_range_t</code>  Composite type containing the min
00789  * and max values from the named variable.
00790  */
00791 Datum
00792 veil_range(PG_FUNCTION_ARGS)
00793 {
00794     char  *name;
00795     Range *range;
00796     Datum  datum;
00797 
00798     ensure_init();
00799 
00800     name = strfromtext(PG_GETARG_TEXT_P(0));
00801     range = GetRange(name, false);
00802     
00803     datum = (datum_from_range(range->min, range->max));
00804 
00805     PG_RETURN_DATUM(datum);
00806 }
00807 
00808 PG_FUNCTION_INFO_V1(veil_init_bitmap);
00809 /** 
00810  * <code>veil_init_bitmap(text, text) returns bool</code>
00811  * Create or re-initialise a Bitmap, for dealing with a named range of
00812  * values.
00813  * An error will be raised if the variable already exists and is not a
00814  * Bitmap.
00815  *
00816  * @param fcinfo <code>text</code> The name of the bitmap to
00817  * create or reset
00818  * <br><code>text</code> The name of a Range variable that defines the
00819  * range of the new bitmap.
00820  * @return <code>bool</code> true
00821  */
00822 Datum
00823 veil_init_bitmap(PG_FUNCTION_ARGS)
00824 {
00825     char     *bitmap_name;
00826     char     *range_name;
00827     Bitmap   *bitmap;
00828     VarEntry *bitmap_var;
00829     Range    *range;
00830 
00831     ensure_init();
00832 
00833     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
00834     bitmap_var = vl_lookup_variable(bitmap_name);
00835     bitmap = GetBitmapFromVar(bitmap_var, true, false);
00836     range_name = strfromtext(PG_GETARG_TEXT_P(1));
00837     range = GetRange(range_name, false);
00838 
00839     vl_NewBitmap(&bitmap, bitmap_var->shared, range->min, range->max);
00840 
00841     bitmap_var->obj = (Object *) bitmap;
00842 
00843     PG_RETURN_BOOL(true);
00844 }
00845 
00846 PG_FUNCTION_INFO_V1(veil_clear_bitmap);
00847 /** 
00848  * <code>veil_clear_bitmap(text) returns bool</code>
00849  * Clear all bits in the specified Bitmap.
00850  * An error will be raised if the variable is not a Bitmap or BitmapRef.
00851  *
00852  * @param fcinfo <code>text</code> The name of the bitmap to
00853  * be cleared.
00854  * @return <code>bool</code> true
00855  */
00856 Datum
00857 veil_clear_bitmap(PG_FUNCTION_ARGS)
00858 {
00859     char     *bitmap_name;
00860     VarEntry *bitmap_var;
00861     Bitmap   *bitmap;
00862 
00863     ensure_init();
00864 
00865     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
00866     bitmap_var = vl_lookup_variable(bitmap_name);
00867     bitmap = GetBitmapFromVar(bitmap_var, false, true);
00868 
00869     vl_ClearBitmap(bitmap);
00870 
00871     PG_RETURN_BOOL(true);
00872 }
00873 
00874 PG_FUNCTION_INFO_V1(veil_bitmap_setbit);
00875 /** 
00876  * <code>veil_bitmap_setbit(int4, text) returns bool</code>
00877  * Set the specified bit in the specified Bitmap.
00878  *
00879  * An error will be raised if the variable is not a Bitmap or BitmapRef.
00880  *
00881  * @param fcinfo <code>int4</code> The bit to be set
00882  * <br><code>text</code> The name of the bitmap variable.
00883  * @return <code>bool</code> true
00884  */
00885 Datum
00886 veil_bitmap_setbit(PG_FUNCTION_ARGS)
00887 {
00888     char   *name;
00889     Bitmap *bitmap;
00890     int32   bit;
00891 
00892     ensure_init();
00893 
00894     name = strfromtext(PG_GETARG_TEXT_P(0));
00895     bit = PG_GETARG_INT32(1);
00896     bitmap = GetBitmap(name, false, true);
00897     vl_BitmapSetbit(bitmap, bit);
00898 
00899     PG_RETURN_BOOL(true);
00900 }
00901 
00902 PG_FUNCTION_INFO_V1(veil_bitmap_clearbit);
00903 /** 
00904  * <code>veil_bitmap_clearbit(int4, text) returns bool</code>
00905  * Clear the specified bit in the specified Bitmap.
00906  *
00907  * An error will be raised if the variable is not a Bitmap or BitmapRef.
00908  *
00909  * @param fcinfo <code>int4</code> The bit to be cleared
00910  * <br><code>text</code> The name of the bitmap variable.
00911  * @return <code>bool</code> true
00912  */
00913 Datum
00914 veil_bitmap_clearbit(PG_FUNCTION_ARGS)
00915 {
00916     char   *name;
00917     Bitmap *bitmap;
00918     int32   bit;
00919 
00920     ensure_init();
00921 
00922     name = strfromtext(PG_GETARG_TEXT_P(0));
00923     bit = PG_GETARG_INT32(1);
00924     bitmap = GetBitmap(name, false, true);
00925     vl_BitmapClearbit(bitmap, bit);
00926 
00927     PG_RETURN_BOOL(true);
00928 }
00929 
00930 PG_FUNCTION_INFO_V1(veil_bitmap_testbit);
00931 /** 
00932  * <code>veil_bitmap_testbit(int4, text) returns bool</code>
00933  * Test the specified bit in the specified Bitmap, returning true if it
00934  * is set.
00935  *
00936  * An error will be raised if the variable is not a Bitmap or BitmapRef.
00937  *
00938  * @param fcinfo <code>int4</code> The bit to be tested.
00939  * <br><code>text</code> The name of the bitmap variable.
00940  * @return <code>bool</code> true if the bit was set
00941  */
00942 Datum
00943 veil_bitmap_testbit(PG_FUNCTION_ARGS)
00944 {
00945     char   *name;
00946     Bitmap *bitmap;
00947     int32   bit;
00948     bool    result;
00949 
00950     ensure_init();
00951 
00952     bit = PG_GETARG_INT32(1);
00953     name = strfromtext(PG_GETARG_TEXT_P(0));
00954     bitmap = GetBitmap(name, false, true);
00955 
00956     result = vl_BitmapTestbit(bitmap, bit);
00957     PG_RETURN_BOOL(result);
00958 }
00959 
00960 
00961 PG_FUNCTION_INFO_V1(veil_bitmap_union);
00962 /** 
00963  * <code>veil_bitmap_union(text, text) returns bool</code>
00964  * Union the bitmap specified in parameter 1 with that in parameter 2,
00965  * with the result in parameter 1.
00966  *
00967  * An error will be raised if the variables are not of type Bitmap or
00968  * BitmapRef.
00969  *
00970  * @param fcinfo <code>text</code> The target bitmap
00971  * <br><code>text</code> The bitmap with which to union the target
00972  * @return <code>bool</code> true 
00973  */
00974 Datum
00975 veil_bitmap_union(PG_FUNCTION_ARGS)
00976 {
00977     char        *bitmap1_name;
00978     char        *bitmap2_name;
00979     Bitmap      *target;
00980     Bitmap      *source;
00981 
00982     ensure_init();
00983 
00984     bitmap1_name = strfromtext(PG_GETARG_TEXT_P(0));
00985     bitmap2_name = strfromtext(PG_GETARG_TEXT_P(1));
00986     target = GetBitmap(bitmap1_name, false, true);
00987     source = GetBitmap(bitmap2_name, false, true);
00988 
00989     vl_BitmapUnion(target, source);
00990 
00991     PG_RETURN_BOOL(true);
00992 }
00993 
00994 
00995 PG_FUNCTION_INFO_V1(veil_bitmap_intersect);
00996 /** 
00997  * <code>veil_bitmap_intersect(text, text) returns bool</code>
00998  * Intersect the bitmap specified in parameter 1 with that in parameter 2,
00999  * with the result in parameter 1.
01000  *
01001  * An error will be raised if the variables are not of type Bitmap or
01002  * BitmapRef.
01003  *
01004  * @param fcinfo <code>text</code> The target bitmap
01005  * <br><code>text</code> The bitmap with which to intersect the target
01006  * @return <code>bool</code> true 
01007  */
01008 Datum
01009 veil_bitmap_intersect(PG_FUNCTION_ARGS)
01010 {
01011     char        *bitmap1_name;
01012     char        *bitmap2_name;
01013     Bitmap      *target;
01014     Bitmap      *source;
01015 
01016     ensure_init();
01017 
01018     bitmap1_name = strfromtext(PG_GETARG_TEXT_P(0));
01019     bitmap2_name = strfromtext(PG_GETARG_TEXT_P(1));
01020     target = GetBitmap(bitmap1_name, false, true);
01021     source = GetBitmap(bitmap2_name, false, true);
01022 
01023     vl_BitmapIntersect(target, source);
01024     PG_RETURN_BOOL(true);
01025 }
01026 
01027 
01028 PG_FUNCTION_INFO_V1(veil_bitmap_bits);
01029 /** 
01030  * <code>veil_bitmap_bits(text)</code> returns setof int4
01031  * Return the set of all bits set in the specified Bitmap or BitmapRef.
01032  *
01033  * @param fcinfo <code>text</code> The name of the bitmap.
01034  * @return <code>setof int4</code>The set of bits that are set in the
01035  * bitmap.
01036  */
01037 Datum
01038 veil_bitmap_bits(PG_FUNCTION_ARGS)
01039 {
01040     struct bitmap_bits_state {
01041         Bitmap *bitmap;
01042         int32   bit;
01043     } *state;
01044     FuncCallContext *funcctx;
01045     MemoryContext    oldcontext;
01046     char  *name;
01047     bool   result;
01048     bool   found;
01049     Datum  datum;
01050     
01051     if (SRF_IS_FIRSTCALL())
01052     {
01053         /* Only do this on first call for this result set */
01054         ensure_init();
01055 
01056         funcctx = SRF_FIRSTCALL_INIT();
01057         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
01058         state = palloc(sizeof(struct bitmap_bits_state));
01059         MemoryContextSwitchTo(oldcontext);
01060 
01061         name = strfromtext(PG_GETARG_TEXT_P(0));
01062         state->bitmap = GetBitmap(name, false, true);
01063 
01064         if (!state->bitmap) {
01065             ereport(ERROR,
01066                     (errcode(ERRCODE_INTERNAL_ERROR),
01067                      errmsg("Bitmap %s is not defined",
01068                             name),
01069                      errhint("Perhaps the name is mis-spelled, or its ",
01070                              "definition is missing from veil_init().")));
01071         }
01072 
01073         state->bit = state->bitmap->bitzero;
01074         funcctx->user_fctx = state;
01075     }
01076     
01077     funcctx = SRF_PERCALL_SETUP();
01078     state = funcctx->user_fctx;
01079     
01080     state->bit = vl_BitmapNextBit(state->bitmap, state->bit, &found);
01081     
01082     if (found) {
01083         datum = Int32GetDatum(state->bit);
01084         state->bit++;
01085         SRF_RETURN_NEXT(funcctx, datum);
01086     }
01087     else {
01088         SRF_RETURN_DONE(funcctx);
01089     }
01090 }
01091 
01092 PG_FUNCTION_INFO_V1(veil_bitmap_range);
01093 /** 
01094  * <code>veil_bitmap_range(text) returns veil_range_t</code>
01095  * Return composite type giving the range of the specified Bitmap or
01096  * BitmapRef.
01097  *
01098  * @param fcinfo <code>text</code> The name of the bitmap.
01099  * @return <code>veil_range_t</code>  Composite type containing the min
01100  * and max values of the bitmap's range
01101  */
01102 Datum
01103 veil_bitmap_range(PG_FUNCTION_ARGS)
01104 {
01105     char   *name;
01106     Bitmap *bitmap;
01107 
01108     ensure_init();
01109 
01110     name = strfromtext(PG_GETARG_TEXT_P(0));
01111     bitmap = GetBitmap(name, false, true);
01112 
01113     if (!bitmap) {
01114         ereport(ERROR,
01115                 (errcode(ERRCODE_INTERNAL_ERROR),
01116                  errmsg("Bitmap %s is not defined",
01117                         name),
01118                  errhint("Perhaps the name is mis-spelled, or its ",
01119                          "definition is missing from veil_init().")));
01120     }
01121 
01122     PG_RETURN_DATUM(datum_from_range(bitmap->bitzero, bitmap->bitmax));
01123 }
01124 
01125 
01126 PG_FUNCTION_INFO_V1(veil_init_bitmap_array);
01127 /** 
01128  * <code>veil_init_bitmap_array(text, text, text) returns bool</code>
01129  * Create or reset a BitmapArray.
01130  * An error will be raised if any parameter is not of the correct type.
01131  *
01132  * @param fcinfo <code>text</code> The name of the bitmap array.
01133  * <br><code>text</code> Name of the Range variable that provides the
01134  * range of the array part of the bitmap array.
01135  * <br><code>text</code> Name of the Range variable that provides the
01136  * range of each bitmap in the array.
01137  * @return <code>bool</code>  True
01138  */
01139 Datum
01140 veil_init_bitmap_array(PG_FUNCTION_ARGS)
01141 {
01142     char        *bmarray_name;
01143     char        *arrayrange_name;
01144     char        *maprange_name;
01145     VarEntry    *bmarray_var;
01146     BitmapArray *bmarray;
01147     Range       *arrayrange;
01148     Range       *maprange;
01149 
01150     ensure_init();
01151 
01152     bmarray_name = strfromtext(PG_GETARG_TEXT_P(0));
01153     bmarray_var = vl_lookup_variable(bmarray_name);
01154     bmarray = GetBitmapArrayFromVar(bmarray_var, true);
01155 
01156     arrayrange_name = strfromtext(PG_GETARG_TEXT_P(1));
01157     arrayrange = GetRange(arrayrange_name, false);
01158     maprange_name = strfromtext(PG_GETARG_TEXT_P(2));
01159     maprange = GetRange(maprange_name, false);
01160 
01161     vl_NewBitmapArray(&bmarray, bmarray_var->shared, 
01162                       arrayrange->min, arrayrange->max,
01163                       maprange->min, maprange->max);
01164 
01165     bmarray_var->obj = (Object *) bmarray;
01166 
01167     PG_RETURN_BOOL(true);
01168 }
01169 
01170 PG_FUNCTION_INFO_V1(veil_clear_bitmap_array);
01171 /** 
01172  * <code>veil_clear_bitmap_array(text) returns bool</code>
01173  * Clear the bits in an existing BitmapArray.
01174  * An error will be raised if the parameter is not of the correct type.
01175  *
01176  * @param fcinfo <code>text</code> The name of the BitmapArray.
01177  * @return <code>bool</code>  True
01178  */
01179 Datum
01180 veil_clear_bitmap_array(PG_FUNCTION_ARGS)
01181 {
01182     char        *bmarray_name;
01183     VarEntry    *bmarray_var;
01184     BitmapArray *bmarray;
01185 
01186     ensure_init();
01187 
01188     bmarray_name = strfromtext(PG_GETARG_TEXT_P(0));
01189     bmarray_var = vl_lookup_variable(bmarray_name);
01190     bmarray = GetBitmapArrayFromVar(bmarray_var, false);
01191 
01192     vl_ClearBitmapArray(bmarray);
01193 
01194     PG_RETURN_BOOL(true);
01195 }
01196 
01197 PG_FUNCTION_INFO_V1(veil_bitmap_from_array);
01198 /** 
01199  * <code>veil_bitmap_from_array(text, text, int4) returns text</code>
01200  * Place a reference to the specified Bitmap from a BitmapArray into
01201  * the specified BitmapRef
01202  * An error will be raised if any parameter is not of the correct type.
01203  *
01204  * @param fcinfo <code>text</code> The name of the BitmapRef into which
01205  * a reference to the relevant Bitmap will be placed.
01206  * <br><code>text</code> Name of the BitmapArray containing the Bitmap
01207  * in which we are interested.
01208  * <br><code>int4</code> Index into the array of the bitmap in question.
01209  * @return <code>text</code>  The name of the BitmapRef
01210  */
01211 Datum
01212 veil_bitmap_from_array(PG_FUNCTION_ARGS)
01213 {
01214     text        *bmref_text;
01215     char        *bmref_name;
01216     BitmapRef   *bmref;
01217     char        *bmarray_name;
01218     VarEntry    *bmarray_var;
01219     BitmapArray *bmarray;
01220     int32        arrayelem;
01221     Bitmap      *bitmap;
01222 
01223     bmref_text = PG_GETARG_TEXT_P(0);
01224     bmref_name = strfromtext(bmref_text);
01225     bmref = GetBitmapRef(bmref_name);
01226 
01227     bmarray_name = strfromtext(PG_GETARG_TEXT_P(1));
01228     bmarray = GetBitmapArray(bmarray_name, false);
01229 
01230     arrayelem = PG_GETARG_INT32(2);
01231     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01232     
01233     bmref->bitmap = bitmap;
01234     bmref->xid = GetCurrentTransactionId();
01235     PG_RETURN_TEXT_P(bmref_text);
01236 }
01237 
01238 PG_FUNCTION_INFO_V1(veil_bitmap_array_testbit);
01239 /** 
01240  * <code>veil_bitmap_array_testbit(text, int4, int4) returns bool</code>
01241  * Test a specified bit within a BitmapArray
01242  *
01243  * An error will be raised if the first parameter is not a BitmapArray.
01244  *
01245  * @param fcinfo <code>text</code> The name of the BitmapArray
01246  * <br><code>int4</code> Index of the Bitmap within the array.
01247  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01248  * @return <code>bool</code>  True if the bit was set, false otherwise.
01249  */
01250 Datum
01251 veil_bitmap_array_testbit(PG_FUNCTION_ARGS)
01252 {
01253     char        *name;
01254     BitmapArray *bmarray;
01255     Bitmap      *bitmap;
01256     int32        arrayelem;
01257     int32        bit;
01258 
01259     ensure_init();
01260 
01261     arrayelem = PG_GETARG_INT32(1);
01262     bit = PG_GETARG_INT32(2);
01263 
01264     name = strfromtext(PG_GETARG_TEXT_P(0));
01265     bmarray = GetBitmapArray(name, false);
01266     
01267     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01268     if (bitmap) {
01269         PG_RETURN_BOOL(vl_BitmapTestbit(bitmap, bit));
01270     }
01271     else {
01272         PG_RETURN_BOOL(false);
01273     }
01274 }
01275 
01276 
01277 PG_FUNCTION_INFO_V1(veil_bitmap_array_setbit);
01278 /** 
01279  * <code>veil_bitmap_array_setbit(text, int4, int4) returns bool</code>
01280  * Set a specified bit within a BitmapArray
01281  *
01282  * An error will be raised if the first parameter is not a BitmapArray.
01283  *
01284  * @param fcinfo <code>text</code> The name of the BitmapArray
01285  * <br><code>int4</code> Index of the Bitmap within the array.
01286  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01287  * @return <code>bool</code>  True
01288  */
01289 Datum
01290 veil_bitmap_array_setbit(PG_FUNCTION_ARGS)
01291 {
01292     char        *name;
01293     BitmapArray *bmarray;
01294     Bitmap      *bitmap;
01295     int32        arrayelem;
01296     int32        bit;
01297 
01298     ensure_init();
01299 
01300     arrayelem = PG_GETARG_INT32(1);
01301     bit = PG_GETARG_INT32(2);
01302     name = strfromtext(PG_GETARG_TEXT_P(0));
01303     bmarray = GetBitmapArray(name, false);
01304 
01305     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01306     if (bitmap) {
01307         vl_BitmapSetbit(bitmap, bit);
01308         PG_RETURN_BOOL(true);
01309     }
01310     else {
01311         ereport(ERROR,
01312                 (errcode(ERRCODE_INTERNAL_ERROR),
01313                  errmsg("Bitmap Array range error (%d not in %d..%d)", 
01314                         arrayelem, bmarray->arrayzero, bmarray->arraymax),
01315                  errdetail("Attempt to reference BitmapArray element "
01316                            "outside of the BitmapArray's defined range")));
01317     }
01318 }
01319 
01320 
01321 PG_FUNCTION_INFO_V1(veil_bitmap_array_clearbit);
01322 /** 
01323  * <code>veil_bitmap_array_clearbit(text, int4, int4) returns bool</code>
01324  * Clear a specified bit within a BitmapArray
01325  *
01326  * An error will be raised if the first parameter is not a BitmapArray.
01327  *
01328  * @param fcinfo <code>text</code> The name of the BitmapArray
01329  * <br><code>int4</code> Index of the Bitmap within the array.
01330  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01331  * @return <code>bool</code>  True
01332  */
01333 Datum
01334 veil_bitmap_array_clearbit(PG_FUNCTION_ARGS)
01335 {
01336     char        *name;
01337     BitmapArray *bmarray;
01338     Bitmap      *bitmap;
01339     int32        arrayelem;
01340     int32        bit;
01341 
01342     ensure_init();
01343 
01344     arrayelem = PG_GETARG_INT32(1);
01345     bit = PG_GETARG_INT32(2);
01346     name = strfromtext(PG_GETARG_TEXT_P(0));
01347     bmarray = GetBitmapArray(name, false);
01348 
01349     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01350     if (bitmap) {
01351         vl_BitmapClearbit(bitmap, bit);
01352         PG_RETURN_BOOL(true);
01353     }
01354     else {
01355         ereport(ERROR,
01356                 (errcode(ERRCODE_INTERNAL_ERROR),
01357                  errmsg("Bitmap Array range error (%d not in %d..%d)", 
01358                         arrayelem, bmarray->arrayzero, bmarray->arraymax),
01359                  errdetail("Attempt to reference BitmapArray element "
01360                            "outside of the BitmapArray's defined range")));
01361     }
01362 }
01363 
01364 
01365 PG_FUNCTION_INFO_V1(veil_union_from_bitmap_array);
01366 /** 
01367  * <code>veil_union_from_bitmap_array(text, text, int4) returns bool</code>
01368  * Union a Bitmap with the specified Bitmap from a BitmapArray with the
01369  * result placed into the first parameter.
01370  *
01371  * An error will be raised if the parameters are not of the correct types.
01372  *
01373  * @param fcinfo <code>text</code> The name of the Bitmap into which the
01374  * resulting union will be placed.
01375  * <br><code>text</code> Name of the BitmapArray
01376  * <br><code>int4</code> Index of the required bitmap in the array
01377  * @return <code>bool</code>  True
01378  */
01379 Datum
01380 veil_union_from_bitmap_array(PG_FUNCTION_ARGS)
01381 {
01382     char        *bitmap_name;
01383     char        *bmarray_name;
01384     Bitmap      *target;
01385     BitmapArray *bmarray;
01386     Bitmap      *bitmap;
01387     int32        arrayelem;
01388 
01389     ensure_init();
01390 
01391     arrayelem = PG_GETARG_INT32(2);
01392 
01393     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
01394     bmarray_name = strfromtext(PG_GETARG_TEXT_P(1));
01395     target = GetBitmap(bitmap_name, false, true);
01396     bmarray = GetBitmapArray(bmarray_name, false);
01397 
01398     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01399     if (bitmap) {
01400         vl_BitmapUnion(target, bitmap);
01401     }
01402     PG_RETURN_BOOL(true);
01403 }
01404 
01405 
01406 PG_FUNCTION_INFO_V1(veil_intersect_from_bitmap_array);
01407 /** 
01408  * <code>veil_intersect_from_bitmap_array(text, text, int4) returns bool</code>
01409  * Intersect a Bitmap with the specified Bitmap from a BitmapArray with the
01410  * result placed into the first parameter.
01411  *
01412  * An error will be raised if the parameters are not of the correct types.
01413  *
01414  * @param fcinfo <code>text</code> The name of the Bitmap into which the
01415  * resulting intersection will be placed.
01416  * <br><code>text</code> Name of the BitmapArray
01417  * <br><code>int4</code> Index of the required bitmap in the array
01418  * @return <code>bool</code>  True
01419  */
01420 Datum
01421 veil_intersect_from_bitmap_array(PG_FUNCTION_ARGS)
01422 {
01423     char        *bitmap_name;
01424     char        *bmarray_name;
01425     Bitmap      *target;
01426     BitmapArray *bmarray;
01427     Bitmap      *bitmap;
01428     int32        arrayelem;
01429 
01430     ensure_init();
01431 
01432     arrayelem = PG_GETARG_INT32(2);
01433 
01434     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
01435     bmarray_name = strfromtext(PG_GETARG_TEXT_P(1));
01436     target = GetBitmap(bitmap_name, false, true);
01437     bmarray = GetBitmapArray(bmarray_name, false);
01438 
01439     bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01440     if (bitmap) {
01441         vl_BitmapIntersect(target, bitmap);
01442     }
01443     PG_RETURN_BOOL(true);
01444 }
01445 
01446 
01447 PG_FUNCTION_INFO_V1(veil_bitmap_array_bits);
01448 /** 
01449  * <code>veil_bitmap_array_bits(text)</code> returns setof int4
01450  * Return the set of all bits set in the specified Bitmap from the
01451  * BitmapArray.
01452  *
01453  * @param fcinfo <code>text</code> The name of the bitmap array.
01454  * <br><code>int4</code> Index of the required bitmap in the array
01455  * @return <code>setof int4</code>The set of bits that are set in the
01456  * bitmap.
01457  */
01458 Datum
01459 veil_bitmap_array_bits(PG_FUNCTION_ARGS)
01460 {
01461     struct bitmap_array_bits_state {
01462         Bitmap *bitmap;
01463         int32   bit;
01464     } *state;
01465     FuncCallContext *funcctx;
01466     MemoryContext    oldcontext;
01467     char   *name;
01468     bool    result;
01469     bool    found;
01470     BitmapArray *bmarray;
01471     int     arrayelem;
01472     Datum   datum;
01473     
01474     if (SRF_IS_FIRSTCALL())
01475     {
01476         /* Only do this on first call for this result set */
01477         ensure_init();
01478         
01479         funcctx = SRF_FIRSTCALL_INIT();
01480         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
01481         state = palloc(sizeof(struct bitmap_array_bits_state));
01482         MemoryContextSwitchTo(oldcontext);
01483 
01484         name = strfromtext(PG_GETARG_TEXT_P(0));
01485         arrayelem = PG_GETARG_INT32(1);
01486         bmarray = GetBitmapArray(name, false);
01487 
01488         if (!bmarray) {
01489             ereport(ERROR,
01490                     (errcode(ERRCODE_INTERNAL_ERROR),
01491                      errmsg("BitmapArray %s is not defined",
01492                             name),
01493                      errhint("Perhaps the name is mis-spelled, or its "
01494                              "definition is missing from "
01495                              "veil_init().")));
01496         }
01497 
01498         state->bitmap = vl_BitmapFromArray(bmarray, arrayelem);
01499         if (!state->bitmap) {
01500             ereport(ERROR,
01501                     (errcode(ERRCODE_INTERNAL_ERROR),
01502                      errmsg("Bitmap Array range error (%d not in %d..%d)", 
01503                             arrayelem, bmarray->arrayzero, bmarray->arraymax),
01504                      errdetail("Attempt to reference BitmapArray element "
01505                                "outside of the BitmapArray's defined range")));
01506         }
01507 
01508         state->bit = state->bitmap->bitzero;
01509         funcctx->user_fctx = state;
01510     }
01511     
01512     funcctx = SRF_PERCALL_SETUP();
01513     state = funcctx->user_fctx;
01514 
01515     state->bit = vl_BitmapNextBit(state->bitmap, state->bit, &found);
01516     
01517     if (found) {
01518         datum = Int32GetDatum(state->bit);
01519         state->bit++;
01520         SRF_RETURN_NEXT(funcctx, datum);
01521     }
01522     else {
01523         SRF_RETURN_DONE(funcctx);
01524     }
01525 }
01526 
01527 PG_FUNCTION_INFO_V1(veil_bitmap_array_arange);
01528 /** 
01529  * <code>veil_bitmap_array_arange(text) returns veil_range_t</code>
01530  * Return composite type giving the range of the array part of the
01531  * specified BitmapArray
01532  *
01533  * @param fcinfo <code>text</code> The name of the bitmap array.
01534  * @return <code>veil_range_t</code>  Composite type containing the min
01535  * and max indices of the array
01536  */
01537 Datum
01538 veil_bitmap_array_arange(PG_FUNCTION_ARGS)
01539 {
01540     char        *name;
01541     BitmapArray *bmarray;
01542 
01543     ensure_init();
01544 
01545     name = strfromtext(PG_GETARG_TEXT_P(0));
01546     bmarray = GetBitmapArray(name, false);
01547 
01548     if (!bmarray) {
01549         ereport(ERROR,
01550                 (errcode(ERRCODE_INTERNAL_ERROR),
01551                  errmsg("BitmapArray %s is not defined",
01552                         name),
01553                  errhint("Perhaps the name is mis-spelled, or its "
01554                          "definition is missing from veil_init().")));
01555     }
01556 
01557     PG_RETURN_DATUM(datum_from_range(bmarray->arrayzero, bmarray->arraymax));
01558 }
01559 
01560 
01561 PG_FUNCTION_INFO_V1(veil_bitmap_array_brange);
01562 /** 
01563  * <code>veil_bitmap_array_brange(text) returns veil_range_t</code>
01564  * Return composite type giving the range of every Bitmap within
01565  * the BitmapArray.
01566  *
01567  * @param fcinfo <code>text</code> The name of the bitmap array.
01568  * @return <code>veil_range_t</code>  Composite type containing the min
01569  * and max values of the bitmap array's range
01570  */
01571 Datum
01572 veil_bitmap_array_brange(PG_FUNCTION_ARGS)
01573 {
01574     char        *name;
01575     BitmapArray *bmarray;
01576 
01577     ensure_init();
01578 
01579     name = strfromtext(PG_GETARG_TEXT_P(0));
01580     bmarray = GetBitmapArray(name, false);
01581 
01582     if (!bmarray) {
01583         ereport(ERROR,
01584                 (errcode(ERRCODE_INTERNAL_ERROR),
01585                  errmsg("BitmapArray %s is not defined",
01586                         name),
01587                  errhint("Perhaps the name is mis-spelled, or its "
01588                          "definition is missing from veil_init().")));
01589     }
01590 
01591     PG_RETURN_DATUM(datum_from_range(bmarray->bitzero, bmarray->bitmax));
01592 }
01593 
01594 
01595 
01596 PG_FUNCTION_INFO_V1(veil_init_bitmap_hash);
01597 /** 
01598  * <code>veil_init_bitmap_hash(text, text) returns bool</code>
01599  * Create or reset a BitmapHash.
01600  * An error will be raised if any parameter is not of the correct type.
01601  *
01602  * @param fcinfo <code>text</code> The name of the bitmap hash.
01603  * <br><code>text</code> Name of the Range variable that provides the
01604  * range of each bitmap in the hash.
01605  * @return <code>bool</code>  True
01606  */
01607 Datum
01608 veil_init_bitmap_hash(PG_FUNCTION_ARGS)
01609 {
01610     char       *bmhash_name;
01611     char       *range_name;
01612     VarEntry   *bmhash_var;
01613     BitmapHash *bmhash;
01614     Range      *range;
01615 
01616     ensure_init();
01617 
01618     bmhash_name = strfromtext(PG_GETARG_TEXT_P(0));
01619     bmhash_var = vl_lookup_variable(bmhash_name);
01620     bmhash = GetBitmapHashFromVar(bmhash_var, true);
01621 
01622     range_name = strfromtext(PG_GETARG_TEXT_P(1));
01623     range = GetRange(range_name, false);
01624 
01625     if (bmhash_var->shared) {
01626         ereport(ERROR,
01627                 (errcode(ERRCODE_INTERNAL_ERROR),
01628                  errmsg("illegal attempt to define shared BitmapHash %s",
01629                         bmhash_name),
01630                  errhint("BitmapHashes may only be defined as session, "
01631                          "not shared, variables.")));
01632     }
01633     vl_NewBitmapHash(&bmhash, bmhash_name,
01634                      range->min, range->max);
01635 
01636     bmhash_var->obj = (Object *) bmhash;
01637 
01638     PG_RETURN_BOOL(true);
01639 }
01640 
01641 
01642 PG_FUNCTION_INFO_V1(veil_clear_bitmap_hash);
01643 /** 
01644  * <code>veil_clear_bitmap_hash(text) returns bool</code>
01645  * Clear the bits in an existing BitmapHash.
01646  * An error will be raised if the parameter is not of the correct type.
01647  *
01648  * @param fcinfo <code>text</code> The name of the BitmapHash.
01649  * @return <code>bool</code>  True
01650  */
01651 Datum
01652 veil_clear_bitmap_hash(PG_FUNCTION_ARGS)
01653 {
01654     char       *bmhash_name;
01655     VarEntry   *bmhash_var;
01656     BitmapHash *bmhash;
01657 
01658     ensure_init();
01659 
01660     bmhash_name = strfromtext(PG_GETARG_TEXT_P(0));
01661     bmhash_var = vl_lookup_variable(bmhash_name);
01662     bmhash = GetBitmapHashFromVar(bmhash_var, true);
01663 
01664     vl_NewBitmapHash(&bmhash, bmhash_name,
01665                      bmhash->bitzero, bmhash->bitmax);
01666 
01667     bmhash_var->obj = (Object *) bmhash;
01668 
01669     PG_RETURN_BOOL(true);
01670 }
01671 
01672 
01673 PG_FUNCTION_INFO_V1(veil_bitmap_hash_key_exists);
01674 /** 
01675  * <code>veil_bitmap_hashkey_exists(text, text) returns text</code>
01676  * Place a reference to the specified Bitmap from a BitmapHash into
01677  * the specified BitmapRef
01678  * An error will be raised if any parameter is not of the correct type.
01679  *
01680  * @param fcinfo <code>text</code> Name of the BitmapHashin which we are
01681  * interested.
01682  * <br><code>text</code> Key, into the hash, of the bitmap in question.
01683  * @return <code>boolean</code>  Whether the key is present in the BitmapHash
01684  */
01685 Datum
01686 veil_bitmap_hash_key_exists(PG_FUNCTION_ARGS)
01687 {
01688     char       *bmhash_name;
01689     VarEntry   *bmhash_var;
01690     BitmapHash *bmhash;
01691     char       *hashelem;
01692     bool        found;
01693 
01694     bmhash_name = strfromtext(PG_GETARG_TEXT_P(0));
01695     bmhash = GetBitmapHash(bmhash_name, false);
01696 
01697     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
01698     
01699     found = vl_BitmapHashHasKey(bmhash, hashelem);
01700     
01701     PG_RETURN_BOOL(found);
01702 }
01703 
01704 PG_FUNCTION_INFO_V1(veil_bitmap_from_hash);
01705 /** 
01706  * <code>veil_bitmap_from_hash(text, text, text) returns text</code>
01707  * Place a reference to the specified Bitmap from a BitmapHash into
01708  * the specified BitmapRef
01709  * An error will be raised if any parameter is not of the correct type.
01710  *
01711  * @param fcinfo <code>text</code> The name of the BitmapRef into which
01712  * a reference to the relevant Bitmap will be placed.
01713  * <br><code>text</code> Name of the BitmapHash containing the Bitmap
01714  * in which we are interested.
01715  * <br><code>text</code> Key, into the hash, of the bitmap in question.
01716  * @return <code>text</code>  The name of the BitmapRef
01717  */
01718 Datum
01719 veil_bitmap_from_hash(PG_FUNCTION_ARGS)
01720 {
01721     text       *bmref_text;
01722     char       *bmref_name;
01723     BitmapRef  *bmref;
01724     char       *bmhash_name;
01725     VarEntry   *bmhash_var;
01726     BitmapHash *bmhash;
01727     char       *hashelem;
01728     Bitmap     *bitmap;
01729 
01730     bmref_text = PG_GETARG_TEXT_P(0);
01731     bmref_name = strfromtext(bmref_text);
01732     bmref = GetBitmapRef(bmref_name);
01733 
01734     bmhash_name = strfromtext(PG_GETARG_TEXT_P(1));
01735     bmhash = GetBitmapHash(bmhash_name, false);
01736 
01737     hashelem = strfromtext(PG_GETARG_TEXT_P(2));
01738     bitmap = vl_AddBitmapToHash(bmhash, hashelem);
01739     
01740     bmref->bitmap = bitmap;
01741     bmref->xid = GetCurrentTransactionId();
01742     PG_RETURN_TEXT_P(bmref_text);
01743 }
01744 
01745 PG_FUNCTION_INFO_V1(veil_bitmap_hash_testbit);
01746 /** 
01747  * <code>veil_bitmap_hash_testbit(text, text, int4) returns bool</code>
01748  * Test a specified bit within a BitmapHash
01749  *
01750  * An error will be raised if the first parameter is not a BitmapHash.
01751  *
01752  * @param fcinfo <code>text</code> The name of the BitmapHash
01753  * <br><code>text</code> Key of the Bitmap within the hash.
01754  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01755  * @return <code>bool</code>  True if the bit was set, false otherwise.
01756  */
01757 Datum
01758 veil_bitmap_hash_testbit(PG_FUNCTION_ARGS)
01759 {
01760     char       *name;
01761     BitmapHash *bmhash;
01762     char       *hashelem;
01763     Bitmap     *bitmap;
01764     int32       bit;
01765 
01766     ensure_init();
01767 
01768     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
01769     bit = PG_GETARG_INT32(2);
01770 
01771     name = strfromtext(PG_GETARG_TEXT_P(0));
01772     bmhash = GetBitmapHash(name, false);
01773     
01774     bitmap = vl_BitmapFromHash(bmhash, hashelem);
01775     if (bitmap) {
01776         PG_RETURN_BOOL(vl_BitmapTestbit(bitmap, bit));
01777     }
01778     else {
01779         PG_RETURN_BOOL(false);
01780     }
01781 }
01782 
01783 PG_FUNCTION_INFO_V1(veil_bitmap_hash_setbit);
01784 /** 
01785  * <code>veil_bitmap_hash_setbit(text, text, int4) returns bool</code>
01786  * Set a specified bit within a BitmapHash
01787  *
01788  * An error will be raised if the first parameter is not a BitmapHash.
01789  *
01790  * @param fcinfo <code>text</code> The name of the BitmapHash
01791  * <br><code>text</code> Key of the Bitmap within the hash.
01792  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01793  * @return <code>bool</code>  True
01794  */
01795 Datum
01796 veil_bitmap_hash_setbit(PG_FUNCTION_ARGS)
01797 {
01798     char       *name;
01799     BitmapHash *bmhash;
01800     Bitmap     *bitmap;
01801     char       *hashelem;
01802     int32       bit;
01803 
01804     ensure_init();
01805 
01806     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
01807     bit = PG_GETARG_INT32(2);
01808     name = strfromtext(PG_GETARG_TEXT_P(0));
01809     bmhash = GetBitmapHash(name, false);
01810 
01811     bitmap = vl_AddBitmapToHash(bmhash, hashelem);
01812 
01813     vl_BitmapSetbit(bitmap, bit);
01814     PG_RETURN_BOOL(true);
01815 }
01816 
01817 
01818 PG_FUNCTION_INFO_V1(veil_bitmap_hash_clearbit);
01819 /** 
01820  * <code>veil_bitmap_hash_clearbit(text, text, int4) returns bool</code>
01821  * Clear a specified bit within a BitmapHash
01822  *
01823  * An error will be raised if the first parameter is not a BitmapHash.
01824  *
01825  * @param fcinfo <code>text</code> The name of the BitmapHash
01826  * <br><code>text</code> Key of the Bitmap within the hash.
01827  * <br><code>int4</code> Bit id of the bit within the Bitmap.
01828  * @return <code>bool</code>  True
01829  */
01830 Datum
01831 veil_bitmap_hash_clearbit(PG_FUNCTION_ARGS)
01832 {
01833     char       *name;
01834     BitmapHash *bmhash;
01835     Bitmap     *bitmap;
01836     char       *hashelem;
01837     int32       bit;
01838 
01839     ensure_init();
01840 
01841     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
01842     bit = PG_GETARG_INT32(2);
01843     name = strfromtext(PG_GETARG_TEXT_P(0));
01844     bmhash = GetBitmapHash(name, false);
01845 
01846     bitmap = vl_AddBitmapToHash(bmhash, hashelem);
01847 
01848     vl_BitmapClearbit(bitmap, bit);
01849     PG_RETURN_BOOL(true);
01850 }
01851 
01852 
01853 PG_FUNCTION_INFO_V1(veil_union_into_bitmap_hash);
01854 /** 
01855  * <code>veil_union_into_bitmap_hash(text, text, text) returns bool</code>
01856  * Union a Bitmap with the specified Bitmap from a BitmapHash with the
01857  * result placed into the bitmap hash.
01858  *
01859  * An error will be raised if the parameters are not of the correct types.
01860  *
01861  * @param fcinfo <code>text</code> Name of the BitmapHash
01862  * <br><code>text</code> Key of the required bitmap in the hash
01863  * <br><code>text</code> The name of the Bitmap into which the
01864  * resulting union will be placed.
01865  * @return <code>bool</code>  True
01866  */
01867 Datum
01868 veil_union_into_bitmap_hash(PG_FUNCTION_ARGS)
01869 {
01870     char       *bitmap_name;
01871     char       *bmhash_name;
01872     Bitmap     *target;
01873     BitmapHash *bmhash;
01874     Bitmap     *bitmap;
01875     char       *hashelem;
01876 
01877     ensure_init();
01878 
01879     bmhash_name = strfromtext(PG_GETARG_TEXT_P(0));
01880     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
01881 
01882     bitmap_name = strfromtext(PG_GETARG_TEXT_P(2));
01883     bitmap = GetBitmap(bitmap_name, false, true);
01884     bmhash = GetBitmapHash(bmhash_name, false);
01885 
01886     target = vl_AddBitmapToHash(bmhash, hashelem);
01887     if (target) {
01888         vl_BitmapUnion(target, bitmap);
01889     }
01890     PG_RETURN_BOOL(true);
01891 }
01892 
01893 PG_FUNCTION_INFO_V1(veil_union_from_bitmap_hash);
01894 /** 
01895  * <code>veil_union_from_bitmap_hash(text, text, text) returns bool</code>
01896  * Union a Bitmap with the specified Bitmap from a BitmapHash with the
01897  * result placed into the bitmap parameter.
01898  *
01899  * An error will be raised if the parameters are not of the correct types.
01900  *
01901  * @param fcinfo <code>text</code> The name of the Bitmap into which the
01902  * resulting union will be placed.
01903  * <br><code>text</code> Name of the BitmapHash
01904  * <br><code>text</code> Key of the required bitmap in the hash
01905  * @return <code>bool</code>  True
01906  */
01907 Datum
01908 veil_union_from_bitmap_hash(PG_FUNCTION_ARGS)
01909 {
01910     char       *bitmap_name;
01911     char       *bmhash_name;
01912     Bitmap     *target;
01913     BitmapHash *bmhash;
01914     Bitmap     *bitmap;
01915     char       *hashelem;
01916 
01917     ensure_init();
01918 
01919     hashelem = strfromtext(PG_GETARG_TEXT_P(2));
01920 
01921     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
01922     bmhash_name = strfromtext(PG_GETARG_TEXT_P(1));
01923     target = GetBitmap(bitmap_name, false, true);
01924     bmhash = GetBitmapHash(bmhash_name, false);
01925 
01926     bitmap = vl_BitmapFromHash(bmhash, hashelem);
01927     if (bitmap) {
01928         vl_BitmapUnion(target, bitmap);
01929     }
01930     PG_RETURN_BOOL(true);
01931 }
01932 
01933 PG_FUNCTION_INFO_V1(veil_intersect_from_bitmap_hash);
01934 /** 
01935  * <code>veil_intersect_from_bitmap_hash(text, text, text) returns bool</code>
01936  * Intersect a Bitmap with the specified Bitmap from a BitmapArray with the
01937  * result placed into the bitmap parameter.
01938  *
01939  * An error will be raised if the parameters are not of the correct types.
01940  *
01941  * @param fcinfo <code>text</code> The name of the Bitmap into which the
01942  * resulting intersection will be placed.
01943  * <br><code>text</code> Name of the BitmapHash
01944  * <br><code>text</code> Key of the required bitmap in the hash
01945  * @return <code>bool</code>  True
01946  */
01947 Datum
01948 veil_intersect_from_bitmap_hash(PG_FUNCTION_ARGS)
01949 {
01950     char       *bitmap_name;
01951     char       *bmhash_name;
01952     Bitmap     *target;
01953     BitmapHash *bmhash;
01954     Bitmap     *bitmap;
01955     char       *hashelem;
01956 
01957     ensure_init();
01958 
01959     hashelem = strfromtext(PG_GETARG_TEXT_P(2));
01960 
01961     bitmap_name = strfromtext(PG_GETARG_TEXT_P(0));
01962     bmhash_name = strfromtext(PG_GETARG_TEXT_P(1));
01963     target = GetBitmap(bitmap_name, false, true);
01964     bmhash = GetBitmapHash(bmhash_name, false);
01965 
01966     bitmap = vl_BitmapFromHash(bmhash, hashelem);
01967     if (bitmap) {
01968         vl_BitmapIntersect(target, bitmap);
01969     }
01970     else {
01971         // The bitmap from the hash does not exist, so it is logically
01972         // empty.  Intersection with an empty set yields an empty set.
01973         vl_ClearBitmap(target);
01974     }
01975     PG_RETURN_BOOL(true);
01976 }
01977 
01978 PG_FUNCTION_INFO_V1(veil_bitmap_hash_bits);
01979 /** 
01980  * <code>veil_bitmap_hash_bits(text)</code> returns setof int4
01981  * Return the set of all bits set in the specified Bitmap from the
01982  * BitmapHash.
01983  *
01984  * @param fcinfo <code>text</code> The name of the bitmap hash.
01985  * <br><code>text</code> Key of the required bitmap in the hash
01986  * @return <code>setof int4</code>The set of bits that are set in the
01987  * bitmap.
01988  */
01989 Datum
01990 veil_bitmap_hash_bits(PG_FUNCTION_ARGS)
01991 {
01992     struct bitmap_hash_bits_state {
01993         Bitmap *bitmap;
01994         int32   bit;
01995     } *state;
01996     FuncCallContext *funcctx;
01997     MemoryContext    oldcontext;
01998     char   *name;
01999     bool    result;
02000     bool    found;
02001     BitmapHash *bmhash;
02002     char   *hashelem;
02003     Datum   datum;
02004     
02005     if (SRF_IS_FIRSTCALL())
02006     {
02007         /* Only do this on first call for this result set */
02008         ensure_init();
02009         
02010         funcctx = SRF_FIRSTCALL_INIT();
02011         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
02012         state = palloc(sizeof(struct bitmap_hash_bits_state));
02013         MemoryContextSwitchTo(oldcontext);
02014 
02015         name = strfromtext(PG_GETARG_TEXT_P(0));
02016         hashelem = strfromtext(PG_GETARG_TEXT_P(1));
02017         bmhash = GetBitmapHash(name, false);
02018 
02019         if (!bmhash) {
02020             ereport(ERROR,
02021                     (errcode(ERRCODE_INTERNAL_ERROR),
02022                      errmsg("Bitmap Hash %s not defined", name)));
02023         }
02024 
02025         state->bitmap = vl_BitmapFromHash(bmhash, hashelem);
02026         if (!state->bitmap) {
02027             SRF_RETURN_DONE(funcctx);
02028         }
02029 
02030         state->bit = state->bitmap->bitzero;
02031         funcctx->user_fctx = state;
02032     }
02033     
02034     funcctx = SRF_PERCALL_SETUP();
02035     state = funcctx->user_fctx;
02036 
02037     state->bit = vl_BitmapNextBit(state->bitmap, state->bit, &found);
02038     
02039     if (found) {
02040         datum = Int32GetDatum(state->bit);
02041         state->bit++;
02042         SRF_RETURN_NEXT(funcctx, datum);
02043     }
02044     else {
02045         SRF_RETURN_DONE(funcctx);
02046     }
02047 }
02048 
02049 PG_FUNCTION_INFO_V1(veil_bitmap_hash_range);
02050 /** 
02051  * <code>veil_bitmap_hash_range(text) returns veil_range_t</code>
02052  * Return composite type giving the range of every Bitmap within
02053  * the BitmapHash.
02054  *
02055  * @param fcinfo <code>text</code> The name of the bitmap array.
02056  * @return <code>veil_range_t</code>  Composite type containing the min
02057  * and max values of the bitmap hash's range
02058  */
02059 Datum
02060 veil_bitmap_hash_range(PG_FUNCTION_ARGS)
02061 {
02062     char       *name;
02063     BitmapHash *bmhash;
02064 
02065     ensure_init();
02066 
02067     name = strfromtext(PG_GETARG_TEXT_P(0));
02068     bmhash = GetBitmapHash(name, false);
02069 
02070     if (!bmhash) {
02071         ereport(ERROR,
02072                 (errcode(ERRCODE_INTERNAL_ERROR),
02073                  errmsg("Bitmap Hash %s not defined", name)));
02074     }
02075 
02076     PG_RETURN_DATUM(datum_from_range(bmhash->bitzero, bmhash->bitmax));
02077 }
02078 
02079 
02080 PG_FUNCTION_INFO_V1(veil_bitmap_hash_entries);
02081 /** 
02082  * <code>veil_bitmap_hash_entries(text) returns setof text</code>
02083  * Return  the key of every Bitmap within the BitmapHash.
02084  *
02085  * @param fcinfo <code>text</code> The name of the bitmap hash.
02086  * @return <code>setof text</code>  Every key in the hash.
02087  */
02088 Datum
02089 veil_bitmap_hash_entries(PG_FUNCTION_ARGS)
02090 {
02091     struct bitmap_hash_entries_state {
02092         BitmapHash *bmhash;
02093         VarEntry   *var;
02094     } *state;
02095     FuncCallContext *funcctx;
02096     MemoryContext    oldcontext;
02097     char  *name;
02098     char  *hashelem;
02099     Datum  datum;
02100     text  *result;
02101 
02102     if (SRF_IS_FIRSTCALL())
02103     {
02104         /* Only do this on first call for this result set */
02105         ensure_init();
02106         
02107         funcctx = SRF_FIRSTCALL_INIT();
02108         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
02109         state = palloc(sizeof(struct bitmap_hash_entries_state));
02110         MemoryContextSwitchTo(oldcontext);
02111 
02112         name = strfromtext(PG_GETARG_TEXT_P(0));
02113         state->bmhash = GetBitmapHash(name, false);
02114 
02115         if (!state->bmhash) {
02116             ereport(ERROR,
02117                     (errcode(ERRCODE_INTERNAL_ERROR),
02118                      errmsg("Bitmap Hash %s not defined", name)));
02119         }
02120 
02121         state->var = NULL;
02122         funcctx->user_fctx = state;
02123     }
02124 
02125     funcctx = SRF_PERCALL_SETUP();
02126     state = funcctx->user_fctx;
02127 
02128     state->var = vl_NextHashEntry(state->bmhash->hash, state->var);
02129 
02130     if (state->var) {
02131         result = textfromstrn(state->var->key, HASH_KEYLEN);
02132         datum = PointerGetDatum(result);
02133         SRF_RETURN_NEXT(funcctx, datum);
02134     }
02135     else {
02136         SRF_RETURN_DONE(funcctx);
02137     }
02138 }
02139 
02140 
02141 PG_FUNCTION_INFO_V1(veil_bitmap_hash_defined);
02142 /** 
02143  * <code>veil_bitmap_hash_defined(text, text) returns bool</code>
02144  * Return true if the key exists in the bitmap hash.
02145  *
02146  * @param fcinfo <code>text</code> The name of the bitmap hash.
02147  * <br><code>text</code> Key of the required bitmap in the hash
02148  * @return <code>bool</code>  True if key is defined in the hash
02149  */
02150 Datum
02151 veil_bitmap_hash_defined(PG_FUNCTION_ARGS)
02152 {
02153     char       *bmhash_name;
02154     BitmapHash *bmhash;
02155     char       *hashelem;
02156     Bitmap     *bitmap;
02157 
02158     ensure_init();
02159 
02160 
02161     bmhash_name = strfromtext(PG_GETARG_TEXT_P(0));
02162     hashelem = strfromtext(PG_GETARG_TEXT_P(1));
02163     bmhash = GetBitmapHash(bmhash_name, false);
02164 
02165     bitmap = vl_BitmapFromHash(bmhash, hashelem);
02166     PG_RETURN_BOOL(bitmap != NULL);
02167 }
02168 
02169 
02170 PG_FUNCTION_INFO_V1(veil_int4_set);
02171 /** 
02172  * <code>veil_int4_set(text, int4) returns int4</code>
02173  * Set an Int4Var variable type to a specified value.
02174  * An Error will be raised if the variable is not defined or is of the
02175  * wrong type.
02176  *
02177  * @param fcinfo <code>text</code> The name of the int4 variable.
02178  * @param fcinfo <code>int4</code> The value to be set (may be null).
02179  * @return <code>int4</code>  The new value of the variable.
02180  */
02181 Datum
02182 veil_int4_set(PG_FUNCTION_ARGS)
02183 {
02184     char     *name;
02185     Int4Var  *var;
02186     int32     value;
02187 
02188     ensure_init();
02189 
02190     if (PG_ARGISNULL(0)) {
02191         PG_RETURN_NULL();
02192     }
02193 
02194     name = strfromtext(PG_GETARG_TEXT_P(0));
02195     var = GetInt4Var(name, true);
02196 
02197     if (PG_ARGISNULL(1)) {
02198         var->isnull = true;
02199         PG_RETURN_NULL();
02200     }
02201     else {
02202         value = PG_GETARG_INT32(1);
02203         var->isnull = false;
02204         var->value = value;
02205         PG_RETURN_INT32(value);
02206     }
02207 }
02208 
02209 PG_FUNCTION_INFO_V1(veil_int4_get);
02210 /** 
02211  * <code>veil_int4_get(text) returns int4</code>
02212  * Return the value of an Int4Var variable.
02213  * An Error will be raised if the variable is not defined or is of the
02214  * wrong type.
02215  *
02216  * @param fcinfo <code>text</code> The name of the int4 variable.
02217  * @return <code>int4</code>  The value of the variable.
02218  */
02219 Datum
02220 veil_int4_get(PG_FUNCTION_ARGS)
02221 {
02222     char        *name;
02223     Int4Var     *var;
02224     int32        value;
02225 
02226     ensure_init();
02227 
02228     name = strfromtext(PG_GETARG_TEXT_P(0));
02229     var = GetInt4Var(name, true);
02230 
02231     if (var->isnull) {
02232         PG_RETURN_NULL();
02233     }
02234     else {
02235         PG_RETURN_INT32(var->value);
02236     }
02237 }
02238 
02239 PG_FUNCTION_INFO_V1(veil_init_int4array);
02240 /** 
02241  * <code>veil_init_int4array(text, text) returns bool</code>
02242  * Initialise an Int4Array variable.  Each entry in the array will be
02243  * zeroed.
02244  *
02245  * @param fcinfo <code>text</code> The name of the Int4Array variable.
02246  * <br><code>text</code> Name of the range variable defining the size of
02247  * the array.
02248  * @return <code>bool</code>  True
02249  */
02250 Datum
02251 veil_init_int4array(PG_FUNCTION_ARGS)
02252 {
02253     char      *array_name;
02254     char      *range_name;
02255     VarEntry  *array_var;
02256     VarEntry  *range_var;
02257     Int4Array *array;
02258     Range     *range;
02259 
02260     ensure_init();
02261 
02262     array_name = strfromtext(PG_GETARG_TEXT_P(0));
02263     array_var = vl_lookup_variable(array_name);
02264     array = GetInt4ArrayFromVar(array_var, true);
02265 
02266     range_name = strfromtext(PG_GETARG_TEXT_P(1));
02267     range = GetRange(range_name, false);
02268 
02269     array = vl_NewInt4Array(array, array_var->shared, range->min, range->max);
02270     array_var->obj = (Object *) array;
02271 
02272     PG_RETURN_BOOL(true);
02273 }
02274 
02275 PG_FUNCTION_INFO_V1(veil_clear_int4array);
02276 /** 
02277  * <code>veil_clear_int4array(text) returns bool</code>
02278  * Clear an Int4Array variable.  Each entry in the array will be
02279  * zeroed.
02280  *
02281  * @param fcinfo <code>text</code> The name of the Int4Array variable.
02282  * @return <code>bool</code>  True
02283  */
02284 Datum
02285 veil_clear_int4array(PG_FUNCTION_ARGS)
02286 {
02287     char      *array_name;
02288     Int4Array *array;
02289 
02290     ensure_init();
02291 
02292     array_name = strfromtext(PG_GETARG_TEXT_P(0));
02293     array = GetInt4Array(array_name, false);
02294 
02295     vl_ClearInt4Array(array);
02296 
02297     PG_RETURN_BOOL(true);
02298 }
02299 
02300 PG_FUNCTION_INFO_V1(veil_int4array_set);
02301 /** 
02302  * <code>veil_int4array_set(text, int4, int4) returns int4</code>
02303  * Set an Int4Array entry. 
02304  *
02305  * @param fcinfo <code>text</code> The name of the Int4Array variable.
02306  * <br><code>int4</code> Index of the entry to be set
02307  * <br><code>int4</code> Value to which the entry will be set
02308  * @return <code>int4</code> The new value of the array entry
02309  */
02310 Datum
02311 veil_int4array_set(PG_FUNCTION_ARGS)
02312 {
02313     char      *array_name;
02314     Int4Array *array;
02315     int32      idx;
02316     int32      value;
02317 
02318     ensure_init();
02319 
02320     array_name = strfromtext(PG_GETARG_TEXT_P(0));
02321     array = GetInt4Array(array_name, false);
02322     idx = PG_GETARG_INT32(1);
02323     value = PG_GETARG_INT32(2);
02324     vl_Int4ArraySet(array, idx, value);
02325 
02326     PG_RETURN_INT32(value);
02327 }
02328 
02329 PG_FUNCTION_INFO_V1(veil_int4array_get);
02330 /** 
02331  * <code>veil_int4array_get(text, int4) returns int4</code>
02332  * Get an Int4Array entry. 
02333  *
02334  * @param fcinfo <code>text</code> The name of the Int4Array variable.
02335  * <br><code>int4</code> Index of the entry to be retrieved
02336  * @return <code>int4</code> The value of the array entry
02337  */
02338 Datum
02339 veil_int4array_get(PG_FUNCTION_ARGS)
02340 {
02341     char      *array_name;
02342     Int4Array *array;
02343     int32      idx;
02344     int32      value;
02345 
02346     ensure_init();
02347 
02348     array_name = strfromtext(PG_GETARG_TEXT_P(0));
02349     array = GetInt4Array(array_name, false);
02350     idx = PG_GETARG_INT32(1);
02351     value = vl_Int4ArrayGet(array, idx);
02352 
02353     PG_RETURN_INT32(value);
02354 }
02355 
02356 
02357 PG_FUNCTION_INFO_V1(veil_init);
02358 /** 
02359  * <code>veil_init(bool) returns bool</code>
02360  * Initialise or reset a veil session.
02361  * The boolean parameter will be false when called for initialisation,
02362  * and true when performing a reset.
02363  *
02364  * This function must be redefined as a custom function in your
02365  * implementation. 
02366  *
02367  * @param fcinfo <code>bool</code> Whether we are being called in order
02368  * to reset (true) the session or (false) simply to initialise it.
02369  * @return <code>bool</code> True
02370  */
02371 Datum
02372 veil_init(PG_FUNCTION_ARGS)
02373 {
02374     ereport(ERROR,
02375             (errcode(ERRCODE_INTERNAL_ERROR),
02376              errmsg("default veil version of veil_init() has been called"),
02377              errhint("You must define your own version of this function.")));
02378 
02379     PG_RETURN_BOOL(true);
02380 }
02381 
02382 PG_FUNCTION_INFO_V1(veil_perform_reset);
02383 /** 
02384  * <code>veil_perform_reset() returns bool</code>
02385  * Reset veil shared memory for this database.  This creates a new
02386  * shared memory context with none of the existing shared variables.
02387  * All current transactions will be able to continue using the current
02388  * variables, all new transactions will see the new set, once this
02389  * function has completed.
02390  *
02391  * @param fcinfo 
02392  * @return <code>bool</code> True if the function is able to complete
02393  * successfully.  If it is unable, no harm will have been done but
02394  * neither will a memory reset have been performed.
02395  */
02396 Datum
02397 veil_perform_reset(PG_FUNCTION_ARGS)
02398 {
02399     bool success = true;
02400     bool result;
02401     int  ok;
02402 
02403     ensure_init();
02404     ok = vl_spi_connect();
02405     if (ok != SPI_OK_CONNECT) {
02406         ereport(ERROR,
02407                 (errcode(ERRCODE_INTERNAL_ERROR),
02408                  errmsg("failed to perform reset"),
02409                  errdetail("SPI_connect() failed, returning %d.", ok)));
02410     }
02411 
02412     success = vl_prepare_context_switch();  
02413     if (success) {
02414         result = vl_bool_from_query("select veil_init(TRUE)", &success);
02415         elog(NOTICE, "veil_init returns %s to veil_perform_reset", 
02416              result? "true": "false");
02417         success = vl_complete_context_switch();
02418         elog(NOTICE, 
02419              "vl_complete_context_switch returns %s to veil_perform_reset", 
02420              success? "true": "false");
02421         success &= result;
02422     }
02423     else {
02424         ereport(WARNING,
02425                 (errcode(ERRCODE_INTERNAL_ERROR),
02426                  errmsg("failed to perform reset"),
02427                  errdetail("Unable to prepare for memory reset.  "
02428                            "Maybe another process is performing a reset, "
02429                            "or maybe there is a long-running transaction that "
02430                            "is still using the previous memory context.")));
02431     }
02432 
02433     ok = vl_spi_finish();
02434     PG_RETURN_BOOL(success);
02435 }
02436 
02437 PG_FUNCTION_INFO_V1(veil_force_reset);
02438 /** 
02439  * <code>veil_force_reset() returns bool</code>
02440  * Reset veil shared memory for this database, ignoring existing
02441  * transactions.  This function will always reset the shared memory
02442  * context, even for sessions that are still using it.  Having taken
02443  * this drastic action, it will then cause a panic to reset the server.
02444  *
02445  * Question - won't a panic reset the shared memory in any case?  Is the
02446  * panic superfluous, or maybe is this entire function superfluous?
02447  *
02448  * @param fcinfo 
02449  * @return <code>bool</code> True.
02450  */
02451 Datum
02452 veil_force_reset(PG_FUNCTION_ARGS)
02453 {
02454     ensure_init();
02455     vl_force_context_switch();
02456     PG_RETURN_BOOL(true);
02457 }
02458 
02459 
02460 PG_FUNCTION_INFO_V1(veil_version);
02461 /** 
02462  * <code>veil_version() returns text</code>
02463  * Return a string describing this version of veil.
02464  *
02465  * @param fcinfo 
02466  * @return <code>text</code> String describing the version.
02467  */
02468 Datum
02469 veil_version(PG_FUNCTION_ARGS)
02470 {
02471     char *version_str;
02472     text *version_text;
02473     
02474     version_str = palloc(sizeof(char) * strlen(VEIL_VERSION) + 
02475                          strlen(VEIL_VERSION_INFO) + 4);
02476     sprintf(version_str, "%s (%s)", VEIL_VERSION, VEIL_VERSION_INFO);
02477 
02478     version_text = textfromstr(version_str);
02479     PG_RETURN_TEXT_P(version_text);
02480 }
02481 
02482 PG_FUNCTION_INFO_V1(veil_serialise);
02483 /** 
02484  * <code>veil_serialise(text) returns text</code>
02485  * Return a string describing this version of veil.
02486  *
02487  * @param fcinfo 
02488  * <br><code>text</code> Name of the variable to be serialised.
02489  * @return <code>text</code> String containing the serialised variable.
02490  */
02491 Datum
02492 veil_serialise(PG_FUNCTION_ARGS)
02493 {
02494     char  *name;
02495     char  *result;
02496 
02497     ensure_init();
02498 
02499     if (PG_ARGISNULL(0)) {
02500         PG_RETURN_NULL();
02501     }
02502 
02503     name = strfromtext(PG_GETARG_TEXT_P(0));
02504     result = vl_serialise_var(name);
02505 
02506     if (result) {
02507         PG_RETURN_TEXT_P(textfromstr(result));
02508     }
02509     else {
02510         PG_RETURN_NULL();
02511     }
02512 }
02513 
02514 
02515 PG_FUNCTION_INFO_V1(veil_deserialise);
02516 /** 
02517  * <code>veil_deserialise(text) returns text</code>
02518  * Create or reset variables based on the output of previous
02519  * veil_serialise calls.
02520  *
02521  * @param fcinfo 
02522  * <br><code>text</code> Serialised variables string
02523  * @return <code>int4</code> Count of the items de-serialised from
02524  * the string.
02525  */
02526 Datum
02527 veil_deserialise(PG_FUNCTION_ARGS)
02528 {
02529     char  *stream;
02530     int4   result;
02531     text  *txt;
02532 
02533     ensure_init();
02534 
02535     if (PG_ARGISNULL(0)) {
02536         PG_RETURN_NULL();
02537     }
02538 
02539     txt = PG_GETARG_TEXT_P(0);
02540     stream = strfromtext(txt);
02541     result = vl_deserialise(&stream);
02542 
02543     PG_RETURN_INT32(result);
02544 }
02545 
02546 

Generated on Fri Mar 12 08:38:37 2010 for Veil by  doxygen 1.5.6