-- procedure refresh_trigger select define_function_args('content_type__refresh_trigger','content_type'); create or replace function content_type__refresh_trigger (varchar) returns integer as ' declare refresh_trigger__content_type alias for $1; rule_text text default ''''; function_text text default ''''; v_table_name acs_object_types.table_name%TYPE; type_rec record; begin -- get the table name for the content type (determines view name) raise NOTICE ''refresh trigger for % '', refresh_trigger__content_type; select table_name into v_table_name from acs_object_types where object_type = refresh_trigger__content_type; --=================== start building rule code ======================= function_text := function_text || ''create or replace function '' || v_table_name || ''_f (p_new ''|| v_table_name || ''i) returns void as '''' declare v_revision_id integer; begin select content_revision__new( p_new.title, p_new.description, now(), p_new.mime_type, p_new.nls_language, case when p_new.text is null then p_new.data else p_new.text end, content_symlink__resolve(p_new.item_id), p_new.revision_id, now(), p_new.creation_user, p_new.creation_ip, p_new.object_package_id ) into v_revision_id; ''; -- add an insert statement for each subtype in the hierarchy for this type for type_rec in select ot2.object_type, tree_level(ot2.tree_sortkey) as level from acs_object_types ot1, acs_object_types ot2 where ot2.object_type <> ''acs_object'' and ot2.object_type <> ''content_revision'' and ot1.object_type = refresh_trigger__content_type and ot1.tree_sortkey between ot2.tree_sortkey and tree_right(ot2.tree_sortkey) order by level asc LOOP function_text := function_text || '' '' || content_type__trigger_insert_statement(type_rec.object_type) || ''; ''; end loop; function_text := function_text || '' return; end;'''' language ''''plpgsql''''; ''; -- end building the rule definition code -- create the new function execute function_text; rule_text := ''create rule '' || v_table_name || ''_r as on insert to '' || v_table_name || ''i do instead SELECT '' || v_table_name || ''_f(new); '' ; --================== done building rule code ======================= -- drop the old rule if rule_exists(v_table_name || ''_r'', v_table_name || ''i'') then -- different syntax for dropping a rule in 7.2 and 7.3 so check which -- version is being used (olah). if version() like ''%PostgreSQL 7.2%'' then execute ''drop rule '' || v_table_name || ''_r''; else -- 7.3 syntax execute ''drop rule '' || v_table_name || ''_r '' || ''on '' || v_table_name || ''i''; end if; end if; -- create the new rule for inserts on the content type execute rule_text; return null; end;' language 'plpgsql'; -- function trigger_insert_statement select define_function_args('content_type__trigger_insert_statement','content_type'); create or replace function content_type__trigger_insert_statement (varchar) returns varchar as ' declare trigger_insert_statement__content_type alias for $1; v_table_name acs_object_types.table_name%TYPE; v_id_column acs_object_types.id_column%TYPE; cols varchar default ''''; vals varchar default ''''; attr_rec record; begin if trigger_insert_statement__content_type is null then return exception ''content_type__trigger_insert_statement called with null content_type''; end if; select table_name, id_column into v_table_name, v_id_column from acs_object_types where object_type = trigger_insert_statement__content_type; for attr_rec in select attribute_name from acs_attributes where object_type = trigger_insert_statement__content_type LOOP cols := cols || '', '' || attr_rec.attribute_name; vals := vals || '', p_new.'' || attr_rec.attribute_name; end LOOP; return ''insert into '' || v_table_name || '' ( '' || v_id_column || cols || '' ) values (v_revision_id'' || vals || '')''; end;' language 'plpgsql' stable; select define_function_args('content_type__refresh_view','content_type'); create or replace function content_type__refresh_view (varchar) returns integer as ' declare refresh_view__content_type alias for $1; cols varchar default ''''; tabs varchar default ''''; joins varchar default ''''; v_table_name varchar; join_rec record; begin for join_rec in select ot2.table_name, ot2.id_column, tree_level(ot2.tree_sortkey) as level from acs_object_types ot1, acs_object_types ot2 where ot2.object_type <> ''acs_object'' and ot2.object_type <> ''content_revision'' and lower(ot2.table_name) <> ''acs_objects'' and lower(ot2.table_name) <> ''cr_revisions'' and ot1.object_type = refresh_view__content_type and ot1.tree_sortkey between ot2.tree_sortkey and tree_right(ot2.tree_sortkey) order by ot2.tree_sortkey desc LOOP if join_rec.table_name is not null then cols := cols || '', '' || join_rec.table_name || ''.*''; tabs := tabs || '', '' || join_rec.table_name; joins := joins || '' and acs_objects.object_id = '' || join_rec.table_name || ''.'' || join_rec.id_column; end if; end loop; select table_name into v_table_name from acs_object_types where object_type = refresh_view__content_type; if length(v_table_name) > 25 then raise exception ''Table name cannot be longer than 25 characters, because that causes conflicting rules when we create the views.''; end if; -- create the input view (includes content columns) if table_exists(v_table_name || ''i'') then execute ''drop view '' || v_table_name || ''i'' || '' CASCADE''; end if; -- FIXME: need to look at content_revision__get_content. Since the CR -- can store data in a lob, a text field or in an external file, getting -- the data attribute for this view will be problematic. execute ''create view '' || v_table_name || ''i as select acs_objects.object_id, acs_objects.object_type, acs_objects.title as object_title, acs_objects.package_id as object_package_id, acs_objects.context_id, acs_objects.security_inherit_p, acs_objects.creation_user, acs_objects.creation_date, acs_objects.creation_ip, acs_objects.last_modified, acs_objects.modifying_user, acs_objects.modifying_ip, acs_objects.tree_sortkey, acs_objects.max_child_sortkey, cr.revision_id, cr.title, cr.item_id, content_revision__get_content(cr.revision_id) as data, cr_text.text_data as text, cr.description, cr.publish_date, cr.mime_type, cr.nls_language'' || cols || '' from acs_objects, cr_revisions cr, cr_text'' || tabs || '' where acs_objects.object_id = cr.revision_id '' || joins; -- create the output view (excludes content columns to enable SELECT *) if table_exists(v_table_name || ''x'') then execute ''drop view '' || v_table_name || ''x''; end if; execute ''create view '' || v_table_name || ''x as select acs_objects.object_id, acs_objects.object_type, acs_objects.title as object_title, acs_objects.package_id as object_package_id, acs_objects.context_id, acs_objects.security_inherit_p, acs_objects.creation_user, acs_objects.creation_date, acs_objects.creation_ip, acs_objects.last_modified, acs_objects.modifying_user, acs_objects.modifying_ip, acs_objects.tree_sortkey, acs_objects.max_child_sortkey, cr.revision_id, cr.title, cr.item_id, cr.description, cr.publish_date, cr.mime_type, cr.nls_language, i.name, i.parent_id'' || cols || '' from acs_objects, cr_revisions cr, cr_items i, cr_text'' || tabs || '' where acs_objects.object_id = cr.revision_id and cr.item_id = i.item_id'' || joins; PERFORM content_type__refresh_trigger(refresh_view__content_type); -- exception -- when others then -- dbms_output.put_line(''Error creating attribute view or trigger for'' -- || content_type); return 0; end;' language 'plpgsql'; create or replace function inline_0() returns integer as ' declare v_row record; begin for v_row in select distinct o.object_type,o.table_name from acs_object_type_supertype_map m, acs_object_types o where (m.ancestor_type=''content_revision'' and o.object_type=m.object_type) or (o.object_type=''content_revision'') loop if table_exists(v_row.table_name) then perform content_type__refresh_view(v_row.object_type); end if; end loop; return 0; end;' language 'plpgsql'; select inline_0(); drop function inline_0(); -- rebuild content search triggers to honor publish_date drop trigger content_search__itrg on cr_revisions; drop trigger content_search__dtrg on cr_revisions; drop trigger content_search__utrg on cr_revisions; drop trigger content_item_search__utrg on cr_items; drop function content_search__itrg(); drop function content_search__utrg(); drop function content_item_search__utrg(); create function content_search__itrg () returns opaque as ' begin if (select live_revision from cr_items where item_id=new.item_id) = new.revision_id and new.publish_date >= current_timestamp then perform search_observer__enqueue(new.revision_id,''INSERT''); end if; return new; end;' language 'plpgsql'; create or replace function content_search__utrg () returns opaque as ' declare v_live_revision integer; begin select into v_live_revision live_revision from cr_items where item_id=old.item_id; if old.revision_id=v_live_revision and new.publish_date <= current_timestamp then insert into search_observer_queue ( object_id, event ) values ( old.revision_id, ''UPDATE'' ); end if; return new; end;' language 'plpgsql'; -- we need new triggers on cr_items to index when a live revision -- changes -DaveB 2002-09-26 create function content_item_search__utrg () returns opaque as ' begin if new.live_revision is not null and coalesce(old.live_revision,0) <> new.live_revision and (select publish_date from cr_revisions where revision_id=new.live_revision) <= current_timestamp then perform search_observer__enqueue(new.live_revision,''INSERT''); end if; if old.live_revision is not null and old.live_revision <> coalesce(new.live_revision,0) then perform search_observer__enqueue(old.live_revision,''DELETE''); end if; if new.publish_status = ''expired'' then perform search_observer__enqueue(old.live_revision,''DELETE''); end if; return new; end;' language 'plpgsql'; create trigger content_search__itrg after insert on cr_revisions for each row execute procedure content_search__itrg (); create trigger content_search__dtrg after delete on cr_revisions for each row execute procedure content_search__dtrg (); create trigger content_search__utrg after update on cr_revisions for each row execute procedure content_search__utrg (); create trigger content_item_search__utrg before update on cr_items for each row execute procedure content_item_search__utrg ();