From: Marc Munro Date: Thu, 11 Aug 2011 23:00:44 +0000 (-0700) Subject: Final fixups for a 9.1 release. Much improved docs, and sql comments. X-Git-Url: http://git.postgresql.org/gitweb/edit?a=commitdiff_plain;h=a3d22e61f3f80b87c06456f3b80783ea8dbdc9a6;p=veil.git Final fixups for a 9.1 release. Much improved docs, and sql comments. --- diff --git a/GNUmakefile b/GNUmakefile index 64064b9..9dc4d26 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -17,15 +17,16 @@ BUILD_DIR = $(shell pwd) MODULE_big = veil OBJS = $(SOURCES:%.c=%.o) DEPS = $(SOURCES:%.c=%.d) -EXTRA_CLEAN = $(SRC_CLEAN) EXTENSION=veil -MODULEDIR=extension/veil +MODULEDIR=extension VEIL_VERSION = $(shell \ grep default_version veil.control | sed 's/[^0-9.]*\([0-9.]*\).*/\1/') VEIL_CONTROL = veil--$(VEIL_VERSION).sql +VEIL_DEMO_CONTROL = veil_demo--$(VEIL_VERSION).sql SUBDIRS = src regress docs demo +EXTRA_CLEAN = $(SRC_CLEAN) $(VEIL_CONTROL) $(VEIL_DEMO_CONTROL) include $(SUBDIRS:%=%/Makefile) @@ -39,6 +40,9 @@ endif PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) + +override CFLAGS := $(CFLAGS) -O0 + include $(DEPS) # Build per-source dependency files for inclusion diff --git a/demo/Makefile b/demo/Makefile index 01d5004..610619f 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -35,4 +35,11 @@ demo/veil_demo.png: demo/veil_demo.xml demo_clean: rm -f $(DEMO_GARBAGE) $(DEMO_DIR)/demo_build.log +$(VEIL_DEMO_CONTROL): demo/veil_demo.sqs + @echo Creating $(VEIL_DEMO_CONTROL) + @cp $< $@ + +all: $(VEIL_DEMO_CONTROL) + + demo_distclean: demo_clean diff --git a/regress/regress.log b/regress/regress.log index 6335aff..e2ab8ac 100644 --- a/regress/regress.log +++ b/regress/regress.log @@ -1,5 +1,4 @@ - Creating regression test objects... -- Loading the veil extension... NOTICE: extension "veil" does not exist, skipping DROP EXTENSION CREATE EXTENSION @@ -49,10 +48,10 @@ TEST 1.1 ~ #1 *| *VEIL_SHMEMCTL#Initial variable listing - NOTE Test 1.1 will fail (correctly) if this is not a freshly created database - TEST 1.2 = #42#create session int4 - 42 + 42 TEST 1.3 = #42#retrieve session int4 - 42 + 42 TEST 1.4 ~ #sess_int4 *\| *Int4 *\| *f#list defined variables VEIL_SHMEMCTL | ShmemCtl | t @@ -77,13 +76,13 @@ TEST 1.8 ~ #ERROR.*mismatch#access non-existant session range ERROR: type mismatch in sess_range: expected Range, got Undefined DETAIL: Variable sess_range is not of the expected type. TEST 1.9 = #14#create session range - 14 + 14 PREP f TEST 1.10 = #1#create shared ranged - 1 + 1 TEST 1.11 ~ #5 *| *3#list defined variables 5 | 3 @@ -109,16 +108,16 @@ TEST 1.17 ~ #range error#attempt to set arrary element out of range ERROR: Int4ArraySet range error DETAIL: Index (12) not in range 17..17. TEST 1.18 = #14#set int4 array element - 14 + 14 TEST 1.19 = #14#fetch int4 array element - 14 + 14 PREP t TEST 1.20 = #0#clear array and fetch element - 0 + 0 PREP f @@ -126,21 +125,21 @@ PREP t TEST 1.21 = #14#define and fetch from shared int4 array - 14 + 14 TEST 1.22 = #14#shared int4 array get - 14 + 14 PREP - 14 + 14 t t - 24 + 24 - 11 + 11 - - ...test set 1a: variables (second process)... @@ -156,11 +155,11 @@ TEST 1.25 = #0#Before de-serialising session variables 0 PREP - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 TEST 1.25 = #5#Checking session variables are de-serialised 5 @@ -169,6 +168,9 @@ TEST 1.26 ~ #17 *| *17#Checking Range of range variable 17 | 17 TEST 1.27 ~ #11 *| *24#Checking Range of range2 variable + 11 | 24 + +TEST 1.28 = #24#Checking array2 variable(1) Performing regression tests... NOTICE: veil_init returns true to veil_perform_reset NOTICE: vl_complete_context_switch returns true to veil_perform_reset @@ -186,14 +188,14 @@ PASS END TEST 1.1 TEST 1.2 = #42#create session int4 - 42 + 42 MATCH = "42" PASS END TEST 1.2 TEST 1.3 = #42#retrieve session int4 - 42 + 42 MATCH = "42" PASS @@ -242,7 +244,7 @@ PASS END TEST 1.8 TEST 1.9 = #14#create session range - 14 + 14 MATCH = "14" PASS @@ -251,7 +253,7 @@ END TEST 1.9 f TEST 1.10 = #1#create shared ranged - 1 + 1 MATCH = "1" PASS @@ -307,14 +309,14 @@ PASS END TEST 1.17 TEST 1.18 = #14#set int4 array element - 14 + 14 MATCH = "14" PASS END TEST 1.18 TEST 1.19 = #14#fetch int4 array element - 14 + 14 MATCH = "14" PASS @@ -323,7 +325,7 @@ END TEST 1.19 t TEST 1.20 = #0#clear array and fetch element - 0 + 0 MATCH = "0" PASS @@ -334,28 +336,28 @@ END TEST 1.20 t TEST 1.21 = #14#define and fetch from shared int4 array - 14 + 14 MATCH = "14" PASS END TEST 1.21 TEST 1.22 = #14#shared int4 array get - 14 + 14 MATCH = "14" PASS END TEST 1.22 - 14 + 14 t t - 24 + 24 - 11 + 11 TEST 1.23 ~ #4 *| *4#list all shared variables 4 | 4 @@ -378,11 +380,11 @@ MATCH = "0" PASS END TEST 1.25 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 TEST 1.25 = #5#Checking session variables are de-serialised 5 @@ -398,27 +400,31 @@ MATCH ~ "17 | 17" PASS END TEST 1.26 -TEST 1.27 ~ #11 *| *24#Checking Ran 11 | 24 +TEST 1.27 ~ #11 *| *24#Checking Range of range2 variable + 11 | 24 +MATCH ~ "11 | 24" -TEST 1.28 = #24#Checking array2 variable(1) - 24 +PASS +END TEST 1.27 + +TEST 1.28 = 24 TEST 1.29 = #11#Checking array2 variable(2) - 11 + 11 TEST 1.30 = #0#Checking array2 variable(3) - 0 + 0 - ...test set 2: bitmaps... PREP - 70 + 70 - 2 + 2 f TEST 2.1 ~ #OK#Initialise shared and session bitmaps - OK | t | t + OK | t | t TEST 2.2 = #3#Populate shared bitmap 3 @@ -446,9 +452,9 @@ TEST 2.9 ~ #3.*|.*20070#Test bitmap bits 3 | 20070 TEST 2.10 = #20070#Further test bitmap bits - 20001 - 20002 - 20070 + 20001 + 20002 + 20070 - - ...test set 2a: bitmaps (second process)... @@ -456,40 +462,41 @@ PREP t TEST 2.11 != #20070#Check that shared bitmap has bit cleared - 20001 - 20002 + 20001 + 20002 TEST 2.12 = #2#Check that shared bitmap has other bits still set 2 PREP - 1 + 1 TEST 2.13 = #t#Test for known true values in serialised session bitmap t PREP - t | t | t + t | t | t - t | t | t | t + t | t | t | t - t | t + t | t TEST 2.13 ~ #20001 *| *20003 *| *3#Check union of bitmaps 20001 | 20003 | 3 PREP - t | t + t | t TEST 2.14 ~ #20002 *| *20002 *| *1#Check bitmap intersection - 20002 | 20002 | 1 - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select min(veil.bitmap_bits), max(veil.bitmap_bits), count(*... + ^ - - ...test set 3: bitmap arrays... PREP - 2 + 2 - 70 + 70 TEST 3.1 = #t#Create bitmap array t @@ -524,7 +531,7 @@ HINT: Perhaps the name is mis-spelled, or its definition is missing from veil_i PREP session_bitmap_ref - t | t + t | t TEST 3.10 ~ #2 *| *20001 *| *20003#Add bits thru ref, check bits in array 2 | 20001 | 20003 @@ -545,59 +552,44 @@ PREP t TEST 3.12 ~ #1 *| *20003 *| *20003#Intersect thru ref, check bits in array - 1 | 20003 | 20003 - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma... + ^ PREP TEST 3.13 ~ #10001.*10002#Check array range 10001 | 10002 TEST 3.14 ~ #20001.*20070#Check bitmaps range - 20001 | 20070 - -PREP - f - - t - - session_bitmap_ref - -ge of range2 variable - 11 | 24 -MATCH ~ "11 | 24" - -PASS -END TEST 1.27 - -TEST 1.28 = #24#Checking array2 variable(1) - 24 +#24#Checking array2 variable(1) + 24 MATCH = "24" PASS END TEST 1.28 TEST 1.29 = #11#Checking array2 variable(2) - 11 + 11 MATCH = "11" PASS END TEST 1.29 TEST 1.30 = #0#Checking array2 variable(3) - 0 + 0 MATCH = "0" PASS END TEST 1.30 - 70 + 70 - 2 + 2 f TEST 2.1 ~ #OK#Initialise shared and session bitmaps - OK | t | t -MATCH ~ "OK | t | t" + OK | t | t +MATCH ~ "OK | t | t" PASS END TEST 2.1 @@ -659,9 +651,9 @@ PASS END TEST 2.9 TEST 2.10 = #20070#Further test bitmap bits - 20001 - 20002 - 20070 + 20001 + 20002 + 20070 MATCH = "20070" PASS @@ -670,8 +662,8 @@ END TEST 2.10 t TEST 2.11 != #20070#Check that shared bitmap has bit cleared - 20001 - 20002 + 20001 + 20002 PASS END TEST 2.11 @@ -683,7 +675,7 @@ MATCH = "2" PASS END TEST 2.12 - 1 + 1 TEST 2.13 = #t#Test for known true values in serialised session bitmap t @@ -692,11 +684,11 @@ MATCH = "t" PASS END TEST 2.13 - t | t | t + t | t | t - t | t | t | t + t | t | t | t - t | t + t | t TEST 2.13 ~ #20001 *| *20003 *| *3#Check union of bitmaps 20001 | 20003 | 3 @@ -705,18 +697,19 @@ MATCH ~ "20001 | 20003 | 3" PASS END TEST 2.13 - t | t + t | t TEST 2.14 ~ #20002 *| *20002 *| *1#Check bitmap intersection - 20002 | 20002 | 1 -MATCH ~ "20002 | 20002 | 1" - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select min(veil.bitmap_bits), max(veil.bitmap_bits), count(*... +MATCH ~ "LINE 1: select min(veil.bitmap_bits), max(veil.bitmap_bits), count(*..." + ^ PASS END TEST 2.14 - 2 + 2 - 70 + 70 TEST 3.1 = #t#Create bitmap array t @@ -785,7 +778,7 @@ END TEST 3.9 session_bitmap_ref - t | t + t | t TEST 3.10 ~ #2 *| *20001 *| *20003#Add bits thru ref, check bits in array 2 | 20001 | 20003 @@ -812,39 +805,34 @@ END TEST 3.11 t TEST 3.12 ~ #1 *| *20003 *| *20003#Intersect thru ref, check bits in array - 1 | 20003 | 20003 -MATCH ~ "1 | 20003 | 20003" - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma... +MATCH ~ "LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma..." + ^ PASS END TEST 3.12 TEST 3.13 ~ #10001.*10002#Check array range 10001 | 10002 -MATCH ~ "10001 | 10002" - -PASS -END TEST 3.13 - -TEST 3.14 ~ #20001.*20070#Check bitmaps range - 20001 | 20070 -MATCH ~ "20001 | 20070" - -PASS -END TEST 3.14 +MATCH ~ "10001 | 1000 20001 | 20070 +PREP f t - session_bitmap_ t + session_bitmap_ref + + t - - ...test set 3a: bitmap arrays (second process)... TEST 3.15 ~ #1 *| *20003 *| *20003#Check bits in shared bitmap array - 1 | 20003 | 20003 - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma... + ^ PREP - 1 + 1 TEST 3.16 ~ #10001.*10002#Check array range after de-serialisation 10001 | 10002 @@ -858,7 +846,7 @@ TEST 3.18 ~ #1 *\| *20003 *\| *20003#Check bits in array after de-ser. - - ...test set 4: bitmap hashes... PREP - 70 + 70 TEST 4.1 = #t#Create session bitmap hash t @@ -894,7 +882,7 @@ HINT: Perhaps the name is mis-spelled, or its definition is missing from veil_i PREP session_bitmap_ref - t | t + t | t TEST 4.10 ~ #2 *| *20001 *| *20003#Test bits after setting them 2 | 20001 | 20003 @@ -916,8 +904,9 @@ PREP t TEST 4.12 ~ #1 *| *20003 *| *20003#Intersect and test bits - 1 | 20003 | 20003 - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_hash_bits), max(veil.bitmap... + ^ TEST 4.13 ~ #wibble#Test bitmap hash entry (a) wibble rubble @@ -950,7 +939,7 @@ TEST 4.19 ~ #falsex#Check for undefined bitmap in hash falsex PREP - 1 + 1 TEST 4.20 = #t#Check a bit in the deserialised bitmap hash t @@ -961,37 +950,39 @@ TEST 4.21 ~ #1 *| *20003 *| *20003#Count those bits - - ...test set 5: control functions... PREP IGNORE -- Loading the veil extension... -TEST 5.1 ~ #ERROR.*veil_init#Default init -ERROR: default veil version of veil_init() has been called -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(FALSE)" -PREP -TEST 5.2 = #10#Demo init - 10 +TEST 5.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" +2" -PREP -TEST 5.3 = #t#Reset once -NOTICE: veil_init returns true to veil_perform_reset -NOTICE: vl_complete_context_switch returns true to veil_perform_reset - t +PASS +END TEST 3.13 -TEST 5.4 = #1#Check variables after reset - 1 +TEST 3.14 ~ #20001.*20070#Check bitmaps range + 20001 | 20070 +MATCH ~ "20001 | 20070" -TEST 5.5 = #t#Reset again -ref +PASS +END TEST 3.14 + + f t -TEST 3.15 ~ #1 *| *20003 *| *20003#Check bits in shared bitmap array - 1 | 20003 | 20003 -MATCH ~ "1 | 20003 | 20003" + session_bitmap_ref + t + +TEST 3.15 ~ #1 *| *20003 *| *20003#Check bits in shared bitmap array +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma... +MATCH ~ "LINE 1: select count(*), min(veil.bitmap_array_bits), max(veil.bitma..." + ^ PASS END TEST 3.15 - 1 + 1 TEST 3.16 ~ #10001.*10002#Check array range after de-serialisation 10001 | 10002 @@ -1014,7 +1005,7 @@ MATCH ~ "1 | 20003 | 20003" PASS END TEST 3.18 - 70 + 70 TEST 4.1 = #t#Create session bitmap hash t @@ -1083,7 +1074,7 @@ END TEST 4.9 session_bitmap_ref - t | t + t | t TEST 4.10 ~ #2 *| *20001 *| *20003#Test bits after setting them 2 | 20001 | 20003 @@ -1111,9 +1102,10 @@ END TEST 4.11 t TEST 4.12 ~ #1 *| *20003 *| *20003#Intersect and test bits - 1 | 20003 | 20003 -MATCH ~ "1 | 20003 | 20003" - +ERROR: missing FROM-clause entry for table "veil" +LINE 1: select count(*), min(veil.bitmap_hash_bits), max(veil.bitmap... +MATCH ~ "LINE 1: select count(*), min(veil.bitmap_hash_bits), max(veil.bitmap..." + ^ PASS END TEST 4.12 @@ -1174,7 +1166,7 @@ MATCH ~ "falsex" PASS END TEST 4.19 - 1 + 1 TEST 4.20 = #t#Check a bit in the deserialised bitmap hash t @@ -1190,35 +1182,23 @@ MATCH ~ "1 | 20001 | 20001" PASS END TEST 4.21 -TEST 5.1 ~ #ERROR.*veil_init#Default init -ERROR: default veil version of veil_init() has been called -MATCH ~ "ERROR: default veil version of veil_init() has been called" -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(FALSE)" -PASS -END TEST 5.1 - +TEST 5.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +MATCH ~ "ERROR: No user defPREP TEST 5.2 = #10#Demo init - 10 -MATCH = "10" - -PASS -END TEST 5.2 + 10 +PREP TEST 5.3 = #t#Reset once NOTICE: veil_init returns true to veil_perform_reset NOTICE: vl_complete_context_switch returns true to veil_perform_reset t -MATCH = "t" - -PASS -END TEST 5.3 TEST 5.4 = #1#Check variables after reset 1 -MATCH = "1" -PNOTICE: veil_init returns true to veil_perform_reset +TEST 5.5 = #t#Reset again +NOTICE: veil_init returns true to veil_perform_reset NOTICE: vl_complete_context_switch returns true to veil_perform_reset t @@ -1226,11 +1206,10 @@ TEST 5.6 = #2#Check variables again 2 PREP IGNORE -- Loading the veil extension... -TEST 5.7 ~ #ERROR.*veil_init#Reset with failing veil_init -ERROR: default veil version of veil_init() has been called -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(TRUE)" +TEST 5.7 ~ #ERROR.*veil init#Reset with failing veil_init +ERROR: No user defined veil init functions found +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(TRUE)" TEST 5.8 ~ #^ *f *$#Failing reset (context switch was left incomplete) WARNING: failed to perform reset DETAIL: Unable to prepare for memory reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. @@ -1241,6 +1220,8 @@ WARNING: failed to perform reset DETAIL: Unable to prepare for memory reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. f +PREP IGNORE +ERROR: could not access file "@LIBPATH@": No such file or directory TEST 5.10 ~ #^ *t *$#Force reset t @@ -1253,7 +1234,7 @@ NOTICE: vl_complete_context_switch returns true to veil_perform_reset PREP f - 100 + 100 t @@ -1338,7 +1319,7 @@ DETAIL: Unable to prepare for memory reset. Maybe another process is performin f PREP - 100 + 100 t @@ -1389,21 +1370,33 @@ TEST 5.21 = #15#Bitmap variable from other session with bits 15 TEST 5.22 = #t#Successful reset - 15 +ined veil init functions found" +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" +PASS +END TEST 5.1 + +TEST 5.2 = #10#Demo init + 10 +MATCH = "10" +PASS +END TEST 5.2 + +TEST 5.3 = #t#Reset once NOTICE: veil_init returns true to veil_perform_reset NOTICE: vl_complete_context_switch returns true to veil_perform_reset t +MATCH = "t" -TEST 5.23 ~ #ERROR.*Undefined#No bitmap variable from other session - f +PASS +END TEST 5.3 -ERROR: type mismatch in bitmap_x: expected Bitmap, got Undefined -DETAIL: Variable bitmap_x is not of the expected type. -TEST 5.24 = #f#Failed reset as session still in use -WARNING: failed to perform reset -DETAIL: Unable to prepare for memory reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. -ASS +TEST 5.4 = #1#Check variables after reset + 1 +MATCH = "1" + +PASS END TEST 5.4 TEST 5.5 = #t#Reset again @@ -1422,11 +1415,11 @@ MATCH = "2" PASS END TEST 5.6 -TEST 5.7 ~ #ERROR.*veil_init#Reset with failing veil_init -ERROR: default veil version of veil_init() has been called -MATCH ~ "ERROR: default veil version of veil_init() has been called" -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(TRUE)" +TEST 5.7 ~ #ERROR.*veil init#Reset with failing veil_init +ERROR: No user defined veil init functions found +MATCH ~ "ERROR: No user defined veil init functions found" +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(TRUE)" PASS END TEST 5.7 @@ -1448,6 +1441,7 @@ DETAIL: Unable to prepare for memory reset. Maybe another process is performin PASS END TEST 5.9 +ERROR: could not access file "@LIBPATH@": No such file or directory TEST 5.10 ~ #^ *t *$#Force reset t MATCH ~ "t" @@ -1466,7 +1460,7 @@ END TEST 5.11 f - 100 + 100 t @@ -1572,7 +1566,7 @@ DETAIL: Unable to prepare for memory reset. Maybe another process is performin PASS END TEST 5.17 - 100 + 100 t @@ -1628,32 +1622,21 @@ TEST 5.21 = #15#Bitmap variable from other session with bits 15 MATCH = "15" -PASS -END TEST 5.21 - -TEST 5.22 = #t#Successful reset 15 NOTICE: veil_init returns true to veil_perform_reset NOTICE: vl_complete_context_switch returns true to veil_perform_reset t -MATCH = "t" - -PASS -END TEST 5.22 TEST 5.23 ~ #ERROR.*Undefined#No bitmap variable from other session f ERROR: type mismatch in bitmap_x: expected Bitmap, got Undefined -MATCH ~ "ERROR: type mismatch in bitmap_x: expected Bitmap, got Undefined" DETAIL: Variable bitmap_x is not of the expected type. -PASS -END TEST 5.23 - TEST 5.24 = #f#Failed reset as session still in use WARNING: failed to perform reset -DETAIL: Unable to prepare for memo f +DETAIL: Unable to prepare for memory reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. + f TEST 5.25 ~ #WARNING.*reset#Failed reset as session still in use (again) WARNING: failed to perform reset @@ -1661,7 +1644,7 @@ DETAIL: Unable to prepare for memory reset. Maybe another process is performin f PREP - 100 + 100 t @@ -1728,11 +1711,10 @@ TEST 5.99 = #24#New bitmap created by other session - - ...test set 6: veil_init() doing something useful... PREP IGNORE -- Loading the veil extension... -TEST 6.1 ~ #ERROR.*veil_init#Default init -ERROR: default veil version of veil_init() has been called -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(FALSE)" +TEST 6.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" PREP IGNORE t @@ -1762,17 +1744,71 @@ TEST 6.5 ~ #shared1.*Int4.*t#Defined shared variable shared2 | Undefined | t - -- ...test set 7: veil_init() triggering SPI bug... +- ...test set 7: veil_demo... PREP IGNORE -ERROR: database "regressdb2" does not exist -- Loading the veil extension... -NOTICE: extension "veil" does not exist, skipping -ERROR: language "plpgsql" already exists -TEST 7.1 = #9#Test for SPI bug - 9 +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to function veil.veil_init1(boolean) +drop cascades to function veil.veil_init2(boolean) +TEST 7.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" +TEST 7.2 ~ #10#veil_demo init + 10 + +TEST 7.3 ~ #0#Not connected + 0 + +TEST 7.4 ~ #t#connect_person + t + +TEST 7.5 ~ #1#non-privileged access + 1 +PREP IGNORE + t + +TEST 7.6 ~ #6#privileged access + 6 + +PREP IGNORE + f + +TEST 7.7 ~ #0#Disconnect + 0 + +PREP IGNORE +TEST 7.8 ~ #ERROR.*veil init#Drop veil_demo (default init) +ERROR: No user defined veil init functions found +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(TRUE)" COMPLETE -ry reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. +PASS +END TEST 5.21 + +TEST 5.22 = #t#Successful reset + 15 + +NOTICE: veil_init returns true to veil_perform_reset +NOTICE: vl_complete_context_switch returns true to veil_perform_reset + t +MATCH = "t" + +PASS +END TEST 5.22 + +TEST 5.23 ~ #ERROR.*Undefined#No bitmap variable from other session + f + +ERROR: type mismatch in bitmap_x: expected Bitmap, got Undefined +MATCH ~ "ERROR: type mismatch in bitmap_x: expected Bitmap, got Undefined" +DETAIL: Variable bitmap_x is not of the expected type. +PASS +END TEST 5.23 + +TEST 5.24 = #f#Failed reset as session still in use +WARNING: failed to perform reset +DETAIL: Unable to prepare for memory reset. Maybe another process is performing a reset, or maybe there is a long-running transaction that is still using the previous memory context. f MATCH = "f" @@ -1788,7 +1824,7 @@ DETAIL: Unable to prepare for memory reset. Maybe another process is performin PASS END TEST 5.25 - 100 + 100 t @@ -1859,11 +1895,11 @@ MATCH = "24" PASS END TEST 5.99 -TEST 6.1 ~ #ERROR.*veil_init#Default init -ERROR: default veil version of veil_init() has been called -MATCH ~ "ERROR: default veil version of veil_init() has been called" -HINT: You must define your own version of this function. -CONTEXT: SQL statement "select veil_init(FALSE)" +TEST 6.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +MATCH ~ "ERROR: No user defined veil init functions found" +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" PASS END TEST 6.1 @@ -1909,20 +1945,75 @@ MATCH ~ "shared1 | Int4 | t" PASS END TEST 6.5 -ERROR: database "regressdb2" does not exist -NOTICE: extension "veil" does not exist, skipping -ERROR: language "plpgsql" already exists -TEST 7.1 = #9#Test for SPI bug - 9 -MATCH = "9" +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to function veil.veil_init1(boolean) +drop cascades to function veil.veil_init2(boolean) +TEST 7.1 ~ #ERROR.*veil init#Default init +ERROR: No user defined veil init functions found +MATCH ~ "ERROR: No user defined veil init functions found" +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(FALSE)" +PASS +END TEST 7.1 + +TEST 7.2 ~ #10#veil_demo init + 10 +MATCH ~ "10" +PASS +END TEST 7.2 + +TEST 7.3 ~ #0#Not connected + 0 +MATCH ~ "0" + +PASS +END TEST 7.3 + +TEST 7.4 ~ #t#connect_person + t +MATCH ~ "t" + +PASS +END TEST 7.4 + +TEST 7.5 ~ #1#non-privileged access + 1 +MATCH ~ "1" + +PASS +END TEST 7.5 + + t + +TEST 7.6 ~ #6#privileged access + 6 +MATCH ~ "6" + +PASS +END TEST 7.6 + + f + +TEST 7.7 ~ #0#Disconnect + 0 +MATCH ~ "0" + +PASS +END TEST 7.7 + +TEST 7.8 ~ #ERROR.*veil init#Drop veil_demo (default init) +ERROR: No user defined veil init functions found +MATCH ~ "ERROR: No user defined veil init functions found" +HINT: You must refefine veil.veil_init() or register your own init functions in the veil.veil_init_fns table. +CONTEXT: SQL statement "select veil.veil_init(TRUE)" COMPLETE PASS -END TEST 7.1 +END TEST 7.8 -tests: 117 -passed: 117 +tests: 124 +passed: 124 failed: 0 - Dropping regressdb... diff --git a/regress/regress.sh b/regress/regress.sh index 124be39..96b094c 100755 --- a/regress/regress.sh +++ b/regress/regress.sh @@ -30,8 +30,8 @@ EOF define_veil() { - echo "\echo - Loading the veil extension... -drop extension if exists veil; + echo " +drop extension if exists veil cascade; create extension veil;" } @@ -42,7 +42,7 @@ db_build_schema() \set ECHO ALL `define_veil` create or replace -function veil_init(bool) returns bool as +function veil.veil_init(doing_reset bool) returns bool as ' begin return true; @@ -93,107 +93,107 @@ regress_1() echo "- ...test set 1: variables..." do_test 1 <multi_call_memory_ctx); - tupdesc = RelationNameGetTupleDesc("veil_variable_t"); + tupdesc = RelationNameGetTupleDesc("veil.veil_variable_t"); slot = TupleDescGetSlot(tupdesc); funcctx->slot = slot; attinmeta = TupleDescGetAttInMetadata(tupdesc); @@ -743,7 +744,7 @@ datum_from_range(int32 min, int32 max) MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext); init_done = true; - tupdesc = RelationNameGetTupleDesc("veil_range_t"); + tupdesc = RelationNameGetTupleDesc("veil.veil_range_t"); slot = TupleDescGetSlot(tupdesc); attinmeta = TupleDescGetAttInMetadata(tupdesc); @@ -2320,8 +2321,9 @@ PG_FUNCTION_INFO_V1(veil_init); * The boolean parameter will be false when called for initialisation, * and true when performing a reset. * - * This function must be redefined as a custom function in your - * implementation. + * This function may be redefined as a custom function in your + * implementation, or will call initialisation functions registered in + * the table veil.veil_init_fns. * * @param fcinfo doing_reset bool Whether we are being * called in order to reset (true) the session or (false) simply to @@ -2331,11 +2333,16 @@ PG_FUNCTION_INFO_V1(veil_init); Datum veil_init(PG_FUNCTION_ARGS) { - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("default veil version of veil_init() has been called"), - errhint("You must define your own version of this function."))); + bool param = PG_GETARG_BOOL(0); + int rows = vl_call_init_fns(param); + if (rows == 0) { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("No user defined veil init functions found"), + errhint("You must refefine veil.veil_init() or register your " + "own init functions in the veil.veil_init_fns table."))); + } PG_RETURN_BOOL(true); } @@ -2357,11 +2364,12 @@ Datum veil_perform_reset(PG_FUNCTION_ARGS) { bool success = true; + bool pushed; bool result; int ok; ensure_init(); - ok = vl_spi_connect(); + ok = vl_spi_connect(&pushed); if (ok != SPI_OK_CONNECT) { ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), @@ -2371,9 +2379,9 @@ veil_perform_reset(PG_FUNCTION_ARGS) success = vl_prepare_context_switch(); if (success) { - result = vl_bool_from_query("select veil_init(TRUE)", &success); + result = vl_bool_from_query("select veil.veil_init(TRUE)", &success); elog(NOTICE, "veil_init returns %s to veil_perform_reset", - result? "true": "false"); + success? "true": "false"); success = vl_complete_context_switch(); elog(NOTICE, "vl_complete_context_switch returns %s to veil_perform_reset", @@ -2390,7 +2398,7 @@ veil_perform_reset(PG_FUNCTION_ARGS) "is still using the previous memory context."))); } - ok = vl_spi_finish(); + ok = vl_spi_finish(pushed); PG_RETURN_BOOL(success); } diff --git a/src/veil_interface.sqs b/src/veil_interface.sqs index 64b25a4..dd896f8 100644 --- a/src/veil_interface.sqs +++ b/src/veil_interface.sqs @@ -15,33 +15,48 @@ create schema veil; comment on schema veil is 'Schema containing all veil components.'; +create table veil.veil_init_fns( + fn_name varchar not null, + priority integer not null +); + +comment on table veil.veil_init_fns is +'Configuration table containing the names of functions, conforming to +the veil.veil_init() API, that veil_init() should call to initialise or +reset veil variables. The calls will be performed in priority order. +Note that other veil extensions are expected to create inherited chldren +of this table, so that their init functions will be called and when the +extension is dropped, the functions will no longer be visible to +veil.veil_init().'; -create type veil_range_t as ( +select pg_catalog.pg_extension_config_dump('veil.veil_init_fns', ''); + +create type veil.veil_range_t as ( min int4, max int4 ); -comment on type veil_range_t is +comment on type veil.veil_range_t is 'Veil type used to record ranges. A range is a pair of integers identifying the minimum and maximum values of the range. Ranges are used to constrain the size of a bitmap or bitmap array.'; -create type veil_variable_t as ( +create type veil.veil_variable_t as ( name text, type text, shared bool ); -comment on type veil_variable_t is +comment on type veil.veil_variable_t is 'Veil type used as the result type of veil_variables(), to describe each variable known to a veil instance.'; create or replace -function veil_share(name text) returns bool +function veil.share(name text) returns bool as '@LIBPATH@', 'veil_share' language C stable strict; -comment on function veil_share(name text) is +comment on function veil.share(name text) is 'Create a shared variable named NAME. Return TRUE if successful, else raise an error. @@ -57,17 +72,17 @@ session variables, and are created by assignment, or initialisation. To create a shared variable, call veil_share() with the name of the variable you wish to create, then create and use the variable as you would a session variable. Shared variables should only be created and -initialised from veil_init() in order to prevent race conditions. If a -variable has already been created as a session variable, it cannot be -repurposed as a shared variable.'; +initialised from veil.veil_init() in order to prevent race conditions. +If a variable has already been created as a session variable, it cannot +be repurposed as a shared variable.'; create or replace -function veil_variables() returns setof veil_variable_t +function veil.veil_variables() returns setof veil.veil_variable_t as '@LIBPATH@', 'veil_variables' language C stable; -comment on function veil_variables() is +comment on function veil.veil_variables() is 'List all current veil_variables. Return a set of veil_variable_t results, detailing each existant variable @@ -76,11 +91,11 @@ This is intended for interactive use for debugging purposes.'; create or replace -function veil_init_range(name text, min int4, max int4) returns int4 +function veil.init_range(name text, min int4, max int4) returns int4 as '@LIBPATH@', 'veil_init_range' language C stable strict; -comment on function veil_init_range(text, int4, int4) is +comment on function veil.init_range(text, int4, int4) is 'Initialise a Range variable called NAME constrained by MIN and MAX. Return the number of elements in the range. @@ -89,20 +104,20 @@ Ranges may be examined using the veil_range() function.'; create or replace -function veil_range(name text) returns veil_range_t +function veil.range(name text) returns veil.veil_range_t as '@LIBPATH@', 'veil_range' language C stable strict; -comment on function veil_range(name text) is +comment on function veil.range(name text) is 'Return the range for range variable NAME.'; create or replace -function veil_init_bitmap(bitmap_name text, range_name text) returns bool +function veil.init_bitmap(bitmap_name text, range_name text) returns bool as '@LIBPATH@', 'veil_init_bitmap' language C stable strict; -comment on function veil_init_bitmap(text, text) is +comment on function veil.init_bitmap(text, text) is 'Create or re-initialise the Bitmap named BITMAP_NAME, for the range of bits given by RANGE_NAME. @@ -112,12 +127,12 @@ All bits in the bitmap will be zero (cleared).'; create or replace -function veil_clear_bitmap(name text) returns bool +function veil.clear_bitmap(bitmap_name text) returns bool as '@LIBPATH@', 'veil_clear_bitmap' language C stable strict; -comment on function veil_clear_bitmap(text) is -'Clear the Bitmap or BitmapRef identified by NAME. +comment on function veil.clear_bitmap(text) is +'Clear the Bitmap or BitmapRef identified by BITMAP_NAME. Return TRUE, or raise an error. @@ -125,12 +140,12 @@ Clear (set to zero) all bits in the named bitmap.'; create or replace -function veil_bitmap_setbit(name text, bit_number int4) returns bool +function veil.bitmap_setbit(bitmap_name text, bit_number int4) returns bool as '@LIBPATH@', 'veil_bitmap_setbit' language C stable strict; -comment on function veil_bitmap_setbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, set the bit given by +comment on function veil.bitmap_setbit(text, int4) is +'In the Bitmap or BitmapRef identified by BITMAP_NAME, set the bit given by BIT_NUMBER. Return TRUE or raise an error. @@ -139,12 +154,12 @@ Set to 1, the identified bit.'; create or replace -function veil_bitmap_clearbit(name text, bit_number int4) returns bool +function veil.bitmap_clearbit(bitmap_name text, bit_number int4) returns bool as '@LIBPATH@', 'veil_bitmap_clearbit' language C stable strict; -comment on function veil_bitmap_clearbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, clear the bit given by +comment on function veil.bitmap_clearbit(text, int4) is +'In the Bitmap or BitmapRef identified by BITMAP_NAME, clear the bit given by BIT_NUMBER. Return TRUE or raise an error. @@ -153,72 +168,72 @@ Set to 0, the identified bit.'; create or replace -function veil_bitmap_testbit(name text, bit_number int4) returns bool +function veil.bitmap_testbit(bitmap_name text, bit_number int4) returns bool as '@LIBPATH@', 'veil_bitmap_testbit' language C stable strict; -comment on function veil_bitmap_testbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, test the bit given by +comment on function veil.bitmap_testbit(text, int4) is +'In the Bitmap or BitmapRef identified by BITMAP_NAME, test the bit given by BIT_NUMBER. Return TRUE if the bit is set, FALSE if it is zero.'; create or replace -function veil_bitmap_union(result_name text, name2 text) returns bool +function veil.bitmap_union(result_name text, bm2_name text) returns bool as '@LIBPATH@', 'veil_bitmap_union' language C stable strict; -comment on function veil_bitmap_union(text, text) is -'Union two Bitmaps, RESULT_NAME and NAME2, with the result going into +comment on function veil.bitmap_union(text, text) is +'Union two Bitmaps, RESULT_NAME and BM2_NAME, with the result going into the first. Return TRUE, or raise an error.'; create or replace -function veil_bitmap_intersect(result_name text, name2 text) returns bool +function veil.bitmap_intersect(result_name text, bm2_name text) returns bool as '@LIBPATH@', 'veil_bitmap_intersect' language C stable strict; -comment on function veil_bitmap_intersect(text, text) is -'Intersect two Bitmaps, RESULT_NAME and NAME2, with the result going into +comment on function veil.bitmap_intersect(text, text) is +'Intersect two Bitmaps, RESULT_NAME and B<2_NAME, with the result going into the first. Return TRUE, or raise an error.'; create or replace -function veil_bitmap_bits(name text) returns setof int4 +function veil.bitmap_bits(bitmap_name text) returns setof int4 as '@LIBPATH@', 'veil_bitmap_bits' language C stable strict; -comment on function veil_bitmap_bits(text) is -'Return each bit in the bitmap NAME. +comment on function veil.bitmap_bits(text) is +'Return each bit in the bitmap BITMAP_NAME. This is primarily intended for interactive use for debugging, etc.'; create or replace -function veil_bitmap_range(name text) returns veil_range_t +function veil.bitmap_range(bitmap_name text) returns veil.veil_range_t as '@LIBPATH@', 'veil_bitmap_range' language C stable strict; -comment on function veil_bitmap_range(text) is -'Return the range of bitmap NAME. +comment on function veil.bitmap_range(text) is +'Return the range of bitmap BITMAP_NAME. It is primarily intended for interactive use.'; create or replace -function veil_init_bitmap_array(bmarray text, array_range text, +function veil.init_bitmap_array(bmarray text, array_range text, bitmap_range text) returns bool as '@LIBPATH@', 'veil_init_bitmap_array' language C stable strict; -comment on function veil_init_bitmap_array(text, text, text) is +comment on function veil.init_bitmap_array(text, text, text) is 'Creates or resets (clears) BMARRAY, to have ARRAY_RANGE bitmaps of BITMAP_RANGE bits. @@ -226,25 +241,25 @@ Returns TRUE or raises an error'; create or replace -function veil_clear_bitmap_array(bmarray text) returns bool +function veil.clear_bitmap_array(bmarray text) returns bool as '@LIBPATH@', 'veil_clear_bitmap_array' language C stable strict; -comment on function veil_clear_bitmap_array(text) is +comment on function veil.clear_bitmap_array(text) is 'Clear all bits in all bitmaps of bitmap array BMARRAY. Return TRUE or raise an error'; create or replace -function veil_bitmap_from_array(bmref text, bmarray text, +function veil.bitmap_from_array(bmref_name text, bmarray text, index int4) returns text as '@LIBPATH@', 'veil_bitmap_from_array' language C stable strict; -comment on function veil_bitmap_from_array(text, text, int4) is -'Set BitmapRef BMREF to the bitmap from BMARRAY indexed by INDEX. +comment on function veil.bitmap_from_array(text, text, int4) is +'Set BitmapRef BMREF_NAME to the bitmap from BMARRAY indexed by INDEX. Return the name of the BitmapRef. @@ -255,13 +270,13 @@ the transaction they are defined.'; create or replace -function veil_bitmap_array_testbit( +function veil.bitmap_array_testbit( bmarray text, arr_idx int4, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_array_testbit' language C stable strict; -comment on function veil_bitmap_array_testbit(text, int4, int4) is +comment on function veil.bitmap_array_testbit(text, int4, int4) is 'Test a bit in BMARRAY, from the bitmap indexed by ARR_IDX, checking the bit identified by BITNO. @@ -269,13 +284,13 @@ Return TRUE if the bit is set, else FALSE'; create or replace -function veil_bitmap_array_setbit( +function veil.bitmap_array_setbit( bmarray text, arr_idx int4, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_array_setbit' language C stable strict; -comment on function veil_bitmap_array_setbit(text, int4, int4) is +comment on function veil.bitmap_array_setbit(text, int4, int4) is 'Set a bit in BMARRAY, from the bitmap indexed by ARR_IDX, setting the bit identified by BITNO. @@ -283,13 +298,13 @@ Return TRUE'; create or replace -function veil_bitmap_array_clearbit( +function veil.bitmap_array_clearbit( bmarray text, arr_idx int4, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_array_clearbit' language C stable strict; -comment on function veil_bitmap_array_clearbit(text, int4, int4) is +comment on function veil.bitmap_array_clearbit(text, int4, int4) is 'Clear a bit in BMARRAY, from the bitmap indexed by ARR_IDX, clearing the bit identified by BITNO. @@ -297,70 +312,70 @@ Return TRUE'; create or replace -function veil_union_from_bitmap_array( +function veil.union_from_bitmap_array( bitmap text, bmarray text, arr_idx int4) returns bool as '@LIBPATH@', 'veil_union_from_bitmap_array' language C stable strict; -comment on function veil_union_from_bitmap_array(text, text, int4) is +comment on function veil.union_from_bitmap_array(text, text, int4) is 'Union BITMAP with BMARRAY[ARR_IDX], with the result going into bitmap. Return TRUE'; create or replace -function veil_intersect_from_bitmap_array( +function veil.intersect_from_bitmap_array( bitmap text, bmarray text, arr_idx int4) returns bool as '@LIBPATH@', 'veil_intersect_from_bitmap_array' language C stable strict; -comment on function veil_intersect_from_bitmap_array(text, text, int4) is +comment on function veil.intersect_from_bitmap_array(text, text, int4) is 'Intersect BITMAP with BMARRAY[ARR_IDX], with the result going into bitmap. Return TRUE'; create or replace -function veil_bitmap_array_bits(bmarray text, arr_idx int4) returns setof int4 +function veil.bitmap_array_bits(bmarray text, arr_idx int4) returns setof int4 as '@LIBPATH@', 'veil_bitmap_array_bits' language C stable strict; -comment on function veil_bitmap_array_bits(text, int4) is +comment on function veil.bitmap_array_bits(text, int4) is 'Return all bits in the bitmap given by BMARRAY[ARR_IDX]. This is primarily intended for interactive use: for debugging, etc.'; create or replace -function veil_bitmap_array_arange(bmarray text) returns veil_range_t +function veil.bitmap_array_arange(bmarray text) returns veil.veil_range_t as '@LIBPATH@', 'veil_bitmap_array_arange' language C stable strict; -comment on function veil_bitmap_array_arange(text) is +comment on function veil.bitmap_array_arange(text) is 'Return the array bounds for BMARRAY.'; create or replace -function veil_bitmap_array_brange(bmarray text) returns veil_range_t +function veil.bitmap_array_brange(bmarray text) returns veil.veil_range_t as '@LIBPATH@', 'veil_bitmap_array_brange' language C stable strict; -comment on function veil_bitmap_array_brange(text) is +comment on function veil.bitmap_array_brange(text) is 'Return the range of the bitmaps in BMARRAY.'; create or replace -function veil_init_bitmap_hash(bmhash text, range text) returns bool +function veil.init_bitmap_hash(bmhash text, range text) returns bool as '@LIBPATH@', 'veil_init_bitmap_hash' language C stable strict; -comment on function veil_init_bitmap_hash(text, text) is +comment on function veil.init_bitmap_hash(text, text) is 'Initialise a bitmap hash variable called BMHASH to contain bitmaps of size RANGE. @@ -368,47 +383,47 @@ Return TRUE.'; create or replace -function veil_clear_bitmap_hash(bmhash text) returns bool +function veil.clear_bitmap_hash(bmhash text) returns bool as '@LIBPATH@', 'veil_clear_bitmap_hash' language C stable strict; -comment on function veil_clear_bitmap_hash(text) is +comment on function veil.clear_bitmap_hash(text) is 'Clear all bits in an existing bitmap hash named BMHASH. Return TRUE.'; create or replace -function veil_bitmap_hash_key_exists(bmhash text, key text) returns bool +function veil.bitmap_hash_key_exists(bmhash text, key text) returns bool as '@LIBPATH@', 'veil_bitmap_hash_key_exists' language C stable strict; -comment on function veil_bitmap_hash_key_exists(text, text) is +comment on function veil.bitmap_hash_key_exists(text, text) is 'Determine whether in BMHASH the given KEY already exists. Return TRUE if the key exists, else FALSE.'; create or replace -function veil_bitmap_from_hash(text, text, text) returns text +function veil.bitmap_from_hash(bmref text, bmhash text, key text) returns text as '@LIBPATH@', 'veil_bitmap_from_hash' language C stable strict; -comment on function veil_bitmap_from_hash(text, text, text) is +comment on function veil.bitmap_from_hash(text, text, text) is 'Set BitmapRef BMREF to the bitmap from BMHASH identfied by KEY. Return the name of BMREF.'; create or replace -function veil_bitmap_hash_testbit(text, text, int4) returns bool +function veil.bitmap_hash_testbit(bmhash text, key text, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_hash_testbit' language C stable strict; -comment on function veil_bitmap_hash_testbit(text, text, int4) is +comment on function veil.bitmap_hash_testbit(text, text, int4) is 'Test the bit, in the bitmap from BMHASH identified by KEY, given by BITNO. @@ -416,12 +431,12 @@ Return TRUE if the bit is set, else FALSE.'; create or replace -function veil_bitmap_hash_setbit(text, text, int4) returns bool +function veil.bitmap_hash_setbit(bmhash text, key text, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_hash_setbit' language C stable strict; -comment on function veil_bitmap_hash_setbit(text, text, int4) is +comment on function veil.bitmap_hash_setbit(text, text, int4) is 'Set the bit, in the bitmap from BMHASH identified by KEY, given by BITNO to TRUE. @@ -429,12 +444,12 @@ Return TRUE.'; create or replace -function veil_bitmap_hash_clearbit(text, text, int4) returns bool +function veil.bitmap_hash_clearbit(bmhash text, key text, bitno int4) returns bool as '@LIBPATH@', 'veil_bitmap_hash_clearbit' language C stable strict; -comment on function veil_bitmap_hash_clearbit(text, text, int4) is +comment on function veil.bitmap_hash_clearbit(text, text, int4) is 'Set the bit, in the bitmap from BMHASH identified by KEY, given by BITNO to FALSE. @@ -442,12 +457,12 @@ Return TRUE.'; create or replace -function veil_union_into_bitmap_hash(text, text, text) returns bool +function veil.union_into_bitmap_hash(bmhash text, key text, bitmap text) returns bool as '@LIBPATH@', 'veil_union_into_bitmap_hash' language C stable strict; -comment on function veil_union_into_bitmap_hash(text, text, text) is +comment on function veil.union_into_bitmap_hash(text, text, text) is 'Into the bitmap from BMHASH, identified by KEY, and union the bits from BITMAP (which may be a bitmap or bitmap_ref). @@ -455,11 +470,11 @@ Return TRUE.'; create or replace -function veil_union_from_bitmap_hash(text, text, text) returns bool +function veil.union_from_bitmap_hash(bmhash text, key text, bitmap text) returns bool as '@LIBPATH@', 'veil_union_from_bitmap_hash' language C stable strict; -comment on function veil_union_from_bitmap_hash(text, text, text) is +comment on function veil.union_from_bitmap_hash(text, text, text) is 'Retrieve the bitmap from BMHASH, identified by KEY, and union it into BITMAP (which may be a bitmap or bitmap_ref). @@ -467,11 +482,11 @@ Return TRUE.'; create or replace -function veil_intersect_from_bitmap_hash(text, text, text) returns bool +function veil.intersect_from_bitmap_hash(bitmap text, bmhash text, key text) returns bool as '@LIBPATH@', 'veil_intersect_from_bitmap_hash' language C stable strict; -comment on function veil_intersect_from_bitmap_hash(text, text, text) is +comment on function veil.intersect_from_bitmap_hash(text, text, text) is 'Into BITMAP, intersect the bits from the bitmap in BMHASH identified by KEY. @@ -479,63 +494,63 @@ Return TRUE.'; create or replace -function veil_bitmap_hash_bits(text, text) returns setof int4 +function veil.bitmap_hash_bits(bmhash text, key text) returns setof int4 as '@LIBPATH@', 'veil_bitmap_hash_bits' language C stable strict; -comment on function veil_bitmap_hash_bits(text, text) is +comment on function veil.bitmap_hash_bits(text, text) is 'Return the set of bits in the bitset from BMHASH identfied by KEY.'; create or replace -function veil_bitmap_hash_range(text) returns veil_range_t +function veil.bitmap_hash_range(bmhash text) returns veil.veil_range_t as '@LIBPATH@', 'veil_bitmap_hash_range' language C stable strict; -comment on function veil_bitmap_hash_range(text) is +comment on function veil.bitmap_hash_range(text) is 'Return the range of all bitmaps in BMHASH.'; create or replace -function veil_bitmap_hash_entries(text) returns setof text +function veil.bitmap_hash_entries(bmhash text) returns setof text as '@LIBPATH@', 'veil_bitmap_hash_entries' language C stable strict; -comment on function veil_bitmap_hash_entries(text) is +comment on function veil.bitmap_hash_entries(text) is 'Return the keys of all bitmaps in BMHASH.'; create or replace -function veil_int4_set(text, int4) returns int4 +function veil.int4_set(name text, value int4) returns int4 as '@LIBPATH@', 'veil_int4_set' language C stable; -comment on function veil_int4_set(text, int4) is +comment on function veil.int4_set(text, int4) is 'Set the int4 variable NAME to VALUE. Return the new value'; create or replace -function veil_int4_get(text) returns int4 +function veil.int4_get(name text) returns int4 as '@LIBPATH@', 'veil_int4_get' language C stable strict; -comment on function veil_int4_get(text) is +comment on function veil.int4_get(text) is 'Return the value of int4 variable NAME.'; create or replace -function veil_init_int4array(text, text) returns bool +function veil.init_int4array(arrayname text, range text) returns bool as '@LIBPATH@', 'veil_init_int4array' language C stable strict; -comment on function veil_init_int4array(text, text) is +comment on function veil.init_int4array(text, text) is 'Initialise the int4 array ARRAYNAME, with an index range of RANGE. Each entry in the array is set to zero. @@ -544,11 +559,11 @@ Return TRUE.'; create or replace -function veil_clear_int4array(text) returns bool +function veil.clear_int4array(arrayname text) returns bool as '@LIBPATH@', 'veil_clear_int4array' language C stable strict; -comment on function veil_clear_int4array(text) is +comment on function veil.clear_int4array(text) is 'Reset each entry in the int4 array ARRAYNAME to zero. Return TRUE.'; @@ -556,44 +571,45 @@ Return TRUE.'; create or replace -function veil_int4array_set(text, int4, int4) returns int4 +function veil.int4array_set(arrayname text, idx int4, value int4) returns int4 as '@LIBPATH@', 'veil_int4array_set' language C stable; -comment on function veil_int4array_set(text, int4, int4) is -'Set the ARRAY element IDX to VALUE. +comment on function veil.int4array_set(text, int4, int4) is +'Set the ARRAYNAME element IDX to VALUE. Return the new value.'; create or replace -function veil_int4array_get(text, int4) returns int4 +function veil.int4array_get(arrayname text, idx int4) returns int4 as '@LIBPATH@', 'veil_int4array_get' language C stable strict; -comment on function veil_int4array_get(text, int4) is -'Return the value of ARRAY element IDX.'; +comment on function veil.int4array_get(text, int4) is +'Return the value of ARRAYNAME element IDX.'; create or replace -function veil_init(bool) returns bool +function veil.veil_init(doing_reset bool) returns bool as '@LIBPATH@', 'veil_init' language C stable strict; -comment on function veil_init(bool) is -'This is the default version of veil_init, which does nothing except -raise an error.'; +comment on function veil.veil_init(bool) is +'This calls all registered init functions, passing the DOING_RESET +parameter to them, in priority order. If there are no registered +functions, an exception is raised.'; create or replace -function veil_perform_reset() returns bool +function veil.veil_perform_reset() returns bool as '@LIBPATH@', 'veil_perform_reset' language C stable; -comment on function veil_perform_reset() is +comment on function veil.veil_perform_reset() is 'Allow userspace to force call of veil_init. This function may fail due to outstanding transactions possibly holding @@ -605,33 +621,34 @@ Return TRUE if successful, FALSE otherwise.'; create or replace -function veil_force_reset() returns bool +function veil.veil_force_reset() returns bool as '@LIBPATH@', 'veil_force_reset' language C stable; -comment on function veil_force_reset() is +comment on function veil.veil_force_reset() is 'Allow userspace to force an unconditional reset of veil shared memory. This always causes a PANIC, causing the database to fully reset.'; + create or replace -function veil_version() returns text +function veil.version() returns text as '@LIBPATH@', 'veil_version' language C stable; -comment on function veil_version() is +comment on function veil.version() is 'Return a text string identifying the current veil version.'; create or replace -function veil_serialise(varname text) returns text +function veil.serialise(varname text) returns text as '@LIBPATH@', 'veil_serialise' language C stable strict; -comment on function veil_serialise(varname text) is +comment on function veil.serialise(varname text) is 'Return a serialised copy of a variable VARNAME in text form. This is intended to be used with pgmemcache so that session variables @@ -643,12 +660,12 @@ The value can be restored by de-serialising it.'; create or replace -function veil_serialize(text) returns text +function veil.serialize(varname text) returns text as '@LIBPATH@', 'veil_serialise' language C stable strict; -comment on function veil_serialize(varname text) is +comment on function veil.serialize(varname text) is 'Return a serialised copy of a variable VARNAME in text form. This is intended to be used with pgmemcache so that session variables @@ -660,12 +677,12 @@ The value can be restored by de-serializing it.'; create or replace -function veil_deserialise(text) returns int4 +function veil.deserialise(stream text) returns int4 as '@LIBPATH@', 'veil_deserialise' language C stable strict; -comment on function veil_deserialise(text) is +comment on function veil.deserialise(text) is 'Reset the contents of a set of serialised variable from STREAM. Return the number of items de-serialised.'; @@ -673,77 +690,79 @@ Return the number of items de-serialised.'; -- Ditto for victims of webster. create or replace -function veil_deserialize(text) returns int4 +function veil.deserialize(stream text) returns int4 as '@LIBPATH@', 'veil_deserialise' language C stable strict; -comment on function veil_deserialize(text) is +comment on function veil.deserialize(text) is 'Reset the contents of a set of serialized variable from STREAM. Return the number of items de-serialized.'; -revoke execute on function veil_share(text) from public; -revoke execute on function veil_variables() from public; -revoke execute on function veil_init_range(text, int4,int4) from public; -revoke execute on function veil_range(text) from public; +revoke execute on function veil.share(text) from public; +revoke execute on function veil.veil_variables() from public; +revoke execute on function veil.init_range(text, int4, int4) from public; +revoke execute on function veil.range(text) from public; -revoke execute on function veil_init_bitmap(text, text) from public; -revoke execute on function veil_clear_bitmap(text) from public; -revoke execute on function veil_bitmap_setbit(text, int4) from public; -revoke execute on function veil_bitmap_testbit(text, int4) from public; -revoke execute on function veil_bitmap_bits(text) from public; -revoke execute on function veil_bitmap_range(text) from public; +revoke execute on function veil.init_bitmap(text, text) from public; +revoke execute on function veil.clear_bitmap(text) from public; +revoke execute on function veil.bitmap_setbit(text, int4) from public; +revoke execute on function veil.bitmap_testbit(text, int4) from public; +revoke execute on function veil.bitmap_bits(text) from public; +revoke execute on function veil.bitmap_range(text) from public; -revoke execute on function veil_init_bitmap_array(text, text, text) +revoke execute on function veil.init_bitmap_array(text, text, text) from public; -revoke execute on function veil_clear_bitmap_array(text) from public; -revoke execute on function veil_bitmap_from_array(text, text, int4) +revoke execute on function veil.clear_bitmap_array(text) from public; +revoke execute on function veil.bitmap_from_array(text, text, int4) from public; -revoke execute on function veil_bitmap_array_setbit(text, int4, int4) +revoke execute on function veil.bitmap_array_setbit(text, int4, int4) from public; -revoke execute on function veil_bitmap_array_testbit(text, int4, int4) +revoke execute on function veil.bitmap_array_testbit(text, int4, int4) from public; -revoke execute on function veil_union_from_bitmap_array(text, text, int4) +revoke execute on function veil.union_from_bitmap_array(text, text, int4) from public; -revoke execute on function veil_intersect_from_bitmap_array(text, text, int4) +revoke execute on function veil.intersect_from_bitmap_array(text, text, int4) from public; -revoke execute on function veil_bitmap_array_bits(text, int4) from public; -revoke execute on function veil_bitmap_array_arange(text) from public; -revoke execute on function veil_bitmap_array_brange(text) from public; +revoke execute on function veil.bitmap_array_bits(text, int4) from public; +revoke execute on function veil.bitmap_array_arange(text) from public; +revoke execute on function veil.bitmap_array_brange(text) from public; -revoke execute on function veil_init_bitmap_hash(text, text) from public; -revoke execute on function veil_clear_bitmap_hash(text) from public; -revoke execute on function veil_bitmap_hash_key_exists(text, text) +revoke execute on function veil.init_bitmap_hash(text, text) from public; +revoke execute on function veil.clear_bitmap_hash(text) from public; +revoke execute on function veil.bitmap_hash_key_exists(text, text) from public; -revoke execute on function veil_bitmap_from_hash(text, text, text) +revoke execute on function veil.bitmap_from_hash(text, text, text) from public; -revoke execute on function veil_bitmap_hash_setbit(text, text, int4) +revoke execute on function veil.bitmap_hash_setbit(text, text, int4) from public; -revoke execute on function veil_bitmap_hash_testbit(text, text, int4) +revoke execute on function veil.bitmap_hash_testbit(text, text, int4) from public; -revoke execute on function veil_union_into_bitmap_hash(text, text, text) +revoke execute on function veil.union_into_bitmap_hash(text, text, text) from public; -revoke execute on function veil_union_from_bitmap_hash(text, text, text) +revoke execute on function veil.union_from_bitmap_hash(text, text, text) from public; -revoke execute on function veil_intersect_from_bitmap_hash(text, text, text) +revoke execute on function veil.intersect_from_bitmap_hash(text, text, text) from public; -revoke execute on function veil_bitmap_hash_bits(text, text) from public; -revoke execute on function veil_bitmap_hash_range(text) from public; -revoke execute on function veil_bitmap_hash_entries(text) from public; - -revoke execute on function veil_init_int4array(text, text) from public; -revoke execute on function veil_clear_int4array(text) from public; -revoke execute on function veil_int4array_set(text, int4, int4) from public; -revoke execute on function veil_int4array_get(text, int4) from public; - -revoke execute on function veil_init(bool) from public; - -revoke execute on function veil_serialise(text) from public; -revoke execute on function veil_serialize(text) from public; -revoke execute on function veil_deserialise(text) from public; -revoke execute on function veil_deserialize(text) from public; +revoke execute on function veil.bitmap_hash_bits(text, text) from public; +revoke execute on function veil.bitmap_hash_range(text) from public; +revoke execute on function veil.bitmap_hash_entries(text) from public; + +revoke execute on function veil.init_int4array(text, text) from public; +revoke execute on function veil.clear_int4array(text) from public; +revoke execute on function veil.int4array_set(text, int4, int4) from public; +revoke execute on function veil.int4array_get(text, int4) from public; + +revoke execute on function veil.veil_init(bool) from public; +revoke execute on function veil.veil_perform_reset() from public; +revoke execute on function veil.veil_force_reset() from public; + +revoke execute on function veil.serialise(text) from public; +revoke execute on function veil.serialize(text) from public; +revoke execute on function veil.deserialise(text) from public; +revoke execute on function veil.deserialize(text) from public; diff --git a/src/veil_mainpage.c b/src/veil_mainpage.c index 0f2f715..12d3018 100644 --- a/src/veil_mainpage.c +++ b/src/veil_mainpage.c @@ -11,7 +11,7 @@ /*! \mainpage Veil -\version 1.0.0 (Stable)) +\version 9.1.0 (Stable)) \section license License BSD \section intro_sec Introduction @@ -69,13 +69,13 @@ As an example let's assume that we have a secured view, users, that allows a user to see only their own record. When Alice queries the view, she will see this: -\code +\verbatim select * from users; userid | username ----------+----------- 12345 | Alice -\endcode +\endverbatim Alice should not be able to see any details for Bob or even, strictly speaking, tell whether there is an entry for Bob. This query though: @@ -107,7 +107,7 @@ the where clause, if the function is deemed inexpensive enough, will see every row in the table and so will be able to leak supposedly protected data. This type of exploit can be protected against easily enough by preventing users from defining their own functions, however there are -postgres' builtins that can be potentially be exploited in the same way. +postgres builtins that can be potentially be exploited in the same way. \subsection GoodNews The Good News @@ -159,12 +159,10 @@ create table persons ( The secured view would be defined something like this: \verbatim create view persons( - person_id, - person_name) as -select person_id, - person_name -from persons -where i_have_personal_priv(10013, person_id); + person_id, person_name) as +select person_id, person_name + from persons + where i_have_personal_priv(10013, person_id); \endverbatim A query performed on the view will return rows only for those persons @@ -269,7 +267,7 @@ given context. There are three types of security context: data about a staff member. Note that determining a user's access rights in a relational context may require extra queries to be performed for each function call. Your design should aim to minimise - this. Some applications may require a number of distinct relational + this. Some applications may require several distinct relational contexts. \subsection over-funcs2 Access Functions and Security Contexts @@ -374,6 +372,8 @@ sections - \subpage API-serialisation - \subpage API-control +Note that all veil objects are placed in the veil schema. + \section API-intro Veil API Overview Veil is an API that simply provides a set of state variable types, and operations on those variable types, which are optimised for privilege @@ -409,8 +409,8 @@ Shared variables are global across all sessions. Once a shared variable is defined, all sessions will have access to it. Shared variables are defined in two steps. First, the variable is defined as shared, and then it is initialised and accessed in the same way as for session -variables. Note that shared variables should only be modified within -the function veil_init(). +variables. Note that shared variables should only be created within +\ref API-control-registered-init or \ref API-control-init. Note that bitmap refs and bitmap hashes may not be stored in shared variables. @@ -434,28 +434,30 @@ Note again that session variables are created on usage. Their is no specific function for creating a variable in the variables API. For an example of a function to create a variable see \ref API-bitmap-init. -\section API-variables-share veil_share(name text) -\code -function veil_share(name text) returns bool -\endcode +\section API-variables-share share(name text) +\verbatim +function veil.share(name text) returns bool +\endverbatim -This is used to define a specific variable as being shared. A shared -variable is accessible to all sessions and exists to reduce the need for -multiple copies of identical data. For instance in the Veil demo, -role_privileges are recorded in a shared variable as they will be -identical for all sessions, and to create a copy for each session would -be an unnecessary overhead. This function should only be called from -veil_init(). +Implemented by C function veil_share(), this is used to define a +specific variable as being shared. A shared variable is accessible to +all sessions and exists to reduce the need for multiple copies of +identical data. For instance in the Veil demo, role_privileges are +recorded in a shared variable as they will be identical for all +sessions, and to create a copy for each session would be an unnecessary +overhead. This function should only be called from +\ref API-control-registered-init or \ref API-control-init. \section API-variables-var veil_variables() -\code -function veil_variables() returns setof veil_variable_t -\endcode +\verbatim +function veil.veil_variables() returns setof veil_variable_t +\endverbatim -This function returns a description for each variable known to the -session. It provides the name, the type, and whether the variable is -shared. It is primarily intended for interactive use when developing -and debugging Veil-based systems. +This function, implemented by C function veil_variables(), returns a +description for each variable known to the session. It provides the +name, the type, and whether the variable is shared. It is primarily +intended for interactive use when developing and debugging Veil-based +systems. Next: \ref API-simple */ @@ -464,8 +466,20 @@ Next: \ref API-simple Veil's basic types are those that do not contain repeating groups (arrays, hashes, etc). -Ranges consist of a pair of values and are generally used to initialise -the bounds of array and bitmap types. Ranges may not contain nulls. +Ranges, implemented by the type \ref veil_range_t, +consist of a pair of values and are generally used to initialise the +bounds of array and bitmap types. + +\anchor veil_range_t \ref veil_range_t is defined as: + +\verbatim +create type veil.veil_range_t as ( + min int4, + max int4 +); +\endverbatim + +Ranges may not contain nulls. The int4 type is used to record a simple nullable integer. This is typically used to record the id of the connected user in a session. @@ -477,34 +491,37 @@ The following functions comprise the Veil basic types API: - \ref API-basic-int4-set - \ref API-basic-int4-get -\section API-basic-init-range veil_init_range(name text, min int4, max int4) -\code -function veil_init_range(name text, min int4, max int4) returns int4 -\endcode +\section API-basic-init-range init_range(name text, min int4, max int4) +\verbatim +function veil.init_range(name text, min int4, max int4) returns int4 +\endverbatim -This defines a range, and returns the extent of that range. +This, implemented by veil_init_range() defines a range, and returns the +extent of that range. -\section API-basic-range veil_range(name text) -\code -function veil_range(name text) returns veil_range_t -\endcode +\section API-basic-range range(name text) +\verbatim +function veil.range(name text) returns veil.range_t +\endverbatim -This returns the contents of a range. It is intended primarily for -interactive use. +This, implemented by C function veil_range() returns the contents +of a range. It is intended primarily for interactive use. -\section API-basic-int4-set veil_int4_set(text, int4) -\code -function veil_int4_set(text, int4) returns int4 -\endcode +\section API-basic-int4-set int4_set(name text, value int4) +\verbatim +function veil.int4_set(name text, value int4) returns int4 +\endverbatim -Sets an int4 variable to a value, returning that same value. +Sets an int4 variable to a value, returning that same value. It is +implemented by C function veil_int4_set(). -\section API-basic-int4-get veil_int4_get(text) -\code -function veil_int4_get(text) returns int4 -\endcode +\section API-basic-int4-get int4_get(name text) +\verbatim +function veil.int4_get(name text) returns int4 +\endverbatim -Returns the value of an int4 variable. +Returns the value of the int4 variable given by name. Implemented by C +function veil_int4_get(). Next: \ref API-bitmaps @@ -536,64 +553,74 @@ The following functions comprise the Veil bitmaps API: - \ref API-bitmap-bits - \ref API-bitmap-range -\section API-bitmap-init veil_init_bitmap(bitmap_name text, range_name text) -\code -function veil_init_bitmap(bitmap_name text, range_name text) returns bool -\endcode +\section API-bitmap-init init_bitmap(bitmap_name text, range_name text) +\verbatim +function veil.init_bitmap(bitmap_name text, range_name text) returns bool +\endverbatim This is used to create or resize a bitmap. The first parameter provides the name of the bitmap, the second is the name of a range variable that -will govern the size of the bitmap. +will govern the size of the bitmap. It is implemented by C function +veil_init_bitmap(). -\section API-bitmap-clear veil_clear_bitmap(name text) -\code -function veil_clear_bitmap(name text) returns bool -\endcode -This is used to clear (set to zero) all bits in the bitmap. +\section API-bitmap-clear clear_bitmap(bitmap_name text) +\verbatim +function veil.clear_bitmap(bitmap_name text) returns bool +\endverbatim +This is used to clear (set to zero) all bits in the bitmap. It is +implemented by C function veil_clear_bitmap(). -\section API-bitmap-setbit veil_bitmap_setbit(name text, bit_number int4) -\code -function veil_bitmap_setbit(text, int4) returns bool -\endcode -This is used to set a specified bit in a bitmap. +\section API-bitmap-setbit bitmap_setbit(bitmap_name text, bit_number int4) +\verbatim +function veil.bitmap_setbit(bitmap_name text, bit_number int4) returns bool +\endverbatim +This is used to set a specified bit, given by bit_number in the bitmap +identified by bitmap_name. It is implemented by C function +veil_bitmap_setbit(). -\section API-bitmap-clearbit veil_bitmap_clearbit(name text, bit_number int4) -\code -function veil_bitmap_clearbit(name text, bit_number int4) returns bool -\endcode -This is used to clear (set to zero) a specified bit in a bitmap. +\section API-bitmap-clearbit bitmap_clearbit(bitmap_name text, bit_number int4) +\verbatim +function veil.bitmap_clearbit(bitmap_name text, bit_number int4) returns bool +\endverbatim +This is used to clear (set to zero) a specified bit in a bitmap. It is +implemented by C function veil_bitmap_clearbit(). -\section API-bitmap-testbit veil_bitmap_testbit(name text, bit_number int4) -\code -function veil_bitmap_testbit(name text, bit_number int4) returns bool -\endcode +\section API-bitmap-testbit bitmap_testbit(bitmap_name text, bit_number int4) +\verbatim +function veil.bitmap_testbit(bitmap_name text, bit_number int4) returns bool +\endverbatim This is used to test a specified bit in a bitmap. It returns true if -the bit is set, false otherwise. +the bit is set, false otherwise. It is implemented by C function +veil_bitmap_testbit(). -\section API-bitmap-union veil_bitmap_union(result_name text, name2 text) -\code -function veil_bitmap_union(result_name text, name2 text) returns bool -\endcode +\section API-bitmap-union bitmap_union(result_name text, bm2_name text) +\verbatim +function veil.bitmap_union(result_name text, bm2_name text) returns bool +\endverbatim Form the union of two bitmaps with the result going into the first. +Implemented by C function veil_bitmap_union(). -\section API-bitmap-intersect veil_bitmap_intersect(result_name text, name2 text) -\code -function veil_bitmap_intersect(result_name text, name2 text) returns bool -\endcode -Form the intersection of two bitmaps with the result going into the first. +\section API-bitmap-intersect bitmap_intersect(result_name text, bm2_name text) +\verbatim +function veil.bitmap_intersect(result_name text, bm2_name text) returns bool +\endverbatim +Form the intersection of two bitmaps with the result going into the +first. Implemented by C function veil_bitmap_intersect(). -\section API-bitmap-bits veil_bitmap_bits(name text) -\code -function veil_bitmap_bits(name text) returns setof int4 -\endcode +\section API-bitmap-bits bitmap_bits(bitmap_name text) +\verbatim +function veil.bitmap_bits(bitmap_name text) returns setof int4 +\endverbatim This is used to list all bits set within a bitmap. It is primarily for interactive use during development and debugging of Veil-based systems. +It is implemented by C function veil_bitmap_bits(). -\section API-bitmap-range veil_bitmap_range(name text) -\code -function veil_bitmap_range(name text) returns veil_range_t -\endcode -This returns the range of a bitmap. It is primarily intended for -interactive use. +\section API-bitmap-range bitmap_range(bitmap_name text) +\verbatim +function veil.bitmap_range(bitmap_name text) returns veil.range_t +\endverbatim +This returns the range, as a \ref veil_range_t, of a +bitmap. It is primarily intended for interactive use. It is +implemented by C function veil_bitmap_range(). Next: \ref API-bitmap-arrays */ @@ -620,85 +647,100 @@ The following functions comprise the Veil bitmap arrays API: - \ref API-bmarray-arange - \ref API-bmarray-brange -\section API-bmarray-init veil_init_bitmap_array(bmarray text, array_range text, bitmap_range text) -\code -function veil_init_bitmap_array(bmarray text, array_range text, bitmap_range text) returns bool -\endcode -Creates or resets (clears) a bitmap array. +\section API-bmarray-init init_bitmap_array(bmarray text, array_range text, bitmap_range text) +\verbatim +function veil.init_bitmap_array(bmarray text, array_range text, bitmap_range text) returns bool +\endverbatim +Creates or resets (clears) the bitmap array named bmarray. +The last two parameters are the names of ranges used to bound the +dimensions of the array, and the range of bits within the array's +bitmaps. Implemented by C function veil_init_bitmap_array(). -\section API-bmarray-clear veil_clear_bitmap_array(bmarray text) -\code -function veil_clear_bitmap_array(bmarray text) returns bool -\endcode -Clear all bits in all bitmaps of a bitmap array +\section API-bmarray-clear clear_bitmap_array(bmarray text) +\verbatim +function veil.clear_bitmap_array(bmarray text) returns bool +\endverbatim +Clear all bits in all bitmaps of the bitmap array named +bmarray. Implemented by C function veil_clear_bitmap_array(). -\section API-bmarray-bmap veil_bitmap_from_array(bmref text, bmarray text, index int4) -\code -function veil_bitmap_from_array(bmref text, bmarray text, index int4) returns text -\endcode -Generate a reference to a specific bitmap in a bitmap array +\section API-bmarray-bmap bitmap_from_array(bmref_name text, bmarray text, index int4) +\verbatim +function veil.bitmap_from_array(bmref_name text, bmarray text, index int4) returns text +\endverbatim +Place a reference into bmref_name to the bitmap identified +by index in bitmap array bmarray. Implemented +by C function veil_bitmap_from_array(). -\section API-bmarray-testbit veil_bitmap_array_testbit(bmarray text, arr_idx int4, bitno int4) -\code -function veil_bitmap_array_testbit(bmarray text, arr_idx int4, bitno int4) returns bool -\endcode -Test a specific bit in a bitmap array. +\section API-bmarray-testbit bitmap_array_testbit(bmarray text, arr_idx int4, bitno int4) +\verbatim +function veil.bitmap_array_testbit(bmarray text, arr_idx int4, bitno int4) returns bool +\endverbatim +Test a specific bit in a bitmap array. Implemented by C function +veil_bitmap_array_testbit(). -\section API-bmarray-setbit veil_bitmap_array_setbit(bmarray text, arr_idx int4, bitno int4) -\code -function veil_bitmap_array_setbit(bmarray text, arr_idx int4, bitno int4) returns bool -\endcode -Set a specific bit in a bitmap array. +\section API-bmarray-setbit bitmap_array_setbit(bmarray text, arr_idx int4, bitno int4) +\verbatim +function veil.bitmap_array_setbit(bmarray text, arr_idx int4, bitno int4) returns bool +\endverbatim +Set a specific bit in a bitmap array. Implemented by C function +veil_bitmap_array_setbit(). -\section API-bmarray-clearbit veil_bitmap_array_clearbit(bmarray text, arr_idx int4, bitno int4) -\code -function veil_bitmap_array_clearbit(bmarray text, arr_idx int4, bitno int4) returns bool -\endcode -Clear a specific bit in a bitmap array. +\section API-bmarray-clearbit bitmap_array_clearbit(bmarray text, arr_idx int4, bitno int4) +\verbatim +function veil.bitmap_array_clearbit(bmarray text, arr_idx int4, bitno int4) returns bool +\endverbatim +Clear a specific bit in a bitmap array. Implemented by C function +veil_bitmap_array_clearbit(). -\section API-bmarray-union veil_union_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) -\code -function veil_union_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) returns bool -\endcode +\section API-bmarray-union union_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) +\verbatim +function veil.union_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) returns bool +\endverbatim Union a bitmap with a specified bitmap from an array, with the result in -the bitmap. This is a faster shortcut for: +the bitmap. Implemented by C function +veil_union_from_bitmap_array(). This is a faster shortcut for the +following logical construction: - -veil_bitmap_union(<bitmap>, veil_bitmap_from_array(<bitmap_array>, <index>)) -. +\verbatim +veil.bitmap_union(, veil.bitmap_from_array(, )) +\endverbatim -\section API-bmarray-intersect veil_intersect_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) -\code -function veil_intersect_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) returns bool -\endcode +\section API-bmarray-intersect intersect_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) +\verbatim +function veil.intersect_from_bitmap_array(bitmap text, bmarray text, arr_idx int4) returns bool +\endverbatim Intersect a bitmap with a specified bitmap from an array, with the result in -the bitmap. This is a faster shortcut for: +the bitmap. Implemented by C function +veil_intersect_from_bitmap_array(). This is a faster shortcut for the +following logical construction: - -veil_bitmap_intersect(<bitmap>, veil_bitmap_from_array(<bitmap_array>, <index>)) -. +\verbatim +veil.bitmap_intersect(, veil.bitmap_from_array(,)) +\endverbatim -\section API-bmarray-bits veil_bitmap_array_bits(bmarray text, arr_idx int4) -\code -function veil_bitmap_array_bits(bmarray text, arr_idx int4) returns setof int4 -\endcode +\section API-bmarray-bits bitmap_array_bits(bmarray text, arr_idx int4) +\verbatim +function veil.bitmap_array_bits(bmarray text, arr_idx int4) returns setof int4 +\endverbatim Show all bits in the specific bitmap within an array. This is primarily intended for interactive use when developing and debugging Veil-based -systems. +systems. Implemented by C function veil_bitmap_array_bits(). -\section API-bmarray-arange veil_bitmap_array_arange(bmarray text) -\code -function veil_bitmap_array_arange(bmarray text) returns veil_range_t -\endcode -Show the range of array indices for the specified bitmap array. -Primarily for interactive use. +\section API-bmarray-arange bitmap_array_arange(bmarray text) +\verbatim +function veil.bitmap_array_arange(bmarray text) returns veil_range_t +\endverbatim +Return the range of array indices, as a \ref veil_range_t, for the +specified bitmap array. Primarily for interactive use. Implemented by +C function veil_bitmap_array_arange(). -\section API-bmarray-brange veil_bitmap_array_brange(bmarray text) -\code -function veil_bitmap_array_brange(bmarray text) returns veil_range_t -\endcode -Show the range of all bitmaps in the specified bitmap array. -Primarily for interactive use. +\section API-bmarray-brange bitmap_array_brange(bmarray text) +\verbatim +function veil.bitmap_array_brange(bmarray text) returns veil_range_t +\endverbatim +Show the range, as a \ref veil_range_t, of all bitmaps in the specified +bitmap array. Primarily for interactive use. Implemented by +C function veil_bitmap_array_range(). Next: \ref API-bitmap-hashes @@ -728,101 +770,116 @@ The following functions comprise the Veil bitmap hashes API: - \ref API-bmhash-range - \ref API-bmhash-entries -\section API-bmhash-init veil_init_bitmap_hash(bmhash text, range text) -\code -function veil_init_bitmap_hash(bmhash text, range text) returns bool -\endcode -Creates, or resets, a bitmap hash. +\section API-bmhash-init init_bitmap_hash(bmhash text, range text) +\verbatim +function veil.init_bitmap_hash(bmhash text, range text) returns bool +\endverbatim +Creates, or resets, a bitmap hash. Implemented by +C function veil_init_bitmap_hash(). -\section API-bmhash-clear veil_clear_bitmap_hash(bmhash text) -\code -function veil_clear_bitmap_hash(bmhash text) returns bool -\endcode -Clear all bits in a bitmap hash. +\section API-bmhash-clear clear_bitmap_hash(bmhash text) +\verbatim +function veil.clear_bitmap_hash(bmhash text) returns bool +\endverbatim +Clear all bits in all bitmaps of a bitmap hash. Implemented by +C function veil_clear_bitmap_hash(). Implemented by +C function veil_clear_bitmap_hash(). -\section API-bmhash-key-exists veil_bitmap_hash_key_exists(bmhash text, key text) -\code -function veil_bitmap_hash_key_exists(bmhash text, key text) returns bool -\endcode +\section API-bmhash-key-exists bitmap_hash_key_exists(bmhash text, key text) +\verbatim +function veil.bitmap_hash_key_exists(bmhash text, key text) returns bool +\endverbatim Determine whether a given key exists in the hash (contains a bitmap). +Implemented by C function veil_bitmap_hash_key_exists(). -\section API-bmhash-from veil_bitmap_from_hash(text, text, text) -\code -function veil_bitmap_from_hash(text, text, text) returns text -\endcode -Generate a reference to a specific bitmap in a bitmap hash. +\section API-bmhash-from bitmap_from_hash(bmref text, bmhash text, key text) +\verbatim +function veil.bitmap_from_hash(bmref text, bmhash text, key text) returns text +\endverbatim +Generate a reference to a specific bitmap in a bitmap hash. Implemented by +C function veil_bitmap_from_hash(). -\section API-bmhash-testbit veil_bitmap_hash_testbit(text, text, int4) -\code -function veil_bitmap_hash_testbit(text, text, int4) returns bool -\endcode -Test a specific bit in a bitmap hash. +\section API-bmhash-testbit bitmap_hash_testbit(bmhash text, key text, bitno int4) +\verbatim +function veil.bitmap_hash_testbit(bmhash text, key text, bitno int4) returns bool +\endverbatim +Test a specific bit in a bitmap hash. Implemented by +C function veil_bitmap_hash_testbit(). -\section API-bmhash-setbit veil_bitmap_hash_setbit(text, text, int4) -\code -function veil_bitmap_hash_setbit(text, text, int4) returns bool -\endcode -Set a specific bit in a bitmap hash. +\section API-bmhash-setbit bitmap_hash_setbit(bmhash text, kay text, bitno int4) +\verbatim +function veil.bitmap_hash_setbit(bmhash text, key text, bitno int4) returns bool +\endverbatim +Set a specific bit in a bitmap hash. Implemented by +C function veil_bitmap_hash_setbit(). -\section API-bmhash-clearbit veil_bitmap_hash_clearbit(text, text, int4) -\code -function veil_bitmap_hash_clearbit(text, text, int4) returns bool -\endcode -Clear a specific bit in a bitmap hash. +\section API-bmhash-clearbit bitmap_hash_clearbit(bmhash text, key text, bitno int4) +\verbatim +function veil.bitmap_hash_clearbit(bmhash text, key text, bitno int4) returns bool +\endverbatim +Clear a specific bit in a bitmap hash. Implemented by +C function veil_bitmap_hash_clearbit(). -\section API-bmhash-union-into veil_union_into_bitmap_hash(text, text, text) -\code -function veil_union_into_bitmap_hash(text, text, text) returns bool -\endcode +\section API-bmhash-union-into union_into_bitmap_hash(bmhash text, key text, bitmap text) +\verbatim +function veil.union_into_bitmap_hash(bmhash text, key text, bitmap text) returns bool +\endverbatim Union a specified bitmap from a hash with a bitmap, with the result in -the bitmap hash. This is a faster shortcut for: +the bitmap hash. Implemented by C function +veil_union_into_bitmap_hash(). This is a faster shortcut for the +following logical construction: - -veil_bitmap_union(veil_bitmap_from_hash(<bitmap_hash>, <key>), <bitmap>) -. +\verbatim +veil.bitmap_union(veil.bitmap_from_hash(, ), ) +\endverbatim -\section API-bmhash-union-from veil_union_from_bitmap_hash(text, text, text) -\code -function veil_union_from_bitmap_hash(text, text, text) returns bool -\endcode +\section API-bmhash-union-from union_from_bitmap_hash(bmhash text, key text, bitmap text) +\verbatim +function veil.union_from_bitmap_hash(bmhash text, key text, bitmap text) returns bool +\endverbatim Union a bitmap with a specified bitmap from a hash, with the result in -the bitmap. This is a faster shortcut for: +the bitmap. Implemented by C function veil_union_from_bitmap_hash(). +This is a faster shortcut for the following logical construction: - -veil_bitmap_union(<bitmap>, veil_bitmap_from_hash(<bitmap_array>, <key>)) -. +\verbatim +veil.bitmap_union(, veil.bitmap_from_hash(, )) +\endverbatim -\section API-bmhash-intersect-from veil_intersect_from_bitmap_hash(text, text, text) -\code -function veil_intersect_from_bitmap_hash(text, text, text) returns bool -\endcode -Intersect a bitmap with a specified bitmap from a hash, with the result in -the bitmap. This is a faster shortcut for: +\section API-bmhash-intersect-from intersect_from_bitmap_hash(bitmap text, bmhash text, key text) +\verbatim +function veil.intersect_from_bitmap_hash(bitmap text, bmhash text, key text) returns bool +\endverbatim +Intersect a bitmap with a specified bitmap from a hash, with the result +in the bitmap. Implemented by C function +veil_intersect_from_bitmap_hash(). This is a faster shortcut for the +following logical construction: - -veil_bitmap_intersect(<bitmap>, veil_bitmap_from_hash(<bitmap_array>, <key>)) -. +\verbatim +veil.bitmap_intersect(, veil.bitmap_from_hash(, )) +\endverbatim -\section API-bmhash-bits veil_bitmap_hash_bits(text, text) -\code -function veil_bitmap_hash_bits(text, text) returns setof int4 -\endcode +\section API-bmhash-bits bitmap_hash_bits(bmhash text, key text) +\verbatim +function veil.bitmap_hash_bits(bmhash text, key text) returns setof int4 +\endverbatim Show all bits in the specific bitmap within a hash. This is primarily intended for interactive use when developing and debugging Veil-based -systems. +systems. Implemented by C function veil_bitmap_hash_bits(). -\section API-bmhash-range veil_bitmap_hash_range(text) -\code -function veil_bitmap_hash_range(text) returns veil_range_t -\endcode -Show the range of all bitmaps in the hash. Primarily intended for -interactive use. +\section API-bmhash-range bitmap_hash_range(bmhash text) +\verbatim +function veil.bitmap_hash_range(bmhash text) returns veil_range_t +\endverbatim +Show the range, as a \ref veil_range_t, of all bitmaps in the hash. +Primarily intended for interactive use. Implemented by +C function veil_bitmap_hash_range(). -\section API-bmhash-entries veil_bitmap_hash_entries(text) -\code -function veil_bitmap_hash_entries(text) returns setof text -\endcode +\section API-bmhash-entries bitmap_hash_entries(bmhash text) +\verbatim +function veil.bitmap_hash_entries(bmhash text) returns setof text +\endverbatim Show every key in the hash. Primarily intended for interactive use. +Implemented by C function veil_bitmap_hash_entries(). Next: \ref API-int-arrays */ @@ -842,29 +899,33 @@ The following functions comprise the Veil int arrays API: - \ref API-intarray-set - \ref API-intarray-get -\section API-intarray-init veil_init_int4array(text, text) -\code -function veil_init_int4array(text, text) returns bool -\endcode -Creates, or resets the ranges of, an int array. +\section API-intarray-init init_int4array(arrayname text, range text) +\verbatim +function veil.init_int4array(arrayname text, range text) returns bool +\endverbatim +Creates, or resets the ranges of, an int array. Implemented by +C function veil_init_int4array(). -\section API-intarray-clear veil_clear_int4array(text) -\code -function veil_clear_int4array(text) returns bool -\endcode -Clears (zeroes) an int array. +\section API-intarray-clear clear_int4array(arrayname text) +\verbatim +function veil.clear_int4array(arrayname text) returns bool +\endverbatim +Clears (zeroes) an int array. Implemented by +C function veil_clear_int4array(). -\section API-intarray-set veil_int4array_set(text, int4, int4) -\code -function veil_int4array_set(text, int4, int4) returns int4 -\endcode -Set the value of an element in an int array. +\section API-intarray-set int4array_set(arrayname text, idx int4, value int4) +\verbatim +function veil.int4array_set(arrayname text, idx int4, value int4) returns int4 +\endverbatim +Set the value of an element in an int array. Implemented by +C function veil_int4array_set(). -\section API-intarray-get veil_int4array_get(text, int4) -\code -function veil_int4array_get(text, int4) returns int4 -\endcode -Get the value of an element from an int array. +\section API-intarray-get int4array_get(arrayname text, idx int4) +\verbatim +function int4array_get(arrayname text, idx int4) returns int4 +\endverbatim +Get the value of an element from an int array. Implemented by +C function veil_int4array_get(). Next: \ref API-serialisation */ @@ -886,34 +947,35 @@ The following functions comprise the Veil serialisatation API: - \ref API-serialize - \ref API-deserialize -\section API-serialise veil_serialise(text) -\code -function veil_serialise(text) returns text -\endcode +\section API-serialise serialise(varname text) +\verbatim +function veil.serialise(varname text) returns text +\endverbatim This creates a serialised textual representation of the named session variable. The results of this function may be concatenated into a single string, which can be deserialised in a single call to -veil_deserialise() +veil_deserialise(). Implemented by C function veil_serialise(). -\section API-deserialise veil_deserialise(text) -\code -function veil_deserialise(text) returns text -\endcode +\section API-deserialise deserialise(stream text) +\verbatim +function veil.deserialise(stream text) returns text +\endverbatim This takes a serialised representation of one or more variables as created by concatenating the results of veil_serialise(), and de-serialises them, creating new variables as needed and resetting their -values to those they had when they were serialised. +values to those they had when they were serialised. Implemented by C +function veil_deserialise(). -\section API-serialize veil_serialize(text) -\code -function veil_serialize(text) returns text -\endcode +\section API-serialize serialize(varname text) +\verbatim +function veil.serialize(varname text) returns text +\endverbatim Synonym for veil_serialise() -\section API-deserialize veil_deserialize(text) -\code -function veil_deserialize(text) returns text -\endcode +\section API-deserialize deserialize(stream text) +\verbatim +function veil.deserialize(stream text) returns text +\endverbatim Synonym for veil_deserialise() Next: \ref API-control @@ -930,41 +992,78 @@ place. All subsequent transactions will see the new set. The following functions comprise the Veil control functions API: +- \ref API-control-registered-init - \ref API-control-init - \ref API-control-reset -- \ref API-control-force - \ref API-version -\section API-control-init veil_init(bool) -\code -function veil_init(bool) returns bool -\endcode -This function must be redefined by the application. The default -installed version simply raises an error telling you to redefine it. -See \ref Implementation for a more detailed description of this function. +\section API-control-registered-init registered initialisation functions -\section API-control-reset veil_perform_reset() -\code -function veil_perform_reset() returns bool -\endcode -This is used to reset Veil's shared variables. It causes veil_init() to -be called. +A registered initialisation function is one which will be called from +the standard veil \ref API-control-init function. Such functions are +responsible for defining and, usually, initialising shared variables. -\section API-control-force veil_force_reset(bool) -\code -function veil_force_reset() returns bool -\endcode -In the event of veil_perform_reset() failing to complete and leaving -shared variables in a state of limbo, this function may be called to -force the reset. After forcing the reset, this function raises a panic -which will reset the database server. Use this at your peril. +Initialisation functions may be written in any language supported by +PostgreSQL, and must conform to the following function prototype: -\section API-version veil_version() -\code -function veil_version() returns text -\endcode +\verbatim +function init_function(doing_reset bool) returns bool +\endverbatim + +The doing_reset parameter will be set to true if we are +completely resetting veil and redefining all of its variables. In this +case, we must declare and, probably, initialise shared variables prior to +any session initialisation actions. The parameter will be false, if the +function is solely being called to initialise a new session. Check \ref +demo-sec for an example. + +Initialisation functions are registered by inserting their name into +the configuration table veil.veil_init_fns. The functions +listed in this table are executed in order of the priority +column. Eg, to register veil.init_roles() to execute +before veil.init_role_privs(), we would use the following +insert statement: + +\verbatim +insert into veil.veil_init_fns + (fn_name, priority) +values ('veil.init_roles', 1), + ('veil.init_role_privs', 2); +\endverbatim + +\section API-control-init veil_init(doing_reset bool) +\verbatim +function veil.veil_init(doing_reset bool) returns bool +\endverbatim + +This function, implemented by the C function veil_init(), is reponsible +for initialising each veil session. The doing_reset +parameter is true if we are to completely reset Veil, redefining all +shared variables. + +The builtin implementation of veil_init() will call each registered +initialisation function (see \ref API-control-registered-init) in turn. + +If no initialisation functions are registered, veil_init() raises an +exception. + +As an alternative to registering initialisation functions, a Veil-based +application may instead simply redefine veil.veil_init(), though this +usage is deprecated. + +\section API-control-reset veil_perform_reset() +\verbatim +function veil.veil_perform_reset() returns bool +\endverbatim +This is used to reset Veil's shared variables. It causes \ref +API-control-init to be called. Implemented by C function veil_perform_reset(). + +\section API-version version() +\verbatim +function veil.version() returns text +\endverbatim This function returns a string describing the installed version of -veil. +veil. Implemented by C function veil_version(). Next: \ref Building @@ -1103,16 +1202,35 @@ essentially 4 options: \subsection Implementation Implement the Initialisation Function -The initialisation function \ref API-control-init is a critical -function and must be defined. It will be called by Veil, when the first -in-built Veil function is invoked. It is responsible for three distinct -tasks: +Proper initialisation of veil is critical. There are two ways to manage +this. The traditional way is to write your own version of \ref +API-control-init, replacing the supplied version. The newer, better, +alternative is to register your own initialisation functions in the +table veil.veil_init_fns, and have the standard \ref API-control-init, +call them. If there are multiple initialisation functions, they are +called in order of their priority values as specified in the table +veil.veil_init_fns. + +The newer approach has a number of advantages: + +- it fully supports the PostgreSQL extension mechanism, allowing + extensions to be created and dropped; +- it allows different security subsystems to have their own separate + initialisation routines, allowing more modular code and better + separation of responsibilities; +- it is way cooler. + +Initialisation functions \ref API-control-init are critical elements. +They will be called by automatically by Veil, when the first in-built +Veil function is invoked. Initialisation functions are responsible for +three distinct tasks: - Initialisation of session variables - Initialisation of shared variables - Re-initialisation of variables during reset -The boolean parameter to veil_init will be false on initial session +The boolean parameter to veil_init (which is passed to registered +initialisation functions) will be false on initial session startup, and true when performing a reset (\ref API-control-reset). Shared variables are created using \ref API-variables-share. This @@ -1120,16 +1238,16 @@ returns a boolean result describing whether the variable already existed. If so, and we are not performing a reset, the current session need not initialise it. -Session variables are simply created by referring to them. It is worth +Session variables are simply created by using them. It is worth creating and initialising all session variables to "fix" their data types. This will prevent other functions from misusing them. -If the boolean parameter to veil_init is true, then we are performing a -memory reset, and all shared variables should be re-initialised. A -memory reset will be performed whenever underlying, essentially static, -data has been modified. For example, when new privileges have been -added, we must rebuild all privilege bitmaps to accommodate the new -values. +If the boolean parameter to an initialisation fuction is true, then we +are performing a memory reset, and all shared variables should be +re-initialised. A memory reset will be performed whenever underlying, +essentially static, data has been modified. For example, when new +privileges have been added, we must rebuild all privilege bitmaps to +accommodate the new values. \subsection Implementation2 Implement the Connection Functions @@ -1149,7 +1267,7 @@ the demo (\ref demo-sec) for a working example of this. \subsection Implementation3 Implement the Access Functions Access functions provide the low-level access controls to individual -records. As such their performance is critical. It is generally better +records. As such, their performance is critical. It is generally better to make the connection functions to more work, and the access functions less. Bear in mind that if you perform a query that returns 10,000 rows from a table, your access function for that view is going to be called @@ -1198,8 +1316,7 @@ user accounts. Note that the bulk of the code in a Veil application is in the definition of secured views and instead-of triggers, and that this code is all very similar. Consider using a code-generation tool to implement -this. A suitable code-generator for Veil may be provided in subsequent -releases. +this. Next: \ref Demo @@ -1228,7 +1345,7 @@ a database containing the veil_demo application: - create a new database - connect to that database - execute create extension veil; -- execute create extension veil_demo;create extension veil_demo; Next: \ref demo-model @@ -1259,9 +1376,9 @@ contains those privileges. In this application there is a special role, Personal Context that contains the set of privileges that apply to all -users in their personal context. This role does not need to be -explicitly assigned to users, and should probably never be explicitly -assigned. +users in their personal context. Since all users have the same personal +context privileges, the demo application provides this role to all users +implicitly; there is no need for it to be explicitly assigned. Assignments of roles in the global context are made through person_roles, and in the project (relational) context through @@ -1282,7 +1399,7 @@ table is currently left as an exercise for the reader. This describes each person. A person is someone who owns data and who may connect to the database. This table should contain authentication -information etc. In actuality it just maps a name to a person_id. +information etc. In the demo it just maps a name to a person_id. \subsection demo-projects Projects @@ -1390,7 +1507,7 @@ Using your favourite tool connect to your veil_demo database. You will be able to see all of the demo views, both the secured views and the helpers. But you will not initially be able to see any records: each view will appear to contain no data. To gain some privileges you -must identify yourself using the connect_person() function. +must identify yourself using the \ref demo-code-connect-person function. There are 6 persons in the demo. You may connect as any of them and see different subsets of data. The persons are @@ -1496,20 +1613,22 @@ Next: \ref demo-code */ /*! \page demo-code The Demo Code -\dontinclude funcs.sql \section demo-codesec The Code -\subsection demo-code-veil-init veil_init(bool) +\subsection demo-code-veil-init veil.veil_demo_init(performing_reset bool) This function is called at the start of each session, and whenever \ref API-control-reset is called. The parameter, doing_reset, is false when called to initialise a session and true when called from -veil_perform_reset(). +veil_perform_reset(). It is registered with \ref API-control-init +through the veil.veil_demo_init_fns table which is created +as an inherited table of veil.veil_init_fns. By +registering the initialisation functions using a veil_demo-specific +inherited table, when the veil_demo extension is dropped, so is the +registration data for \ref demo-code-veil-init. -This definition replaces the standard default, do-nothing, -implementation that is shipped with Veil (see \ref API-control-init). - -\skip veil_init(bool) -\until veil_share(''det_types_privs'') +\dontinclude veil_demo.sqs +\skip veil_demo_init(doing +\until init_reqd = The first task of veil_init() is to declare a set of Veil shared variables. This is done by calling \ref API-variables-share. This function @@ -1520,6 +1639,8 @@ These variables are defined as shared because they will be identical for each session. Making them shared means that only one session has to deal with the overhead of their initialisation. +\dontinclude veil_demo.sqs +\skip init_reqd = \until end if; We then check whether the shared variables must be initialised. We will @@ -1548,7 +1669,7 @@ initialisation and population is handled in much the same way as described above for Int4Arrays, using the functions \ref API-bmarray-init and \ref API-bmarray-setbit. -\until end; +\until language The final section of code defines and initialises a set of session variables. These are defined here to avoid getting undefined variable @@ -1563,15 +1684,15 @@ must have no privileges on the base objects, or on the raw Veil functions themselves. The only access to objects protected by Veil must be through user-defined functions and views. -\subsection demo-code-connect-person connect_person(int4) +\subsection demo-code-connect-person connect_person(_person_id int4) This function is used to establish a connection from a specific person. In a real application this function would be provided with some form of authentication token for the user. For the sake of simplicity the demo allows unauthenticated connection requests. -\skip connect_person(int4) -\until end; +\skip connect_person(_per +\until language This function identifies the user, ensures that they have can_connect privilege. It initialises the global_context bitmap to contain the @@ -1579,94 +1700,89 @@ union of all privileges for each role the person is assigned through person_roles. It also sets up a bitmap hash containing a bitmap of privileges for each project to which the person is assigned. -\subsection demo-code-global-priv i_have_global_priv(int4) +\subsection demo-code-global-priv i_have_global_priv(priv_id int4) This function is used to determine whether a user has a specified privilege in the global context. It tests that the user is connected -using veil_int4_get(), and then checks whether the +using \ref API-basic-int4-get, and then checks whether the specified privilege is present in the global_context bitmap. -\skip function i_have_global_priv(int4) +\skip function i_have_global_priv(priv \until security definer; The following example shows this function in use by the secured view, privileges: -\dontinclude views.sql \skip create view privileges -\until i_have_global_priv(10004); +\until grant The privileges used above are select_privileges (10001), insert_privileges (10002), update_privileges (10003), and delete_privileges (10004). -\subsection demo-code-personal-priv i_have_personal_priv(int4, int4) +\subsection demo-code-personal-priv i_have_personal_priv(priv_id int4, person_id int4) This function determines whether a user has a specified privilege to a specified user's data, in the global or personal contexts. It performs -the same tests as for i_have_global_context(). If the user +the same tests as for \ref demo-code-global-priv. If the user does not have access in the global context, and the connected user is the same user as the owner of the data we are looking at, then we test whether the specified privilege exists in the role_privs bitmap array for the Personal Context role. -\dontinclude funcs.sql -\skip function i_have_personal_priv(int4, int4) -\until end; +\dontinclude veil_demo.sqs +\skip function i_have_personal_priv(pr +\until language Here is an example of this function in use from the persons secured view: -\dontinclude views.sql \skip create view persons -\until i_have_personal_priv(10013, person_id); +\until grant -\subsection demo-code-project-priv i_have_project_priv(int4, int4) +\subsection demo-code-project-priv i_have_project_priv(priv_id int4, project_id int4) This function determines whether a user has a specified privilege in the global or project contexts. If the user does not have the global privilege, we check whether they have the privilege defined in the project_context BitmapHash. -\dontinclude funcs.sql -\skip function i_have_project_priv(int4, int4) -\until security definer; +\dontinclude veil_demo.sqs +\skip function i_have_project_priv(pr +\until language Here is an example of this function in use from the instead-of insert trigger for the projects secured view: -\dontinclude views.sql \skip create rule ii_projects \until i_have_project_priv(10018, new.project_id); -\subsection demo-code-proj-pers-priv i_have_proj_or_pers_priv(int4, int4, int4) +\subsection demo-code-proj-pers-priv i_have_proj_or_pers_priv(priv_id int4, project_id int4, person_id int4) This function checks all privileges. It starts with the cheapest check first, and short-circuits as soon as a privilege is found. -\dontinclude funcs.sql -\skip function i_have_proj_or_pers_priv(int4, int4, int4) -\until security definer; +\dontinclude veil_demo.sqs +\skip function i_have_proj_or_pers_priv( +\until language Here is an example of this function in use from the instead-of update trigger for the assignments secured view: -\dontinclude views.sql \skip create rule ii_assignments \until i_have_proj_or_pers_priv(10027, old.project_id, old.person_id); -\subsection demo-code-pers-detail-priv i_have_person_detail_priv(int4, int4) +\subsection demo-code-pers-detail-priv i_have_person_detail_priv(detail_id int4, person_id int4) This function is used to determine which types of person details are accessible to each user. This provides distinct access controls to each attribute that may be recorded for a person. -\dontinclude funcs.sql -\skip function i_have_person_detail_priv(int4, int4) -\until security definer; +\dontinclude veil_demo.sqs +\skip function i_have_person_detail_priv( +\until language The function is shown in use, below, in the instead-of delete trigger for person_details. Note that two distinct access functions are being used here. -\dontinclude views.sql \skip create rule id_person_details \until i_have_person_detail_priv(old.detail_type_id, old.person_id); @@ -1860,11 +1976,6 @@ The regression tests are all contained within the regress directory and are run by the regress.sh shell script. Use the -h option to get fairly detailed help. -\subsection Demodb_install Demo Database -As with the regression tests, you will need to be a privileged database -user to be able to create the demo database. For more on installing the -demo database see \ref demo-install. - \subsection Debugging Debugging If you encounter problems with Veil, you may want to try building with debug enabled. Define the variable VEIL_DEBUG on the make command line @@ -1873,23 +1984,25 @@ to add extra debug code to the executable: $ make clean; make VEIL_DEBUG=1 all \endverbatim -This is a new feature and not yet fully formed but is worth trying if -Veil appears to be misbehaving. If any of the debug code encounters a -problem, ERRORs will be raised. +This is a transient feature and not as pervasive as it could be. If you +need help with debugging please contact the author. Next: \ref History */ /*! \page History History and Compatibility \section past Changes History -\subsection v1_0 Version 1.0.0 (Stable) (2011-07-22) -This is the first version of Veil to be considered production ready, and +\subsection v1_0 Version 9.1.0 (Stable) (2011-07-22) +This is the first version of Veil to be considered production ready and completely stable. It is for use only with PostgreSQL 9.1. Support for older versions of PostgreSQL has been removed in this version. Major changes include: - revamp of the build system to use PGXS and the new PostgreSQL 9.1 extensions mechanism. Veil is now built as an extension. +- modification to the veil_init() mechanism, allowing custom + initialisation functions to be registered through the table + veil.veil_init_fns - removal of the old veil_trial mechanism, which allowed Veil to be tried out without fully installing it. This has removed much unnecessary complexity. @@ -2124,7 +2237,7 @@ pre-production versions will be removed from this documentation. - - 1.0.0 (Stable) + 9.1.0 (Stable) - - - diff --git a/src/veil_query.c b/src/veil_query.c index af9234f..9199a6e 100644 --- a/src/veil_query.c +++ b/src/veil_query.c @@ -35,18 +35,6 @@ typedef bool (Fetch_fn)(HeapTuple, TupleDesc, void *); #define FETCH_SIZE 20 -/** - * Counter to assess depth of recursive spi calls, so that we can - * sensibly and safely use spi_push and spi_pop when appropriate. - */ -static int4 query_depth = 0; - -/** - * State variable used to assess whther query_depth may have been left - * in an invalid state following an error being raised. - */ -static TransactionId connection_xid = 0; - /** * If already connected in this session, push the current connection, * and get a new one. @@ -55,36 +43,28 @@ static TransactionId connection_xid = 0; * - and the current transaction id matches the saved transaction id */ int -vl_spi_connect(void) +vl_spi_connect(bool *p_pushed) { - TransactionId xid = GetCurrentTransactionId(); - - if (query_depth > 0) { - if (xid == connection_xid) { - SPI_push(); - } - else { - /* The previous transaction must have aborted without - * resetting query_depth */ - query_depth = 0; - } + int result = SPI_connect(); + if (result == SPI_ERROR_CONNECT) { + SPI_push(); + *p_pushed = TRUE; + return SPI_connect(); } - - connection_xid = xid; - return SPI_connect(); + *p_pushed = FALSE; + return result; } /** * Reciprocal function for vl_spi_connect() */ int -vl_spi_finish(void) +vl_spi_finish(bool pushed) { int spi_result = SPI_finish(); - if (query_depth > 0) { + if (pushed) { SPI_pop(); } - return spi_result; } @@ -177,24 +157,26 @@ query(const char *qry, Fetch_fn process_row, void *fn_param) { - int row; - int fetched = 0; + int row; + int fetched; + int processed = 0; + bool cntinue; + SPITupleTable *tuptab; - query_depth++; prepare_query(qry, nargs, argtypes, args, read_only, saved_plan); - - for(row = 0; row < SPI_processed; row++) { - fetched++; + fetched = SPI_processed; + tuptab = SPI_tuptable; + for(row = 0; row < fetched; row++) { + processed++; /* Process a row using the processor function */ - if (!process_row(SPI_tuptable->vals[row], - SPI_tuptable->tupdesc, - fn_param)) - { + cntinue = process_row(tuptab->vals[row], + tuptab->tupdesc, + fn_param); + if (!cntinue) { break; } } - query_depth--; - return fetched; + return processed; } @@ -289,7 +271,6 @@ str_from_oid_query(const char *qry, * * @result True if the database exists. */ - extern bool vl_db_exists(Oid db_id) { @@ -300,3 +281,85 @@ vl_db_exists(Oid db_id) } +/** + * ::Fetch_fn function for executing registered veil_init() functions for + * ::query. + * \param tuple The row to be processed + * \param tupdesc Descriptor for the types of the fields in the tuple. + * \param p_param Pointer to a boolean value which is the value of the + * argument to the init function being called. + * \return true. This allows ::query to process further rows. + */ +static bool +exec_init_fn(HeapTuple tuple, TupleDesc tupdesc, void *p_param) +{ + char *col = SPI_getvalue(tuple, tupdesc, 1); + char *qry = palloc(strlen(col) + 15); + bool pushed; + bool result; + bool found; + int ok; + + (void) sprintf(qry, "select %s(%s)", col, + *((bool *) p_param)? "true": "false"); + + ok = vl_spi_connect(&pushed); + if (ok != SPI_OK_CONNECT) { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to execute exec_init_fn() (1)"), + errdetail("SPI_connect() failed, returning %d.", ok))); + } + + found = vl_bool_from_query(qry, &result); + + + ok = vl_spi_finish(pushed); + if (ok != SPI_OK_FINISH) { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to execute exec_init_fn() (2)"), + errdetail("SPI_finish() failed, returning %d.", ok))); + } + + return true; +} + + +/** + * Identify any registered init_functions and execute them. + * + * @param param The boolean parameter to be passed to each init_function. + * + * @result The number of init_functions executed. + */ +int +vl_call_init_fns(bool param) +{ + Oid argtypes[0]; + Datum args[0]; + char *qry = "select fn_name from veil.veil_init_fns order by priority"; + bool pushed; + int rows; + int ok; + + ok = vl_spi_connect(&pushed); + if (ok != SPI_OK_CONNECT) { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to execute vl_call_init_fns() (1)"), + errdetail("SPI_connect() failed, returning %d.", ok))); + } + + rows = query(qry, 0, argtypes, args, false, NULL, + exec_init_fn, (void *) ¶m); + + ok = vl_spi_finish(pushed); + if (ok != SPI_OK_FINISH) { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to execute vl_call_init_fns() (2)"), + errdetail("SPI_finish() failed, returning %d.", ok))); + } + return rows; +} diff --git a/src/veil_version.h b/src/veil_version.h index 8bad207..1fba434 100644 --- a/src/veil_version.h +++ b/src/veil_version.h @@ -13,7 +13,7 @@ /** The version number for this version of veil */ -#define VEIL_VERSION "1.0.0" +#define VEIL_VERSION "9.1.0" /** The version number suffix, indicating stability. */ #define VEIL_VERSION_INFO "Stable" diff --git a/veil--1.0.sql b/veil--1.0.sql deleted file mode 100644 index 4dff5cb..0000000 --- a/veil--1.0.sql +++ /dev/null @@ -1,743 +0,0 @@ -/* ---------- - * veil_interface.sqs (or a file derived from it) - * - * Source file from which veil--.sql is generated using - * sed. - * - * Copyright (c) 2005 - 2011 Marc Munro - * Author: Marc Munro - * License: BSD - * - * ---------- - */ - -create type veil_range_t as ( - min int4, - max int4 -); -comment on type veil_range_t is -'Veil type used to record ranges. A range is a pair of integers identifying -the minimum and maximum values of the range. Ranges are used to -constrain the size of a bitmap or bitmap array.'; - -create type veil_variable_t as ( - name text, - type text, - shared bool -); -comment on type veil_variable_t is -'Veil type used as the result type of veil_variables(), to describe each -variable known to a veil instance.'; - - -create or replace -function veil_share(name text) returns bool - as '$libdir/veil', 'veil_share' - language C stable strict; - -comment on function veil_share(name text) is -'Create a shared variable named NAME. - -Return TRUE if successful, else raise an error. - -Create a veil variable as a shared variable. Variables are named -containers for various types of values. They are referenced by name, -passing the name as a string to the various veil functions. - -Variables may be shared variables in which case they are available, with -the same value, to all sessions, or session variables in which case each -session will have its own instance. Variables are by default created as -session variables, and are created by assignment, or initialisation. To -create a shared variable, call veil_share() with the name of the -variable you wish to create, then create and use the variable as you -would a session variable. Shared variables should only be created and -initialised from veil_init() in order to prevent race conditions. If a -variable has already been created as a session variable, it cannot be -repurposed as a shared variable.'; - - -create or replace -function veil_variables() returns setof veil_variable_t - as '$libdir/veil', 'veil_variables' - language C stable; - -comment on function veil_variables() is -'List all current veil_variables. -Return a set of veil_variable_t results, detailing each existant -variable - -This is intended for interactive use for debugging purposes.'; - - -create or replace -function veil_init_range(name text, min int4, max int4) returns int4 - as '$libdir/veil', 'veil_init_range' - language C stable strict; - -comment on function veil_init_range(text, int4, int4) is -'Initialise a Range variable called NAME constrained by MIN and MAX. - -Return the number of elements in the range. - -Ranges may be examined using the veil_range() function.'; - - -create or replace -function veil_range(name text) returns veil_range_t - as '$libdir/veil', 'veil_range' - language C stable strict; - -comment on function veil_range(name text) is -'Return the range for range variable NAME.'; - - -create or replace -function veil_init_bitmap(bitmap_name text, range_name text) returns bool - as '$libdir/veil', 'veil_init_bitmap' - language C stable strict; - -comment on function veil_init_bitmap(text, text) is -'Create or re-initialise the Bitmap named BITMAP_NAME, for the range of -bits given by RANGE_NAME. - -Return TRUE on success, raise an error otherwise. - -All bits in the bitmap will be zero (cleared).'; - - -create or replace -function veil_clear_bitmap(name text) returns bool - as '$libdir/veil', 'veil_clear_bitmap' - language C stable strict; - -comment on function veil_clear_bitmap(text) is -'Clear the Bitmap or BitmapRef identified by NAME. - -Return TRUE, or raise an error. - -Clear (set to zero) all bits in the named bitmap.'; - - -create or replace -function veil_bitmap_setbit(name text, bit_number int4) returns bool - as '$libdir/veil', 'veil_bitmap_setbit' - language C stable strict; - -comment on function veil_bitmap_setbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, set the bit given by -BIT_NUMBER. - -Return TRUE or raise an error. - -Set to 1, the identified bit.'; - - -create or replace -function veil_bitmap_clearbit(name text, bit_number int4) returns bool - as '$libdir/veil', 'veil_bitmap_clearbit' - language C stable strict; - -comment on function veil_bitmap_clearbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, clear the bit given by -BIT_NUMBER. - -Return TRUE or raise an error. - -Set to 0, the identified bit.'; - - -create or replace -function veil_bitmap_testbit(name text, bit_number int4) returns bool - as '$libdir/veil', 'veil_bitmap_testbit' - language C stable strict; - -comment on function veil_bitmap_testbit(text, int4) is -'In the Bitmap or BitmapRef identified by NAME, test the bit given by -BIT_NUMBER. - -Return TRUE if the bit is set, FALSE if it is zero.'; - - -create or replace -function veil_bitmap_union(result_name text, name2 text) returns bool - as '$libdir/veil', 'veil_bitmap_union' - language C stable strict; - -comment on function veil_bitmap_union(text, text) is -'Union two Bitmaps, RESULT_NAME and NAME2, with the result going into -the first. - -Return TRUE, or raise an error.'; - - -create or replace -function veil_bitmap_intersect(result_name text, name2 text) returns bool - as '$libdir/veil', - 'veil_bitmap_intersect' - language C stable strict; - -comment on function veil_bitmap_intersect(text, text) is -'Intersect two Bitmaps, RESULT_NAME and NAME2, with the result going into -the first. - -Return TRUE, or raise an error.'; - - -create or replace -function veil_bitmap_bits(name text) returns setof int4 - as '$libdir/veil', 'veil_bitmap_bits' - language C stable strict; - -comment on function veil_bitmap_bits(text) is -'Return each bit in the bitmap NAME. - -This is primarily intended for interactive use for debugging, etc.'; - - -create or replace -function veil_bitmap_range(name text) returns veil_range_t - as '$libdir/veil', 'veil_bitmap_range' - language C stable strict; - -comment on function veil_bitmap_range(text) is -'Return the range of bitmap NAME. - -It is primarily intended for interactive use.'; - - - -create or replace -function veil_init_bitmap_array(bmarray text, array_range text, - bitmap_range text) returns bool - as '$libdir/veil', 'veil_init_bitmap_array' - language C stable strict; - -comment on function veil_init_bitmap_array(text, text, text) is -'Creates or resets (clears) BMARRAY, to have ARRAY_RANGE bitmaps of -BITMAP_RANGE bits. - -Returns TRUE or raises an error'; - - -create or replace -function veil_clear_bitmap_array(bmarray text) returns bool - as '$libdir/veil', 'veil_clear_bitmap_array' - language C stable strict; - -comment on function veil_clear_bitmap_array(text) is -'Clear all bits in all bitmaps of bitmap array BMARRAY. - -Return TRUE or raise an error'; - - -create or replace -function veil_bitmap_from_array(bmref text, bmarray text, - index int4) returns text - as '$libdir/veil', - 'veil_bitmap_from_array' - language C stable strict; - -comment on function veil_bitmap_from_array(text, text, int4) is -'Set BitmapRef BMREF to the bitmap from BMARRAY indexed by INDEX. - -Return the name of the BitmapRef. - -This is used to isolate a single bitmap from a bitmap array, recording -it in a BitmapRef. That bitmap can then be manipulated by ordinary veil -bitmap functions. Note that BitMapRefs can only be referenced within -the transaction they are defined.'; - - -create or replace -function veil_bitmap_array_testbit( - bmarray text, arr_idx int4, bitno int4) returns bool - as '$libdir/veil', - 'veil_bitmap_array_testbit' - language C stable strict; - -comment on function veil_bitmap_array_testbit(text, int4, int4) is -'Test a bit in BMARRAY, from the bitmap indexed by ARR_IDX, checking the -bit identified by BITNO. - -Return TRUE if the bit is set, else FALSE'; - - -create or replace -function veil_bitmap_array_setbit( - bmarray text, arr_idx int4, bitno int4) returns bool - as '$libdir/veil', - 'veil_bitmap_array_setbit' - language C stable strict; - -comment on function veil_bitmap_array_setbit(text, int4, int4) is -'Set a bit in BMARRAY, from the bitmap indexed by ARR_IDX, setting the -bit identified by BITNO. - -Return TRUE'; - - -create or replace -function veil_bitmap_array_clearbit( - bmarray text, arr_idx int4, bitno int4) returns bool - as '$libdir/veil', - 'veil_bitmap_array_clearbit' - language C stable strict; - -comment on function veil_bitmap_array_clearbit(text, int4, int4) is -'Clear a bit in BMARRAY, from the bitmap indexed by ARR_IDX, clearing the -bit identified by BITNO. - -Return TRUE'; - - -create or replace -function veil_union_from_bitmap_array( - bitmap text, bmarray text, arr_idx int4) returns bool - as '$libdir/veil', - 'veil_union_from_bitmap_array' - language C stable strict; - -comment on function veil_union_from_bitmap_array(text, text, int4) is -'Union BITMAP with BMARRAY[ARR_IDX], with the result going into bitmap. - -Return TRUE'; - - -create or replace -function veil_intersect_from_bitmap_array( - bitmap text, bmarray text, arr_idx int4) returns bool - as '$libdir/veil', - 'veil_intersect_from_bitmap_array' - language C stable strict; - -comment on function veil_intersect_from_bitmap_array(text, text, int4) is -'Intersect BITMAP with BMARRAY[ARR_IDX], with the result going into bitmap. - -Return TRUE'; - - -create or replace -function veil_bitmap_array_bits(bmarray text, arr_idx int4) returns setof int4 - as '$libdir/veil', - 'veil_bitmap_array_bits' - language C stable strict; - -comment on function veil_bitmap_array_bits(text, int4) is -'Return all bits in the bitmap given by BMARRAY[ARR_IDX]. - -This is primarily intended for interactive use: for debugging, etc.'; - - -create or replace -function veil_bitmap_array_arange(bmarray text) returns veil_range_t - as '$libdir/veil', - 'veil_bitmap_array_arange' - language C stable strict; - -comment on function veil_bitmap_array_arange(text) is -'Return the array bounds for BMARRAY.'; - - -create or replace -function veil_bitmap_array_brange(bmarray text) returns veil_range_t - as '$libdir/veil', - 'veil_bitmap_array_brange' - language C stable strict; - -comment on function veil_bitmap_array_brange(text) is -'Return the range of the bitmaps in BMARRAY.'; - - - -create or replace -function veil_init_bitmap_hash(bmhash text, range text) returns bool - as '$libdir/veil', 'veil_init_bitmap_hash' - language C stable strict; - -comment on function veil_init_bitmap_hash(text, text) is -'Initialise a bitmap hash variable called BMHASH to contain bitmaps of -size RANGE. - -Return TRUE.'; - - -create or replace -function veil_clear_bitmap_hash(bmhash text) returns bool - as '$libdir/veil', 'veil_clear_bitmap_hash' - language C stable strict; - -comment on function veil_clear_bitmap_hash(text) is -'Clear all bits in an existing bitmap hash named BMHASH. - -Return TRUE.'; - - -create or replace -function veil_bitmap_hash_key_exists(bmhash text, key text) returns bool - as '$libdir/veil', - 'veil_bitmap_hash_key_exists' - language C stable strict; - -comment on function veil_bitmap_hash_key_exists(text, text) is -'Determine whether in BMHASH the given KEY already exists. - -Return TRUE if the key exists, else FALSE.'; - - -create or replace -function veil_bitmap_from_hash(text, text, text) returns text - as '$libdir/veil', - 'veil_bitmap_from_hash' - language C stable strict; - -comment on function veil_bitmap_from_hash(text, text, text) is -'Set BitmapRef BMREF to the bitmap from BMHASH identfied by KEY. - -Return the name of BMREF.'; - - -create or replace -function veil_bitmap_hash_testbit(text, text, int4) returns bool - as '$libdir/veil', - 'veil_bitmap_hash_testbit' - language C stable strict; - -comment on function veil_bitmap_hash_testbit(text, text, int4) is -'Test the bit, in the bitmap from BMHASH identified by KEY, given by -BITNO. - -Return TRUE if the bit is set, else FALSE.'; - - -create or replace -function veil_bitmap_hash_setbit(text, text, int4) returns bool - as '$libdir/veil', - 'veil_bitmap_hash_setbit' - language C stable strict; - -comment on function veil_bitmap_hash_setbit(text, text, int4) is -'Set the bit, in the bitmap from BMHASH identified by KEY, given by -BITNO to TRUE. - -Return TRUE.'; - - -create or replace -function veil_bitmap_hash_clearbit(text, text, int4) returns bool - as '$libdir/veil', - 'veil_bitmap_hash_clearbit' - language C stable strict; - -comment on function veil_bitmap_hash_clearbit(text, text, int4) is -'Set the bit, in the bitmap from BMHASH identified by KEY, given by -BITNO to FALSE. - -Return TRUE.'; - - -create or replace -function veil_union_into_bitmap_hash(text, text, text) returns bool - as '$libdir/veil', - 'veil_union_into_bitmap_hash' - language C stable strict; - -comment on function veil_union_into_bitmap_hash(text, text, text) is -'Into the bitmap from BMHASH, identified by KEY, and union the bits from -BITMAP (which may be a bitmap or bitmap_ref). - -Return TRUE.'; - - -create or replace -function veil_union_from_bitmap_hash(text, text, text) returns bool - as '$libdir/veil', - 'veil_union_from_bitmap_hash' - language C stable strict; -comment on function veil_union_from_bitmap_hash(text, text, text) is -'Retrieve the bitmap from BMHASH, identified by KEY, and union it into -BITMAP (which may be a bitmap or bitmap_ref). - -Return TRUE.'; - - -create or replace -function veil_intersect_from_bitmap_hash(text, text, text) returns bool - as '$libdir/veil', - 'veil_intersect_from_bitmap_hash' - language C stable strict; -comment on function veil_intersect_from_bitmap_hash(text, text, text) is -'Into BITMAP, intersect the bits from the bitmap in BMHASH identified by -KEY. - -Return TRUE.'; - - -create or replace -function veil_bitmap_hash_bits(text, text) returns setof int4 - as '$libdir/veil', - 'veil_bitmap_hash_bits' - language C stable strict; - -comment on function veil_bitmap_hash_bits(text, text) is -'Return the set of bits in the bitset from BMHASH identfied by KEY.'; - - -create or replace -function veil_bitmap_hash_range(text) returns veil_range_t - as '$libdir/veil', - 'veil_bitmap_hash_range' - language C stable strict; - -comment on function veil_bitmap_hash_range(text) is -'Return the range of all bitmaps in BMHASH.'; - - -create or replace -function veil_bitmap_hash_entries(text) returns setof text - as '$libdir/veil', - 'veil_bitmap_hash_entries' - language C stable strict; - -comment on function veil_bitmap_hash_entries(text) is -'Return the keys of all bitmaps in BMHASH.'; - - -create or replace -function veil_int4_set(text, int4) returns int4 - as '$libdir/veil', - 'veil_int4_set' - language C stable; - -comment on function veil_int4_set(text, int4) is -'Set the int4 variable NAME to VALUE. - -Return the new value'; - - -create or replace -function veil_int4_get(text) returns int4 - as '$libdir/veil', - 'veil_int4_get' - language C stable strict; - -comment on function veil_int4_get(text) is -'Return the value of int4 variable NAME.'; - - -create or replace -function veil_init_int4array(text, text) returns bool - as '$libdir/veil', 'veil_init_int4array' - language C stable strict; - -comment on function veil_init_int4array(text, text) is -'Initialise the int4 array ARRAYNAME, with an index range of RANGE. - -Each entry in the array is set to zero. - -Return TRUE.'; - - -create or replace -function veil_clear_int4array(text) returns bool - as '$libdir/veil', - 'veil_clear_int4array' - language C stable strict; -comment on function veil_clear_int4array(text) is -'Reset each entry in the int4 array ARRAYNAME to zero. - -Return TRUE.'; - - - -create or replace -function veil_int4array_set(text, int4, int4) returns int4 - as '$libdir/veil', - 'veil_int4array_set' - language C stable; - -comment on function veil_int4array_set(text, int4, int4) is -'Set the ARRAY element IDX to VALUE. - -Return the new value.'; - - -create or replace -function veil_int4array_get(text, int4) returns int4 - as '$libdir/veil', - 'veil_int4array_get' - language C stable strict; - -comment on function veil_int4array_get(text, int4) is -'Return the value of ARRAY element IDX.'; - - -create or replace -function veil_init(bool) returns bool - as '$libdir/veil', - 'veil_init' - language C stable strict; - -comment on function veil_init(bool) is -'This is the default version of veil_init, which does nothing except -raise an error.'; - - -create or replace -function veil_perform_reset() returns bool - as '$libdir/veil', 'veil_perform_reset' - language C stable; - -comment on function veil_perform_reset() is -'Allow userspace to force call of veil_init. - -This function may fail due to outstanding transactions possibly holding -shared memory that we wish to re-use. In this case a warning will be -issued. Once any long running transactions have completed, a retry -should succeed. - -Return TRUE if successful, FALSE otherwise.'; - - -create or replace -function veil_force_reset() returns bool - as '$libdir/veil', 'veil_force_reset' - language C stable; - -comment on function veil_force_reset() is -'Allow userspace to force an unconditional reset of veil shared memory. - -This always causes a PANIC, causing the database to fully reset.'; - - -create or replace -function veil_version() returns text - as '$libdir/veil', 'veil_version' - language C stable; - -comment on function veil_version() is -'Return a text string identifying the current veil version.'; - - - -create or replace -function veil_serialise(varname text) returns text - as '$libdir/veil', - 'veil_serialise' - language C stable strict; - -comment on function veil_serialise(varname text) is -'Return a serialised copy of a variable VARNAME in text form. - -This is intended to be used with pgmemcache so that session variables -can be efficiently cached. Serialised values can be concatenated -together as a single string and then deserialised in a single operation. - -The value can be restored by de-serialising it.'; - - - -create or replace -function veil_serialize(text) returns text - as '$libdir/veil', - 'veil_serialise' - language C stable strict; - -comment on function veil_serialize(varname text) is -'Return a serialised copy of a variable VARNAME in text form. - -This is intended to be used with pgmemcache so that session variables -can be efficiently cached. Serialized values can be concatenated -together as a single string and then deserialized in a single operation. - -The value can be restored by de-serializing it.'; - - - -create or replace -function veil_deserialise(text) returns int4 - as '$libdir/veil', - 'veil_deserialise' - language C stable strict; - -comment on function veil_deserialise(text) is -'Reset the contents of a set of serialised variable from STREAM. - -Return the number of items de-serialised.'; - - --- Ditto for victims of webster. -create or replace -function veil_deserialize(text) returns int4 - as '$libdir/veil', - 'veil_deserialise' - language C stable strict; - -comment on function veil_deserialize(text) is -'Reset the contents of a set of serialized variable from STREAM. - -Return the number of items de-serialized.'; - - -revoke execute on function veil_share(text) from public; -revoke execute on function veil_variables() from public; -revoke execute on function veil_init_range(text, int4,int4) from public; -revoke execute on function veil_range(text) from public; - -revoke execute on function veil_init_bitmap(text, text) from public; -revoke execute on function veil_clear_bitmap(text) from public; -revoke execute on function veil_bitmap_setbit(text, int4) from public; -revoke execute on function veil_bitmap_testbit(text, int4) from public; -revoke execute on function veil_bitmap_bits(text) from public; -revoke execute on function veil_bitmap_range(text) from public; - -revoke execute on function veil_init_bitmap_array(text, text, text) - from public; -revoke execute on function veil_clear_bitmap_array(text) from public; -revoke execute on function veil_bitmap_from_array(text, text, int4) - from public; -revoke execute on function veil_bitmap_array_setbit(text, int4, int4) - from public; -revoke execute on function veil_bitmap_array_testbit(text, int4, int4) - from public; -revoke execute on function veil_union_from_bitmap_array(text, text, int4) - from public; -revoke execute on function veil_intersect_from_bitmap_array(text, text, int4) - from public; -revoke execute on function veil_bitmap_array_bits(text, int4) from public; -revoke execute on function veil_bitmap_array_arange(text) from public; -revoke execute on function veil_bitmap_array_brange(text) from public; - - -revoke execute on function veil_init_bitmap_hash(text, text) from public; -revoke execute on function veil_clear_bitmap_hash(text) from public; -revoke execute on function veil_bitmap_hash_key_exists(text, text) - from public; -revoke execute on function veil_bitmap_from_hash(text, text, text) - from public; -revoke execute on function veil_bitmap_hash_setbit(text, text, int4) - from public; -revoke execute on function veil_bitmap_hash_testbit(text, text, int4) - from public; -revoke execute on function veil_union_into_bitmap_hash(text, text, text) - from public; -revoke execute on function veil_union_from_bitmap_hash(text, text, text) - from public; -revoke execute on function veil_intersect_from_bitmap_hash(text, text, text) - from public; -revoke execute on function veil_bitmap_hash_bits(text, text) from public; -revoke execute on function veil_bitmap_hash_range(text) from public; -revoke execute on function veil_bitmap_hash_entries(text) from public; - -revoke execute on function veil_init_int4array(text, text) from public; -revoke execute on function veil_clear_int4array(text) from public; -revoke execute on function veil_int4array_set(text, int4, int4) from public; -revoke execute on function veil_int4array_get(text, int4) from public; - -revoke execute on function veil_init(bool) from public; - -revoke execute on function veil_serialise(text) from public; -revoke execute on function veil_serialize(text) from public; -revoke execute on function veil_deserialise(text) from public; -revoke execute on function veil_deserialize(text) from public; - - diff --git a/veil.control b/veil.control index a55c85d..f9e6127 100644 --- a/veil.control +++ b/veil.control @@ -7,8 +7,8 @@ # License: BSD # -directory = 'extension/veil' -default_version = '1.0' +directory = 'extension' +default_version = '9.1' module_pathname = '$libdir/veil' superuser = true relocatable = false diff --git a/veil_demo--1.0.sql b/veil_demo--1.0.sql deleted file mode 100644 index 491cd1d..0000000 --- a/veil_demo--1.0.sql +++ /dev/null @@ -1,1265 +0,0 @@ -create schema hidden; -revoke all on schema hidden from public; - -create table hidden.privileges ( - privilege_id integer not null, - privilege_name varchar(80) not null -); -alter table hidden.privileges add constraint privilege__pk - primary key(privilege_id); - - -create table hidden.roles ( - role_id integer not null, - role_name varchar(80) not null -); -alter table hidden.roles add constraint role__pk - primary key(role_id); - - -create table hidden.role_privileges ( - role_id integer not null, - privilege_id integer not null -); - -alter table hidden.role_privileges add constraint role_privilege__pk - primary key(role_id, privilege_id); - -alter table hidden.role_privileges add constraint role_privilege__role_fk - foreign key(role_id) - references hidden.roles(role_id); - -alter table hidden.role_privileges add constraint role_privilege__priv_fk - foreign key(privilege_id) - references hidden.privileges(privilege_id); - -create table hidden.role_roles ( - role_id integer not null, - has_role_id integer not null -); - -alter table hidden.role_roles add constraint role_role__pk - primary key(role_id, has_role_id); - -alter table hidden.role_roles add constraint role_role__role_fk - foreign key(role_id) - references hidden.roles(role_id); - -alter table hidden.role_roles add constraint role_role__has_role_fk - foreign key(has_role_id) - references hidden.roles(role_id); - - -create sequence person_id_seq; -create table hidden.persons ( - person_id integer not null, - person_name varchar(80) not null -); -alter table hidden.persons add constraint person__pk - primary key(person_id); - - -create sequence project_id_seq; -create table hidden.projects ( - project_id integer not null, - project_name varchar(80) not null -); -alter table hidden.projects add constraint project__pk - primary key(project_id); - - -create table hidden.detail_types ( - detail_type_id integer not null, - required_privilege_id integer not null, - detail_type_name varchar(80) not null -); -alter table hidden.detail_types add constraint detail_type__pk - primary key(detail_type_id); - -alter table hidden.detail_types add constraint detail_type__priv_fk - foreign key(required_privilege_id) - references hidden.privileges(privilege_id); - - -create table hidden.assignments ( - project_id integer not null, - person_id integer not null, - role_id integer not null -); -alter table hidden.assignments add constraint assignment__pk - primary key(project_id, person_id); - -alter table hidden.assignments add constraint assignment__project_fk - foreign key(project_id) - references hidden.projects(project_id); - -alter table hidden.assignments add constraint assignment__person_fk - foreign key(person_id) - references hidden.persons(person_id); - -alter table hidden.assignments add constraint assignment__role_fk - foreign key(role_id) - references hidden.roles(role_id); - - -create table hidden.person_roles ( - person_id integer not null, - role_id integer not null -); -alter table hidden.person_roles add constraint person_role__pk - primary key(person_id, role_id); - -alter table hidden.person_roles add constraint person_role__person_fk - foreign key(person_id) - references hidden.persons(person_id); - -alter table hidden.person_roles add constraint person_role__role_fk - foreign key(role_id) - references hidden.roles(role_id); - - -create table hidden.project_details ( - project_id integer not null, - detail_type_id integer not null, - value text not null -); -alter table hidden.project_details add constraint project_detail__pk - primary key(project_id, detail_type_id); - -alter table hidden.project_details add constraint project_detail__project_fk - foreign key(project_id) - references hidden.projects(project_id); - -alter table hidden.project_details add constraint project_detail__detail_fk - foreign key(detail_type_id) - references hidden.detail_types(detail_type_id); - - -create table hidden.person_details ( - person_id integer not null, - detail_type_id integer not null, - value text not null -); -alter table hidden.person_details add constraint person_detail__pk - primary key(person_id, detail_type_id); - -alter table hidden.person_details add constraint person_detail__person_fk - foreign key(person_id) - references hidden.persons(person_id); - -alter table hidden.person_details add constraint person_detail__detail_fk - foreign key(detail_type_id) - references hidden.detail_types(detail_type_id); - - -insert into hidden.privileges (privilege_id, privilege_name) values -(10001, 'select_privileges'), -(10002, 'insert_privileges'), -(10003, 'update_privileges'), -(10004, 'delete_privileges'), -(10005, 'select_roles'), -(10006, 'insert_roles'), -(10007, 'update_roles'), -(10008, 'delete_roles'), -(10009, 'select_role_privileges'), -(10010, 'insert_role_privileges'), -(10011, 'update_role_privileges'), -(10012, 'delete_role_privileges'), -(10013, 'select_persons'), -(10014, 'insert_persons'), -(10015, 'update_persons'), -(10016, 'delete_persons'), -(10017, 'select_projects'), -(10018, 'insert_projects'), -(10019, 'update_projects'), -(10020, 'delete_projects'), -(10021, 'select_detail_types'), -(10022, 'insert_detail_types'), -(10023, 'update_detail_types'), -(10024, 'delete_detail_types'), -(10025, 'select_assignments'), -(10026, 'insert_assignments'), -(10027, 'update_assignments'), -(10028, 'delete_assignments'), -(10029, 'select_person_roles'), -(10030, 'insert_person_roles'), -(10031, 'update_person_roles'), -(10032, 'delete_person_roles'), -(10033, 'select_project_details'), -(10034, 'insert_project_details'), -(10035, 'update_project_details'), -(10036, 'delete_project_details'), -(10037, 'select_person_details'), -(10038, 'insert_person_details'), -(10039, 'update_person_details'), -(10040, 'delete_person_details'), -(10041, 'select_role_roles'), -(10042, 'insert_role_roles'), -(10043, 'update_role_roles'), -(10044, 'delete_role_roles'), -(10100, 'can_connect'), -(10150, 'view_basic'), -(10151, 'view_personal'), -(10152, 'view_personal_secure'), -(10153, 'view_project_confidential'); - -insert into hidden.roles (role_id, role_name) values -(11001, 'DBA'), -(11002, 'Personal Context'), -(11003, 'Employee'), -(11004, 'Worker'), -(11005, 'Project Manager'), -(11006, 'Director'), -(11007, 'Manager'); - --- DBA can do anything (but is not automatically an employee) -insert into hidden.role_privileges (role_id, privilege_id) -select 11001, privilege_id -from hidden.privileges -where privilege_id != 10100; - --- Personal Context allows update of personal details -insert into hidden.role_privileges (role_id, privilege_id) values -(11002, 10013), -(11002, 10015), -(11002, 10025), -(11002, 10029), -(11002, 10037), -(11002, 10038), -(11002, 10039), -(11002, 10040), -(11002, 10150), -(11002, 10151), -(11002, 10152); - --- Basic Access can see lookup data -insert into hidden.role_privileges (role_id, privilege_id) -select 11003, privilege_id -from hidden.privileges -where privilege_name in ('select_privileges', 'select_roles', - 'select_role_privileges', 'select_detail_types'); - -insert into hidden.role_privileges (role_id, privilege_id) -select 11003, 10100; - --- Workers can modify project info -insert into hidden.role_privileges (role_id, privilege_id) -select 11004, privilege_id -from hidden.privileges -where privilege_name like '%project%' -and privilege_name not like 'delete%' -and privilege_name not like '%confidential'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11004, 10025; -insert into hidden.role_privileges (role_id, privilege_id) -select 11004, 10150; - --- Project Manager can do anything to project info and can see personal info -insert into hidden.role_privileges (role_id, privilege_id) -select 11005, privilege_id -from hidden.privileges -where privilege_name like '%project%' -or privilege_name like '%assignment%'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11005, privilege_id -from hidden.privileges -where privilege_name like 'select_person%'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11005, 10150; -insert into hidden.role_privileges (role_id, privilege_id) -select 11005, 10151; - --- Director can do anything except modify personal details -insert into hidden.role_privileges (role_id, privilege_id) -select 11006, privilege_id -from hidden.privileges -where privilege_name not like '%person%'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11006, privilege_id -from hidden.privileges -where privilege_name like 'select_person%'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11006, 10014; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11006, 10151; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11006, 10152; - --- Manager can see personal info -insert into hidden.role_privileges (role_id, privilege_id) -select 11007, privilege_id -from hidden.privileges -where privilege_name like 'select_person%'; - -insert into hidden.role_privileges (role_id, privilege_id) -select 11007, 10150; -insert into hidden.role_privileges (role_id, privilege_id) -select 11007, 10151; - - -insert into hidden.persons (person_id, person_name) values -(1, 'Deb (the DBA)'), -(2, 'Pat (the PM)'), -(3, 'Derick (the director)'), -(4, 'Will (the worker)'), -(5, 'Wilma (the worker)'), -(6, 'Fred (the fired DBA)'); - -insert into hidden.person_roles (person_id, role_id) values -(1, 11001), -(1, 11003), -(2, 11003), -(2, 11007), -(3, 11003), -(3, 11006), -(4, 11003), -(5, 11003), -(6, 11001); - -insert into hidden.projects (project_id, project_name) values -(101, 'Secret Project'), -(102, 'Public project'); - -insert into hidden.assignments (project_id, person_id, role_id) values -(101, 3, 11005), -(101, 5, 11004), -(102, 2, 11005), -(102, 4, 11004), -(102, 5, 11004); - -insert into hidden.detail_types (detail_type_id, required_privilege_id, - detail_type_name) values -(1001, 10150, 'start_date'), -(1002, 10150, 'status'), -(1003, 10150, 'join_date'), -(1004, 10152, 'salary'), -(1005, 10151, 'date of birth'), -(1006, 10152, 'sin'), -(1007, 10150, 'skills'), -(1008, 10153, 'contract value'); - -insert into hidden.person_details (person_id, detail_type_id, value) values -(1, 1003, '20050102'), -(2, 1003, '20050103'), -(3, 1003, '20050104'), -(4, 1003, '20050105'), -(5, 1003, '20050106'), -(6, 1003, '20050107'), -(1, 1002, 'Employee'), -(2, 1002, 'Employee'), -(3, 1002, 'Employee'), -(4, 1002, 'Employee'), -(5, 1002, 'Employee'), -(6, 1002, 'Terminated'), -(1, 1004, '50,000'), -(2, 1004, '50,000'), -(3, 1004, '80,000'), -(4, 1004, '30,000'), -(5, 1004, '30,000'), -(6, 1004, '40,000'), -(1, 1005, '19610102'), -(2, 1005, '19600102'), -(3, 1005, '19650102'), -(4, 1005, '19660102'), -(5, 1005, '19670102'), -(1, 1006, '123456789'), -(2, 1006, '123456789'), -(3, 1006, '123456789'), -(4, 1006, '123456789'), -(5, 1006, '123456789'), -(1, 1007, 'Oracle, C, SQL'), -(2, 1007, 'Soft peoply-stuff'), -(3, 1007, 'None at all'), -(4, 1007, 'Subservience'), -(5, 1007, 'Subservience'); - - -insert into hidden.project_details (project_id, detail_type_id, value) values -(101, 1001, '20050101'), -(101, 1002, 'Secretly ongoing'), -(101, 1008, '$800,000'), -(102, 1001, '20050101'), -(102, 1002, 'Ongoing'), -(102, 1008, '$100,000'); - - --- Veil Variables: --- Shared: --- privs_range Range The range of privilege_id in the privileges table --- roles_range Range The range of role_id in the roles table --- role_privs Bitmap Array Array of privilege bitmaps indexed by role_id --- det_types_range Range The range of detail_type_id in detail_types --- det_types_privs Int4Array Mapping of detail_type_id to the privilege --- required to access details of that type --- --- Session: --- person_id Int4 The id of the currently connected person --- global_context Bitmap The global privileges of the connected person --- project_context Bitmap Hash Hash of privilege bitmaps, indexed by --- project_id, giving the connected person's project privileges. --- --- Security Contexts: --- Global --- Privileges are identified in variable global_context --- Personal --- Privileges are identified in role_privs[11002]. --- Project --- A relational context. Privileges are identified in --- project_context[project_id]. - --- Replacement for default version of veil_init. --- Initialise and load all shared variables. --- -create or replace -function veil_init(bool) returns bool as ' -declare - doing_reset alias for $1; - exists_privs_range bool; - exists_roles_range bool; - exists_role_privs bool; - exists_det_types_range bool; - exists_det_types_privs bool; - init_reqd bool; - dummy bool; - dummy2 bool; - dummyint int4; - _count int4; -begin - -- Declare all shared variables. - - select into exists_privs_range, exists_roles_range, - exists_role_privs, exists_det_types_range, - exists_det_types_privs - veil_share(''privs_range''), veil_share(''roles_range''), - veil_share(''role_privs''), veil_share(''det_types_range''), - veil_share(''det_types_privs''); - - init_reqd = not (exists_privs_range and exists_role_privs and - exists_role_privs and exists_det_types_range and - exists_det_types_privs); - - if init_reqd or doing_reset then - -- Load ranges for privs and roles. - select into dummyint - veil_init_range(''roles_range'', min(role_id), max(role_id)) - from hidden.roles; - - select into dummyint - veil_init_range(''privs_range'', min(privilege_id), - max(privilege_id)) - from hidden.privileges; - - -- Load range for detail_types - select into dummyint - veil_init_range(''det_types_range'', - min(detail_type_id), max(detail_type_id)) - from hidden.detail_types; - - -- Initialise array of required privs for detail_types - select into dummy - veil_init_int4array(''det_types_privs'', ''det_types_range''); - select into _count - count(veil_int4array_set(''det_types_privs'', - detail_type_id, required_privilege_id)) - from hidden.detail_types; - - -- Initialise role_privs bitmap_array - select into dummy - veil_init_bitmap_array(''role_privs'', ''roles_range'', - ''privs_range''); - - -- Populate role_privs bitmap_array - select into _count - count(veil_bitmap_array_setbit(''role_privs'', - role_id, privilege_id)) - from hidden.role_privileges; - - end if; - - -- Declare important session variables, so that we do not - -- get odd, undefined variable, error messages. - select into dummyint, dummy, dummy2 - veil_int4_set(''person_id'', null), - veil_init_bitmap(''global_context'', ''privs_range''), - veil_init_bitmap_hash(''project_context'', ''privs_range''); - - return true; -end; -' language plpgsql -stable -security definer; - -revoke execute on function veil_init(bool) from public; - - -create or replace -function connect_person(int4) returns bool as ' -declare - _person_id alias for $1; - dummy int4; - _connect bool; - proj_roles record; - last_proj int4; - first_rec bool; -begin - -- In reality this function would require some authentication token such - -- as a password. This is just a dumb demo version. - - select into _connect disconnect_person(); - - -- Test whether provided person exists. This is where we would, in a - -- real version, do proper authentication. - select into dummy 1 - from hidden.persons - where person_id = _person_id; - - if found then - -- The person exists and passes authentication - - -- From the persons roles set the global_context bitmap. - select into dummy - count(veil_union_from_bitmap_array(''global_context'', - ''role_privs'', role_id)) - from hidden.person_roles - where person_id = _person_id; - - -- Check that user has can_connect privilege - select into _connect - veil_bitmap_testbit(''global_context'', 10100); - - if not _connect then - select into _connect disconnect_person(); - return false; - end if; - - - -- From the persons assignments set the project_context bitmap hash. - select into dummy - count(veil_union_into_bitmap_hash(''project_context'', - project_id::text, - veil_bitmap_from_array(''scratch_bitmap'', - ''role_privs'', role_id))) - from hidden.assignments - where person_id = _person_id; - - -- Finally, record the person_id for the connection. - select into dummy veil_int4_set(''person_id'', _person_id); - - return true; - else - return false; - end if; - -end; -' language plpgsql -stable -security definer; - -create or replace -function disconnect_person() returns bool as ' -declare - dummy int4; - dummy2 bool; - dummy3 bool; -begin - -- Clear session bitmaps, and reset the person_id - select into dummy, dummy2, dummy3 - veil_int4_set(''person_id'', null), - veil_init_bitmap(''global_context'', ''privs_range''), - veil_init_bitmap_hash(''project_context'', ''privs_range''); - return false; -end; -' language plpgsql -stable -security definer; - - -create or replace -function i_have_global_priv(int4) returns bool as ' -declare - priv_id alias for $1; - connection_id int4; - result bool; -begin - select into connection_id, result - veil_int4_get(''person_id''), - veil_bitmap_testbit(''global_context'', priv_id); - if connection_id is null then - return false; - else - return result; - end if; -end; -' language plpgsql -stable -security definer; - - -create or replace -function i_have_personal_priv(int4, int4) returns bool as ' -declare - priv_id alias for $1; - person_id alias for $2; - connection_id int4; - result bool; -begin - select into connection_id, result - veil_int4_get(''person_id''), - veil_bitmap_testbit(''global_context'', priv_id); - if connection_id is null then - -- No-one is connected - return false; - else - if result then - -- We have the required privilege in global context. No need - -- to check any further - return true; - else - if person_id = connection_id then - -- We are connected as the owner of this record. Check - -- whether we have the required privilege in personal - -- context. - select into result - veil_bitmap_array_testbit(''role_privs'', - 11002, priv_id); - return result; - else - -- We have no personal context rights to this record - return false; - end if; - end if; - end if; -end; -' language plpgsql -stable -security definer; - - -create or replace -function i_have_project_priv(int4, int4) returns bool as ' -declare - priv_id alias for $1; - project_id alias for $2; - connection_id int4; - result bool; -begin - select into connection_id, result - veil_int4_get(''person_id''), - veil_bitmap_testbit(''global_context'', priv_id); - if connection_id is null then - -- No-one is connected - return false; - else - if result then - -- We have the required privilege in global context. No need - -- to check any further - return true; - else - select into result - veil_bitmap_hash_testbit(''project_context'', - project_id::text, priv_id); - return result; - end if; - end if; -end; -' language plpgsql -stable -security definer; - - -create or replace -function i_have_proj_or_pers_priv(int4, int4, int4) returns bool as ' -declare - priv_id alias for $1; - project_id alias for $2; - person_id alias for $3; - connection_id int4; - result bool; -begin - select into connection_id, result - veil_int4_get(''person_id''), - veil_bitmap_testbit(''global_context'', priv_id); - if connection_id is null then - -- No-one is connected - return false; - else - if result then - -- We have the required privilege in global context. No need - -- to check any further - return true; - else - if person_id = connection_id then - -- We are connected as the owner of this record. Check - -- whether we have the required privilege in personal - -- context. - select into result - veil_bitmap_array_testbit(''role_privs'', - 11002, priv_id); - return result; - end if; - select into result - veil_bitmap_hash_testbit(''project_context'', - project_id::text, priv_id); - return result; - -- We have no personal context rights to this record - -- so check project context - return false; - end if; - end if; -end; -' language plpgsql -stable -security definer; - -create or replace -function i_have_project_detail_priv(int4, int4) returns bool as ' -declare - result bool; - detail_id alias for $1; - proj_id alias for $2; -begin - select into result - i_have_project_priv(veil_int4array_get(''det_types_privs'', detail_id), - proj_id); - return result; -end; -' language plpgsql -stable -security definer; - -create or replace -function i_have_person_detail_priv(int4, int4) returns bool as ' -declare - result bool; - detail_id alias for $1; - person_id alias for $2; -begin - select into result - i_have_personal_priv(veil_int4array_get(''det_types_privs'', detail_id), - person_id); - return result; -end; -' language plpgsql -stable -security definer; - -create view privileges( - privilege_id, - privilege_name) as -select privilege_id, - privilege_name -from hidden.privileges -where i_have_global_priv(10001); - -create rule ii_privileges as -on insert to privileges -do instead - insert into hidden.privileges - (privilege_id, privilege_name) - select new.privilege_id, new.privilege_name - where i_have_global_priv(10002); - -create rule iu_privileges as -on update to privileges -do instead - update hidden.privileges - set privilege_name = new.privilege_name, - privilege_id = new.privilege_id - where privilege_id = old.privilege_id - and i_have_global_priv(10003); - -create rule id_privileges as -on delete to privileges -do instead - delete from hidden.privileges - where privilege_id = old.privilege_id - and i_have_global_priv(10004); - -grant select, insert, update, delete on privileges to public; - -create view roles( - role_id, - role_name) as -select role_id, - role_name -from hidden.roles -where i_have_global_priv(10005); - -create rule ii_roles as -on insert to roles -do instead - insert into hidden.roles - (role_id, role_name) - select new.role_id, new.role_name - where i_have_global_priv(10006); - -create rule iu_roles as -on update to roles -do instead - update hidden.roles - set role_name = new.role_name, - role_id = new.role_id - where role_id = old.role_id - and i_have_global_priv(10007); - -create rule id_roles as -on delete to roles -do instead - delete from hidden.roles - where role_id = old.role_id - and i_have_global_priv(10008); - -grant select, insert, update, delete on roles to public; - -create view role_privileges( - role_id, - privilege_id) as -select role_id, - privilege_id -from hidden.role_privileges -where i_have_global_priv(10009); - -create rule ii_role_privileges as -on insert to role_privileges -do instead - insert into hidden.role_privileges - (role_id, privilege_id) - select new.role_id, new.privilege_id - where i_have_global_priv(10010); - -create rule iu_role_privileges as -on update to role_privileges -do instead - update hidden.role_privileges - set role_id = new.role_id, - privilege_id = new.privilege_id - where role_id = old.role_id - and privilege_id = old.privilege_id - and i_have_global_priv(10011); - -create rule id_role_privileges as -on delete to role_privileges -do instead - delete from hidden.role_privileges - where role_id = old.role_id - and i_have_global_priv(10012); - -grant select, insert, update, delete on role_privileges to public; - - -create view role_roles( - role_id, - has_role_id) as -select role_id, - has_role_id -from hidden.role_roles -where i_have_global_priv(10041); - -create rule ii_role_roles as -on insert to role_roles -do instead - insert into hidden.role_roles - (role_id, has_role_id) - select new.role_id, new.has_role_id - where i_have_global_priv(10042); - -create rule iu_role_roles as -on update to role_roles -do instead - update hidden.role_roles - set role_id = new.role_id, - has_role_id = new.has_role_id - where role_id = old.role_id - and i_have_global_priv(10043); - -create rule id_role_roles as -on delete to role_roles -do instead - delete from hidden.role_roles - where role_id = old.role_id - and i_have_global_priv(10044); - -grant select, insert, update, delete on role_roles to public; - - -create view persons( - person_id, - person_name) as -select person_id, - person_name -from hidden.persons -where i_have_personal_priv(10013, person_id); - -create rule ii_persons as -on insert to persons -do instead - insert into hidden.persons - (person_id, person_name) - select new.person_id, new.person_name - where i_have_personal_priv(10014, new.person_id); - -create rule iu_persons as -on update to persons -do instead - update hidden.persons - set person_id = new.person_id, - person_name = new.person_name - where person_id = old.person_id - and i_have_personal_priv(10015, old.person_id); - -create rule id_persons as -on delete to persons -do instead - delete from hidden.persons - where person_id = old.person_id - and i_have_personal_priv(10016, old.person_id); - -grant select, insert, update, delete on persons to public; - - -create view projects( - project_id, - project_name) as -select project_id, - project_name -from hidden.projects -where i_have_project_priv(10017, project_id); - -create rule ii_projects as -on insert to projects -do instead - insert into hidden.projects - (project_id, project_name) - select new.project_id, new.project_name - where i_have_project_priv(10018, new.project_id); - -create rule iu_projects as -on update to projects -do instead - update hidden.projects - set project_id = new.project_id, - project_name = new.project_name - where project_id = old.project_id - and i_have_project_priv(10019, old.project_id); - -create rule id_projects as -on delete to projects -do instead - delete from hidden.projects - where project_id = old.project_id - and i_have_project_priv(10020, old.project_id); - -grant select, insert, update, delete on projects to public; - - -create view detail_types ( - detail_type_id, - required_privilege_id, - detail_type_name) as -select detail_type_id, - required_privilege_id, - detail_type_name -from hidden.detail_types -where i_have_global_priv(10021); - -create rule ii_detail_types as -on insert to detail_types -do instead - insert into hidden.detail_types - (detail_type_id, detail_type_name) - select new.detail_type_id, new.detail_type_name - where i_have_global_priv(10022); - -create rule iu_detail_types as -on update to detail_types -do instead - update hidden.detail_types - set detail_type_id = new.detail_type_id, - detail_type_name = new.detail_type_name - where detail_type_id = old.detail_type_id - and i_have_global_priv(10023); - -create rule id_detail_types as -on delete to detail_types -do instead - delete from hidden.detail_types - where detail_type_id = old.detail_type_id - and i_have_global_priv(10024); - -grant select, insert, update, delete on detail_types to public; - - -create view assignments ( - project_id, - person_id, - role_id) as -select project_id, - person_id, - role_id -from hidden.assignments -where i_have_proj_or_pers_priv(10025, project_id, person_id); - -create rule ii_assignments as -on insert to assignments -do instead - insert into hidden.assignments - (project_id, person_id, role_id) - select new.project_id, new.person_id, new.role_id - where i_have_proj_or_pers_priv(10026, new.project_id, new.person_id); - -create rule iu_assignments as -on update to assignments -do instead - update hidden.assignments - set project_id = new.project_id, - person_id = new.person_id, - role_id = new.person_id - where project_id = old.project_id - and person_id = old.person_id - and i_have_proj_or_pers_priv(10027, old.project_id, old.person_id); - -create rule id_assignments as -on delete to assignments -do instead - delete from hidden.assignments - where project_id = old.project_id - and person_id = old.person_id - and i_have_proj_or_pers_priv(10028, old.project_id, old.person_id); - -grant select, insert, update, delete on assignments to public; - - -create view person_roles ( - person_id, - role_id) as -select person_id, - role_id -from hidden.person_roles -where i_have_personal_priv(10029, person_id); - -create rule ii_person_roles as -on insert to person_roles -do instead - insert into hidden.person_roles - (person_id, role_id) - select new.person_id, new.role_id - where i_have_personal_priv(10030, new.person_id); - -create rule iu_person_roles as -on update to person_roles -do instead - update hidden.person_roles - set person_id = new.person_id, - role_id = new.role_id - where person_id = old.person_id - and role_id = old.role_id - and i_have_personal_priv(10031, old.person_id); - -create rule id_person_roles as -on delete to person_roles -do instead - delete from hidden.person_roles - where person_id = old.person_id - and role_id = old.role_id - and i_have_personal_priv(10032, old.person_id); - -grant select, insert, update, delete on person_roles to public; - - -create view project_details ( - project_id, - detail_type_id, - value) as -select project_id, - detail_type_id, - value -from hidden.project_details -where i_have_project_priv(10033, project_id) -and i_have_project_detail_priv(detail_type_id, project_id); - -create rule ii_project_details as -on insert to project_details -do instead - insert into hidden.project_details - (project_id, detail_type_id, value) - select new.project_id, new.detail_type_id, new.value - where i_have_project_priv(10034, new.project_id) - and i_have_project_detail_priv(new.detail_type_id, new.project_id); - -create rule iu_project_details as -on update to project_details -do instead - update hidden.project_details - set project_id = new.project_id, - detail_type_id = new.detail_type_id, - value = new.value - where project_id = old.project_id - and detail_type_id = old.detail_type_id - and i_have_project_priv(10035, old.project_id) - and i_have_project_detail_priv(old.detail_type_id, old.project_id); - -create rule id_project_details as -on delete to project_details -do instead - delete from hidden.project_details - where project_id = old.project_id - and detail_type_id = old.detail_type_id - and i_have_project_priv(10036, old.project_id) - and i_have_project_detail_priv(old.detail_type_id, old.project_id); - -grant select, insert, update, delete on project_details to public; - - -create view person_details ( - person_id, - detail_type_id, - value) as -select person_id, - detail_type_id, - value -from hidden.person_details -where i_have_personal_priv(10037, person_id) -and i_have_person_detail_priv(detail_type_id, person_id); - -create rule ii_person_details as -on insert to person_details -do instead - insert into hidden.person_details - (person_id, detail_type_id, value) - select new.person_id, new.detail_type_id, new.value - where i_have_personal_priv(10038, new.person_id) - and i_have_person_detail_priv(new.detail_type_id, new.person_id); - -create rule iu_person_details as -on update to person_details -do instead - update hidden.person_details - set person_id = new.person_id, - detail_type_id = new.detail_type_id, - value = new.value - where person_id = old.person_id - and detail_type_id = old.detail_type_id - and i_have_personal_priv(10039, old.person_id) - and i_have_person_detail_priv(old.detail_type_id, old.person_id); - -create rule id_person_details as -on delete to person_details -do instead - delete from hidden.person_details - where person_id = old.person_id - and detail_type_id = old.detail_type_id - and i_have_personal_priv(10040, old.person_id) - and i_have_person_detail_priv(old.detail_type_id, old.person_id); - - -grant select, insert, update, delete on person_details to public; - - -create or replace -function global_privs_qry() returns setof int4 as ' -select * from veil_bitmap_bits(''global_context''); -' language sql -stable security definer; - -create or replace view my_global_privs ( - privilege_id) as -select * from global_privs_qry(); - -grant select on my_global_privs to public; - - -create or replace -function personal_privs_qry() returns setof int4 as ' -select * from veil_bitmap_array_bits(''role_privs'', 11002); -' language sql -stable security definer; - -create or replace view my_personal_privs ( - privilege_id) as -select * from personal_privs_qry(); - -grant select on my_personal_privs to public; - - -create or replace -function projects_qry() returns setof varchar as ' -select * from veil_bitmap_hash_entries(''project_context''); -' language sql -stable security definer; - -create or replace view my_projects ( - project_id) as -select * from projects_qry(); - -grant select on my_projects to public; - - -create type hidden.proj_privs as ( - project_id int4, - privilege_id int4 -); - -create or replace -function project_privs() returns setof hidden.proj_privs as ' -declare - _project record; - _priv record; - _result hidden.proj_privs; -begin - for _project in - select * from veil_bitmap_hash_entries(''project_context'') - loop - _result.project_id = _project.veil_bitmap_hash_entries; - for _priv in - select * from veil_bitmap_hash_bits(''project_context'', - _result.project_id) - loop - _result.privilege_id = _priv.veil_bitmap_hash_bits; - return next _result; - end loop; - end loop; - return; -end; -' language plpgsql -stable security definer; - -grant execute on function project_privs() to public; - -create or replace view my_project_privs ( - project_id, - privilege_id) as -select * from project_privs(); - -grant select on my_project_privs to public; - - -create or replace view my_privs ( - context, - project, - privilege_id, - privilege_name) -as -select a.context, a.project, a.id, p.privilege_name -from ( - select 'Project' as context, project_id as project, - privilege_id as id, 3 as seq - from my_project_privs - union all - select 'Global', null, privilege_id, 1 - from my_global_privs - union all - select 'Personal', null, privilege_id, 2 - from my_personal_privs - ) a, - privileges p -where p.privilege_id = a.id -order by a.seq, a.context, a.project, a.id; - -grant select on my_privs to public;