create table Room ( roomno varchar(8), comment text ); create unique index Room_rno on Room using btree (roomno varchar_ops); create table WSlot ( slotname varchar(20), roomno varchar(8), slotlink varchar(20), backlink varchar(20) ); create unique index WSlot_name on WSlot using btree (slotname varchar_ops); create table PField ( name text, comment text ); create unique index PField_name on PField using btree (name text_ops); create table PSlot ( slotname varchar(20), pfname text, slotlink varchar(20), backlink varchar(20) ); create unique index PSlot_name on PSlot using btree (slotname varchar_ops); create table PLine ( slotname varchar(20), phonenumber varchar(20), comment text, backlink varchar(20) ); create unique index PLine_name on PLine using btree (slotname varchar_ops); create table Hub ( name varchar(14), comment text, nslots int4 ); create unique index Hub_name on Hub using btree (name varchar_ops); create table HSlot ( slotname varchar(20), hubname varchar(14), slotno int4, slotlink varchar(20) ); create unique index HSlot_name on HSlot using btree (slotname varchar_ops); create index HSlot_hubname on HSlot using btree (hubname varchar_ops); create table System ( name text, comment text ); create unique index System_name on System using btree (name text_ops); create table IFace ( slotname varchar(20), sysname text, ifname text, slotlink varchar(20) ); create unique index IFace_name on IFace using btree (slotname varchar_ops); create table PHone ( slotname varchar(20), comment text, slotlink varchar(20) ); create unique index PHone_name on PHone using btree (slotname varchar_ops); -- ************************************************************ -- * AFTER UPDATE on Room -- * - If room no changes let wall slots follow -- ************************************************************ create function tg_room_au() returns trigger as ' if !$Plans[tg["name"]] $Plans[tg["name"]] = PL::Plan.new("update WSlot set roomno = $1 where roomno = $2", ["varchar", "varchar"]).save end if new["roomno"] != old["roomno"] $Plans[tg["name"]].exec(new["roomno"], old["roomno"]) end PL::OK ' language 'plruby'; create trigger tg_room_au after update on Room for each row execute procedure tg_room_au(); -- ************************************************************ -- * AFTER DELETE on Room -- * - delete wall slots in this room -- ************************************************************ create function tg_room_ad() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("delete from WSlot where roomno = $1", ["varchar"]).save end $Plans[tg["name"]].exec([old["roomno"]]) PL::OK ' language 'plruby'; create trigger tg_room_ad after delete on Room for each row execute procedure tg_room_ad(); -- ************************************************************ -- * BEFORE INSERT or UPDATE on WSlot -- * - Check that room exists -- ************************************************************ create function tg_wslot_biu() returns trigger as ' if !$Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("select count(*) as cnt from Room where roomno = $1", ["varchar"]).save end n = $Plans[tg["name"]].exec([new["roomno"]], 1) if ! n["cnt"] raise "Room #{new[''roomno'']} does not exist" end PL::OK ' language 'plruby'; create trigger tg_wslot_biu before insert or update on WSlot for each row execute procedure tg_wslot_biu(); -- ************************************************************ -- * AFTER UPDATE on PField -- * - Let PSlots of this field follow -- ************************************************************ create function tg_pfield_au() returns trigger as ' if !$Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("update PSlot set pfname = $1 where pfname = $2", ["text", "text"]).save end if new["name"] != old["name"] $Plans[tg["name"]].exec([new["name"], old["name"]]) end PL::OK ' language 'plruby'; create trigger tg_pfield_au after update on PField for each row execute procedure tg_pfield_au(); -- ************************************************************ -- * AFTER DELETE on PField -- * - Remove all slots of this patchfield -- ************************************************************ create function tg_pfield_ad() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("delete from PSlot where pfname = $1", ["text"]).save end $Plans[tg["name"]].exec([old["name"]]) PL::OK ' language 'plruby'; create trigger tg_pfield_ad after delete on PField for each row execute procedure tg_pfield_ad(); -- ************************************************************ -- * BEFORE INSERT or UPDATE on PSlot -- * - Ensure that our patchfield does exist -- ************************************************************ create function tg_pslot_biu() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("select count(*) as cnt from PField where name = $1", ["text"]).save end if ! $Plans[tg["name"]].exec([new["name"]], 1)["cnt"] raise "Patchfield #{new[''name'']} does not exist" end PL::OK ' language 'plruby'; create trigger tg_pslot_biu before insert or update on PSlot for each row execute procedure tg_pslot_biu(); -- ************************************************************ -- * AFTER UPDATE on System -- * - If system name changes let interfaces follow -- ************************************************************ create function tg_system_au() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("update IFace set sysname = $1 where sysname = $2", ["text", "text"]).save end if new["name"] != old["name"] $Plans[tg["name"]].exec([new["name"], old["name"]]) end PL::OK ' language 'plruby'; create trigger tg_system_au after update on System for each row execute procedure tg_system_au(); -- ************************************************************ -- * BEFORE INSERT or UPDATE on IFace -- * - set the slotname to IF.sysname.ifname -- ************************************************************ create function tg_iface_biu() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("select count(*) as cnt from system where name = $1", ["text"]).save end if ! $Plans[tg["name"]].exec([new["sysname"]], 1)["cnt"] raise "system #{new[''sysname'']} does not exist" end sname = "IF.#{new[''sysname'']}.#{new[''ifname'']}" if sname.size > 20 raise "IFace slotname #{sname} too long (20 char max)" end new["slotname"] = sname new ' language 'plruby'; create trigger tg_iface_biu before insert or update on IFace for each row execute procedure tg_iface_biu(); -- ************************************************************ -- * AFTER INSERT or UPDATE or DELETE on Hub -- * - insert/delete/rename slots as required -- ************************************************************ create function tg_hub_a() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("update HSlot set hubname = $1 where hubname = $2", ["varchar", "varchar"]).save end case tg["op"] when PL::INSERT hub_adjustslots(new["name"], 0, new["nslots"].to_i) when PL::UPDATE if old["name"] != new["name"] $Plans[tg["name"]].exec([new["name"], old["name"]]) end hub_adjustslots(new["name"], old["nslots"].to_i, new["nslots"].to_i) when PL::DELETE hub_adjustslots(old["name"], old["nslots"].to_i, 0) end PL::OK ' language 'plruby'; create trigger tg_hub_a after insert or update or delete on Hub for each row execute procedure tg_hub_a(); -- ************************************************************ -- * BEFORE INSERT or UPDATE on HSlot -- * - prevent from manual manipulation -- * - set the slotname to HS.hubname.slotno -- ************************************************************ create function tg_hslot_biu() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("select * from Hub where name = $1", ["varchar"]).save end hubrec = $Plans[tg["name"]].exec([new["hubname"]],1) if !hubrec || new["slotno"].to_i < 1 || new["slotno"].to_i > hubrec["nslots"].to_i raise "no manual manipulation of HSlot" end if (tg["og"] == PL::UPDATE) && (new["hubname"] != old["hubname"]) && $Plans[tg["name"]].exec([old["hubname"]], 1) raise "no manual manipulation of HSlot" end sname = "HS.#{new[''hubname'']}.#{new[''slotno'']}" if sname.size > 20 raise "HSlot slotname #{sname} too long (20 char max)" end new["slotname"] = sname new ' language 'plruby'; create trigger tg_hslot_biu before insert or update on HSlot for each row execute procedure tg_hslot_biu(); -- ************************************************************ -- * BEFORE DELETE on HSlot -- * - prevent from manual manipulation -- ************************************************************ create function tg_hslot_bd() returns trigger as ' if ! $Plans.key?(tg["name"]) $Plans[tg["name"]] = PL::Plan.new("select * from Hub where name = $1", ["varchar"]).save end hubrec = $Plans[tg["name"]].exec([old["hubname"]],1) if !hubrec || old["slotno"].to_i > hubrec["nslots"].to_i return PL::OK end raise "no manual manipulation of HSlot" ' language 'plruby'; create trigger tg_hslot_bd before delete on HSlot for each row execute procedure tg_hslot_bd(); -- ************************************************************ -- * BEFORE INSERT on all slots -- * - Check name prefix -- ************************************************************ create function tg_chkslotname() returns trigger as ' if new["slotname"][0, 2] != args[0] raise "slotname must begin with #{args[0]}" end PL::OK ' language 'plruby'; create trigger tg_chkslotname before insert on PSlot for each row execute procedure tg_chkslotname('PS'); create trigger tg_chkslotname before insert on WSlot for each row execute procedure tg_chkslotname('WS'); create trigger tg_chkslotname before insert on PLine for each row execute procedure tg_chkslotname('PL'); create trigger tg_chkslotname before insert on IFace for each row execute procedure tg_chkslotname('IF'); create trigger tg_chkslotname before insert on PHone for each row execute procedure tg_chkslotname('PH'); -- ************************************************************ -- * BEFORE INSERT or UPDATE on all slots with slotlink -- * - Set slotlink to empty string if NULL value given -- ************************************************************ create function tg_chkslotlink() returns trigger as ' if ! new["slotlink"] new["slotlink"] = "" return new end PL::OK ' language 'plruby'; create trigger tg_chkslotlink before insert or update on PSlot for each row execute procedure tg_chkslotlink(); create trigger tg_chkslotlink before insert or update on WSlot for each row execute procedure tg_chkslotlink(); create trigger tg_chkslotlink before insert or update on IFace for each row execute procedure tg_chkslotlink(); create trigger tg_chkslotlink before insert or update on HSlot for each row execute procedure tg_chkslotlink(); create trigger tg_chkslotlink before insert or update on PHone for each row execute procedure tg_chkslotlink(); -- ************************************************************ -- * BEFORE INSERT or UPDATE on all slots with backlink -- * - Set backlink to empty string if NULL value given -- ************************************************************ create function tg_chkbacklink() returns trigger as ' if ! new["backlink"] new["backlink"] = "" return new end PL::OK ' language 'plruby'; create trigger tg_chkbacklink before insert or update on PSlot for each row execute procedure tg_chkbacklink(); create trigger tg_chkbacklink before insert or update on WSlot for each row execute procedure tg_chkbacklink(); create trigger tg_chkbacklink before insert or update on PLine for each row execute procedure tg_chkbacklink(); -- ************************************************************ -- * BEFORE UPDATE on PSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_pslot_bu() returns trigger as ' if ! $Plans.key?("pslot_bu_del") $Plans["pslot_bu_del"] = PL::Plan.new("delete from PSlot where slotname = $1", ["varchar"]).save $Plans["pslot_bu_ins"] = PL::Plan.new("insert into PSlot (slotname, pfname, slotlink, backlink) values ($1, $2, $3, $4)", ["varchar", "varchar", "varchar", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["pslot_bu_del"].exec([old["slotname"]]) $Plans["pslot_bu_ins"].exec([new["slotname"], new["pfname"], new["slotlink"], new["backlink"]]) return PL::SKIP end PL::OK ' language 'plruby'; create trigger tg_pslot_bu before update on PSlot for each row execute procedure tg_pslot_bu(); -- ************************************************************ -- * BEFORE UPDATE on WSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_wslot_bu() returns trigger as ' if ! $Plans.key?("wslot_bu_del") $Plans["wslot_bu_del"] = PL::Plan.new("delete from WSlot where slotname = $1", ["varchar"]).save $Plans["wslot_bu_ins"] = PL::Plan.new("insert into WSlot (slotname, roomno, slotlink, backlink) values ($1, $2, $3, $4)", ["varchar", "int4", "varchar", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["wslot_bu_del"].exec([old["slotname"]]) $Plans["wslot_bu_ins"].exec([new["slotname"], new["roomno"], new["slotlink"], new["backlink"]]) return PL::SKIP end PL::OK ' language 'plruby'; create trigger tg_wslot_bu before update on WSlot for each row execute procedure tg_Wslot_bu(); -- ************************************************************ -- * BEFORE UPDATE on PLine -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_pline_bu() returns trigger as ' if ! $Plans.key?("pline_bu_del") $Plans["pline_bu_del"] = PL::Plan.new("delete from Pline where slotname = $1", ["varchar"]).save $Plans["pline_bu_ins"] = PL::Plan.new("insert into Pline (slotname, phonenumber, comment, backlink) values ($1, $2, $3, $4)", ["varchar", "int4", "varchar", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["pline_bu_del"].exec([old["slotname"]]) $Plans["pline_bu_ins"].exec([new["slotname"], new["phonenumber"], new["comment"], new["backlink"]]) return PL::SKIP end PL::OK ' language 'plruby'; create trigger tg_pline_bu before update on PLine for each row execute procedure tg_pline_bu(); -- ************************************************************ -- * BEFORE UPDATE on IFace -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_iface_bu() returns trigger as ' if ! $Plans.key?("iface_bu_del") $Plans["iface_bu_del"] = PL::Plan.new("delete from Iface where slotname = $1", ["varchar"]).save $Plans["iface_bu_ins"] = PL::Plan.new("insert into Iface (slotname, sysname, ifname, slotlink) values ($1, $2, $3, $4)", ["varchar", "varchar", "varchar", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["iface_bu_del"].exec([old["slotname"]]) $Plans["iface_bu_ins"].exec([new["slotname"], new["sysname"], new["ifname"], new["slotlink"]]) return PL::SKIP end PL::OK ' language 'plruby'; create trigger tg_iface_bu before update on IFace for each row execute procedure tg_iface_bu(); -- ************************************************************ -- * BEFORE UPDATE on HSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_hslot_bu() returns trigger as ' if ! $Plans.key?("hslot_bu_del") $Plans["hslot_bu_del"] = PL::Plan.new("delete from Hslot where slotname = $1", ["varchar"]).save $Plans["hslot_bu_ins"] = PL::Plan.new("insert into Hslot (slotname, hubname, slotno, slotlink) values ($1, $2, $3, $4)", ["varchar", "varchar", "int4", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["hslot_bu_del"].exec([old["slotname"]]) $Plans["hslot_bu_ins"].exec([new["slotname"], new["hubname"], new["slotno"], new["slotlink"]]) return PL::SKIP end PL::OK ' language 'plruby'; create trigger tg_hslot_bu before update on HSlot for each row execute procedure tg_hslot_bu(); -- ************************************************************ -- * BEFORE UPDATE on PHone -- * - do delete/insert instead of update if name changes -- ************************************************************ create function tg_phone_bu() returns trigger as ' if ! $Plans.key?("phone_bu_del") $Plans["phone_bu_del"] = PL::Plan.new("delete from Phone where slotname = $1", ["varchar"]).save $Plans["phone_bu_ins"] = PL::Plan.new("insert into Phone (slotname, comment, slotlink) values ($1, $2, $3)", ["varchar", "varchar", "varchar"]).save end if new["slotname"] != old["slotname"] $Plans["phone_bu_del"].exec([old["slotname"]]) $Plans["phone_bu_ins"].exec([new["slotname"], new["comment"], new["slotlink"]]) return PL::SKIP end ' language 'plruby'; create trigger tg_phone_bu before update on PHone for each row execute procedure tg_phone_bu(); -- ************************************************************ -- * AFTER INSERT or UPDATE or DELETE on slot with backlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ create function tg_backlink_a() returns trigger as ' case tg["op"] when PL::INSERT if ! new["backlink"].empty? backlink_set(new["backlink"], new["slotname"]) end when PL::UPDATE if new["backlink"] != old["backlink"] if ! old["backlink"].empty? backlink_unset(old["backlink"], old["slotname"]) end if ! new["backlink"].empty? backlink_set(new["backlink"], new["slotname"]) end else if new["slotname"] != old["slotname"] && ! new["backlink"].empty? slotlink_set(new["backlink"], new["slotname"]) end end when PL::DELETE if ! old["backlink"].empty? backlink_unset(old["backlink"], old["slotname"]); end end PL::OK ' language 'plruby'; create trigger tg_backlink_a after insert or update or delete on PSlot for each row execute procedure tg_backlink_a('PS'); create trigger tg_backlink_a after insert or update or delete on WSlot for each row execute procedure tg_backlink_a('WS'); create trigger tg_backlink_a after insert or update or delete on PLine for each row execute procedure tg_backlink_a('PL'); -- ************************************************************ -- * AFTER INSERT or UPDATE or DELETE on slot with slotlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ create function tg_slotlink_a() returns trigger as ' case tg["op"] when PL::INSERT if ! new["slotlink"].empty? slotlink_set(new["slotlink"], new["slotname"]) end when PL::UPDATE if new["slotlink"] != old["slotlink"] if ! old["slotlink"].empty? stlotlink_unset(old["slotlink"], old["slotname"]) end if ! new["slotlink"].empty? slotlink_set(new["slotlink"], new["slotname"]) end else if new["slotname"] != old["slotname"] && ! new["slotlink"].empty? slotlink_set(new["slotlink"], new["slotname"]) end end when PL::DELETE if ! old["slotlink"].empty? stlotlink_unset(old["slotlink"], old["slotname"]) end end PL::OK ' language 'plruby'; create trigger tg_slotlink_a after insert or update or delete on PSlot for each row execute procedure tg_slotlink_a('PS'); create trigger tg_slotlink_a after insert or update or delete on WSlot for each row execute procedure tg_slotlink_a('WS'); create trigger tg_slotlink_a after insert or update or delete on IFace for each row execute procedure tg_slotlink_a('IF'); create trigger tg_slotlink_a after insert or update or delete on HSlot for each row execute procedure tg_slotlink_a('HS'); create trigger tg_slotlink_a after insert or update or delete on PHone for each row execute procedure tg_slotlink_a('PH'); -- ************************************************************ -- * Describe the backside of a patchfield slot -- ************************************************************ create function pslot_backlink_view(varchar) returns text as ' if ! $Plans.key?("pslot_view") $Plans["pslot_view"] = PL::Plan.new("select * from PSlot where slotname = $1", ["varchar"]).save end rec = $Plans["pslot_view"].exec([args[0]], 1) return "" if ! rec return "-" if rec["backlink"].empty? bltype = rec["backlink"][0, 2] case bltype when "PL" rec = PL.exec("select * from PLine where slotname = ''#{rec[''backlink'']}''", 1) retval = "Phone line #{rec[''phonenumber''].strip}" if ! rec["comment"].empty? retval << " (#{rec[''comment'']})" end return retval when "WS" rec = PL.exec("select * from WSlot where slotname = ''#{rec[''backlink'']}''", 1) retval = "#{rec[''slotname''].strip} in room " retval << rec["roomno"].strip + " -> " rec = PL.exec("select wslot_slotlink_view(''#{rec[''slotname'']}''::varchar) as ws_result", 1) return retval + rec["ws_result"] end rec["backlink"] ' language 'plruby'; -- ************************************************************ -- * Describe the front of a patchfield slot -- ************************************************************ create function pslot_slotlink_view(varchar) returns text as ' if ! $Plans.key?("pslot_view") $Plans["pslot_view"] = PL::Plan.new("select * from PSlot where slotname = $1", ["varchar"]).save end rec = $Plans["pslot_view"].exec([args[0]], 1) return "" if ! rec return "-" if rec["slotlink"].empty? case rec["slotlink"][0, 2] when "PS" retval = rec["slotlink"].strip + " -> " rec = PL.exec("select pslot_backlink_view(''#{rec[''slotlink'']}''::varchar) as bac", 1) return retval + rec["bac"] when "HS" comm = PL.exec("select comment from Hub H, HSlot HS where HS.slotname = ''#{rec[''slotlink'']}'' and H.name = HS.hubname", 1) retval = "" if ! comm["comment"].empty? retval << comm["comment"] end retval << " slot " comm = PL.exec("select slotno from HSlot where slotname = ''#{rec[''slotlink'']}''", 1) return retval + comm["slotno"].to_s end rec["slotlink"] ' language 'plruby'; -- ************************************************************ -- * Describe the front of a wall connector slot -- ************************************************************ create function wslot_slotlink_view(varchar) returns text as ' if ! $Plans.key?("wslot_view") $Plans["wslot_view"] = PL::Plan.new("select * from WSlot where slotname = $1", ["varchar"]).save end rec = $Plans["wslot_view"].exec([args[0]], 1) return "" if ! rec return "-" if rec["slotlink"].empty? case rec["slotlink"][0, 2] when "PH" rec = PL.exec("select * from PHone where slotname = ''#{rec[''slotlink'']}''", 1) retval = "Phone " + rec["slotname"].strip if ! rec["comment"].empty? retval << " (#{rec[''comment'']})" end return retval when "IF" ifrow = PL.exec("select * from IFace where slotname = ''#{rec[''slotlink'']}''", 1) syrow = PL.exec("select * from System where name = ''#{ifrow[''sysname'']}''", 1) retval = syrow["name"] + " IF " + ifrow["ifname"] if ! syrow["comment"].empty? retval << " (#{syrow[''comment'']})" end return retval end rec["slotlink"] ' language 'plruby'; -- ************************************************************ -- * View of a patchfield describing backside and patches -- ************************************************************ create view Pfield_v1 as select PF.pfname, PF.slotname, pslot_backlink_view(PF.slotname) as backside, pslot_slotlink_view(PF.slotname) as patch from PSlot PF; -- -- -- create table plruby_singleton_methods ( name varchar(60), args varchar(60), body text, comment text ); create unique index plr_s_m_i on plruby_singleton_methods (name); insert into plruby_singleton_methods values ('hub_adjustslots', 'name, oldsl, newsl', ' if ! $Plans.key?("hub_adjust_del") $Plans["hub_adjust_del"] = PL::Plan.new("delete from HSlot where hubname = $1 and slotno > $2", ["varchar", "int4"]).save $Plans["hub_adjust_ins"] = PL::Plan.new("insert into HSlot (slotname, hubname, slotno, slotlink) values ($1, $2, $3, $4)", ["varchar", "varchar", "int4", "varchar"]).save end return if oldsl == newsl if newsl < oldsl $Plans["hub_adjust_del"].exec([name, newsl]) else (oldsl+1).upto(newsl) do |x| $Plans["hub_adjust_ins"].exec(["HS.dummy", name, x, ""]) end end ', 'Support function to add/remove slots of Hub'); insert into plruby_singleton_methods values ('backlink_set', 'myname, blname', ' mytype = myname[0, 2] link = mytype + blname[0, 2] if link == "PLPL" raise "backlink between two phone lines does not make sense" end if link == "PLWS" || link == "WSPL" raise "direct link of phone line to wall slot not permitted" end rel = case mytype when "PS" "PSlot" when "WS" "WSlot" when "PL" "PLine" else raise "illegal backlink beginning with #{mytype}" end rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1) if ! rec raise "#{myname} does not exist in #{rel}" end if rec["backlink"] != blname PL.exec("update #{rel} set backlink = ''#{blname}'' where slotname = ''#{myname}''") end ', ' Support function to set the opponents backlink field if it does not already point to the requested slot'); insert into plruby_singleton_methods values ('backlink_unset' , 'myname, blname', ' rel = case myname[0, 2] when "PS" "PSlot" when "WS" "WSlot" when "PL" "PLine" else raise "illegal backlink beginning with #{myname[0, 2]}" end rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1) return if ! rec if rec["backlink"] == blname PL.exec("update #{rel} set backlink = '''' where slotname = ''#{myname}''") end ', ' Support function to clear out the backlink field if it still points to specific slot'); insert into plruby_singleton_methods values ('slotlink_set', 'myname, blname', ' mytype = myname[0, 2] link = mytype + blname[0, 2] if link == "PHPH" raise "slotlink between two phones does not make sense" end if link == "PHHS" || link == "HSPH" raise "link of phone to hub does not make sense" end if link == "PHIF" || link == "IFPH" raise "link of phone to hub does not make sense" end if link == "PSWS" || link == "WSPS" raise "slotlink from patchslot to wallslot not permitted" end rel = case mytype when "PS" "PSlot" when "WS" "WSlot" when "IF" "IFace" when "HS" "HSlot" when "PH" "PHone" else raise "illegal slotlink beginning with <#{mytype}>" end rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1) if ! rec raise "#{myname} does not exists in #{rel}" end if rec["slotlink"] != blname PL.exec("update #{rel} set slotlink = ''#{blname}'' where slotname = ''#{myname}''") end ', ' Support function to set the opponents slotlink field if it does not already point to the requested slot'); insert into plruby_singleton_methods values ('slotlink_unset', 'myname, blname', ' rel = case myname[0, 2] when "PS" "PSlot" when "WS" "WSlot" when "IF" "IFace" when "HS" "HSlot" when "PH" "PHone" else raise "illegal slotlink beginning with #{myname[0, 2]}" end rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1) return if ! rec if rec["slotlink"] == blname PL.exec("update #{rel} set slotlink = '''' where slotname = ''#{myname}''") end ', ' Support function to clear out the slotlink field if it still points to specific slot');