I have Progress code which runs a procedure.
RUN myProc.
The procedure could be defined in the current external procedure, one of its super-procedures, the super-procedure of that one, the session super-procedure, etc. I understand that I cannot know until run-time where the procedure is defined because new super-procedures can be added at run-time.
Is there a way to know at run-time where (in what file) the procedure is defined?
You can iterate THIS-PROCEDURE:SUPER-PROCEDURES and SESSION:SUPER-PROCEDURES. Both are comma delimited lists of procedure handles.
Every handle in that list has an property INTERNAL-ENTRIES which is a comma delimited list of internal procedure names.
You could just step through the code in the debugger and see where that gets you. (I'm not sure if you need to know the file in your code, but I can't see why that would be necessary.)
Related
In my application I have multiple variables that need to be accessed globally from the different functions of my script:
var a=1,b=2,c, ...;
Where "c" undefined at the beginning and takes value produced by some of the functions during scripts execution.
In order to declare them from within my "main" function I'm trying to use window object:
window.a=1;
window.b=2;
window.c;
This works, however I'm not sure if such approach is correct.
And is there is a way to avoid creation multiple window objects for each variable and combine them into more compact structure? Something like:
window.a=1,.b=2,.c;//---of course-this doesn't work
I was asking this question today too. It used to be the way when I last wrote javascript (mid-90s) and still seems to be the case see this resource
I need to call a stored procedure multiple times with different parameters at every call ...
So I have created a macro having definition like below to perform the desired operation.
However, it seems macro can not contain a multi statement request.
So is there any work-around available to have these multiple calls in macro ? Or can a stored procedure be a good option for this operation ?
Please advise.
Thank you !
CREATE MACRO m_Snapshot AS
(
CALL sp_Test('A',0);
CALL sp_Test('B',0);
CALL sp_Test('C',0);
);
I recognized that (insert/delete)-XQueries executed with the BaseX client always returning an empty string. I find this very confusing or unintuitive.
Is there a way to find out if the query was "successful" without querying the database again (and using potentially buggy "transitive" logic like "if I deleted a node, there must be 'oldNodeCount-1' nodes in the XML")?
XQuery Update statements do not return anything -- that's how they are defined. But you're not the only one who does not like those restrictions, and BaseX added two ways around this limitation:
Returning Results
By default, it is not possible to mix different types of expressions
in a query result. The outermost expression of a query must either be
a collection of updating or non-updating expressions. But there are
two ways out:
The BaseX-specific update:output() function bridges this gap: it caches the results of its arguments at runtime and returns them after
all updates have been processed. The following example performs an
update and returns a success message:
update:output("Update successful."), insert node <c/> into doc('factbook')/mondial
With the MIXUPDATES option, all updating constraints will be turned off. Returned nodes will be copied before they are modified by
updating expressions. An error is raised if items are returned within
a transform expression.
If you want to modify nodes in main memory, you can use the transform
expression.
The transform expression will not help you, as you seem to modify the data on disk. Enabling MIXUPDATES allows you to both update the document and return something at the same time, for example running something like
let $node := <c/>
return ($node, insert node $node into doc('factbook')/mondial)
MIXUPDATES allows you to return something which can be further processed. Results are copied before being returned, if you run multiple updates operations and do not get the expected results, make sure you got the concept of the pending update list.
The db:output() function intentionally breaks its interface contract: it is defined to be an updating function (not having any output), but at the same time it prints some information to the query info. You cannot further process these results, but the output can help you debugging some issues.
Pending Update List
Both ways, you will not be able to have an immediate result from the update, you have to add something on your own -- and be aware updates are not visible until the pending update list is applied, ie. after the query finished.
Compatibility
Obviously, these options are BaseX-specific. If you strongly require compatible and standard XQuery, you cannot use these expressions.
I recognized that (insert/delete)-XQueries executed with the BaseX client always returning an empty string. I find this very confusing or unintuitive.
Is there a way to find out if the query was "successful" without querying the database again (and using potentially buggy "transitive" logic like "if I deleted a node, there must be 'oldNodeCount-1' nodes in the XML")?
XQuery Update statements do not return anything -- that's how they are defined. But you're not the only one who does not like those restrictions, and BaseX added two ways around this limitation:
Returning Results
By default, it is not possible to mix different types of expressions
in a query result. The outermost expression of a query must either be
a collection of updating or non-updating expressions. But there are
two ways out:
The BaseX-specific update:output() function bridges this gap: it caches the results of its arguments at runtime and returns them after
all updates have been processed. The following example performs an
update and returns a success message:
update:output("Update successful."), insert node <c/> into doc('factbook')/mondial
With the MIXUPDATES option, all updating constraints will be turned off. Returned nodes will be copied before they are modified by
updating expressions. An error is raised if items are returned within
a transform expression.
If you want to modify nodes in main memory, you can use the transform
expression.
The transform expression will not help you, as you seem to modify the data on disk. Enabling MIXUPDATES allows you to both update the document and return something at the same time, for example running something like
let $node := <c/>
return ($node, insert node $node into doc('factbook')/mondial)
MIXUPDATES allows you to return something which can be further processed. Results are copied before being returned, if you run multiple updates operations and do not get the expected results, make sure you got the concept of the pending update list.
The db:output() function intentionally breaks its interface contract: it is defined to be an updating function (not having any output), but at the same time it prints some information to the query info. You cannot further process these results, but the output can help you debugging some issues.
Pending Update List
Both ways, you will not be able to have an immediate result from the update, you have to add something on your own -- and be aware updates are not visible until the pending update list is applied, ie. after the query finished.
Compatibility
Obviously, these options are BaseX-specific. If you strongly require compatible and standard XQuery, you cannot use these expressions.
How is trigger function different from 'regular' functions? And is it absolutely necessary in creating a trigger?
For example, in this case:
-- Trigger function
CREATE FUNCTION update_record_trigger_function() RETURNS trigger
LANGUAGE plpgsql
AS $update_record_trigger_function$
BEGIN
PERFORM update_record(NEW.oid); -- helper function ...
RETURN NEW;
END
$update_record_trigger_function$;
-- Trigger for updating latest clicks for posts
CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW
EXECUTE PROCEDURE update_record_trigger_function();
Would it not be simpler to (or is it possible to do):
-- Trigger for updating latest clicks for posts
CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW
PERFORM update_record(NEW.oid); -- syntactically not right but along this idea
I wasn't able to find any document with examples of 'skipping trigger function' or one that explaining how trigger function is special and necessary for triggers?
PostgreSQL separates the "trigger function" from the trigger definition for quite a few reasons:
Trigger functions can be written as generic functions that can work on many different tables, so you can add the same trigger function as a trigger to many different tables. This eases maintenance.
Trigger functions can take parameters that allow them to adapt to specific column names or other characteristics of the table you apply them to. This makes it practical to write generic, re-usable trigger functions where you otherwise could not do so, so you often don't need to repeat the code in multiple places. See EXECUTE ... USING and the format function with its %L and %I format-specifiers.
PostgreSQL tries very hard not care what programming language your functions are written in . They could be PL/PgSQL, Python, Perl, C, or MyWackyPluginLanguage. If it didn't separate trigger function from trigger definition this would be harder to achieve.
The shorthand you describe is not supported in PostgreSQL, though some other database systems provide something very much like what you've shown. You essentially want to be able to define a trigger function as an inline expression. This isn't supported. There's never been a pressing need for it so nobody's implemented it.
If such a feature were added in future - and I'm not aware of any plans to do so - it would probably be done using a PL/PgSQL DO block that was contextually interpreted as a trigger, something like (not legal syntax):
CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW DO $$ PERFORM update_record(NEW.oid); RETURN NEW; $$;
That way the parser wouldn't need to understand PL/PgSQL constructs, we'd just have to teach it to understand FOR EACH ROW DO [string literal body of function] as an alternative to FOR EACH ROW EXECUTE PROCEDURE proc_name(args) and then invoke the PL/PgSQL subsystem to process the trigger literal.
In practice Pg would probably just generate an ordinary trigger function and add a reference to it from the trigger so it's dropped if the trigger was dropped, making this a just convenience macro, just like SERIAL is a convenience macro for an INTEGER field with a DEFAULT nextval(...) and a generated SEQUENCE owned by the table with the SERIAL field. In particular, pg_dump would probably output it as if you'd defined a separate trigger function and trigger, rather than used the shorthand.
Honestly, I doubt anything like this will ever be added, but if you can provide sufficiently convincing use cases you might if you're really lucky interest someone in it. Most likely you'll only get anywhere with such a proposal ("allow DO blocks to be used as trigger procedures") if you're willing to back it with funding for the time required to implement the feature.