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

Generated on Tue Jul 31 15:35:52 2007 for Veil by  doxygen 1.5.2