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

Generated on Tue Mar 11 10:20:03 2008 for Veil by  doxygen 1.5.4