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

Generated on Mon Sep 12 15:26:45 2011 for Veil by  doxygen 1.5.6