passing parameters between forms - forms

Hi everyone i'm trying to passing parameters between forms but i have this error:
frm-92101 there was a failure in the forms server during startup.
I wanna place a button on the EMPLOYEE form that when pressed, will call the EMPLOYEE/DEPENDENT form and automatically query the dependents for the employee being viewed on the EMPLOYEE form.
Icreated the EMPLOYEE Form and add a button.I assigned a trigger when bouton pressed :
DECLARE
pl_id ParamList;
BEGIN
pl_id := Get_Parameter_List('tmpdata');
IF NOT Id_Null(pl_id) THEN
Destroy_Parameter_List( pl_id );
END IF;
pl_id := Create_Parameter_List('tmpdata');
Add_Parameter(pl_id, 'EMPLOYEESSN', TEXT_PARAMETER, :SSN);
Run_Product(FORMS, 'empdepn', SYNCHRONOUS, RUNTIME,
FILESYSTEM, pl_id, NULL);
END;
After that i add a parameter into the EMPLOYEE/DEPENDENT
I created a PARAMETER called EMPLOYEESSN with the code bellow and add a parameter EMPLOYEESSN and add a WHEN-NEW-FORM-INSTANCE trigger :
DECLARE
blk_id Block;
BEGIN
-- Obtain the block ID of the EMPLOYEE block. This is the
-- Master block in the empdepn master/detail form.
blk_id := Find_Block('EMPLOYEE');
IF NOT Id_Null(blk_id) THEN
-- Check to make sure our parameter has a value. If this form
-- were executed by itself, then the parameter will be null.
-- If this form is called from EMPLOYEE then the parameter will
-- be passed along and assigned to: PARAMETER.employeessn
IF (:PARAMETER.employeessn is not null) THEN
-- Since we have a parameter, use it to alter the WHERE Clause
-- property so that it becomes WHERE ssn=:PARAMETER.employeessn
SET_BLOCK_PROPERTY(blk_id,DEFAULT_WHERE,'ssn=' || : PARAMETER.employeessn);
-- Navigate to the EMPLOYEE block and execute a query automatically
GO_BLOCK('EMPLOYEE');
EXECUTE_QUERY;
END IF;
END IF;
END;
Any idea please, thanks for help

Related

PGSQL: Function argument not being passed correctly

I am attempting to search the "message" column of a table for any instance of a tag mentioned (like " #testing1 " for example).
When I manually enter the query it works but I think that I'm not understanding how to concat the tag properly:
This works:
select amount from donations where message like #testing1
But this does not:
CREATE OR REPLACE FUNCTION sum_tag(
tag TEXT)
RETURNS VOID AS $$
BEGIN
select amount from donations where message like CONCAT ('%#', tag, '%');
END; $$
LANGUAGE plpgsql;
The above is what is in the begin and end statements inside of the function sum_tag(tag text).
My intent is that I am trying to capture the tag whether it is in the message as "#testing1 this is a message" or "This is a message #testing1" and then use that as an identifier to sum up all of the amount column values for the associated rows.
Update 1
I have attempted to use the suggestion as noted in the comments but It did not seem to work. The updated function was entered as:
CREATE OR REPLACE FUNCTION sum_tag(
tag TEXT)
RETURNS VOID AS $$
BEGIN
EXECUTE format('select amount from donations where message like %s', tag);
END; $$
LANGUAGE plpgsql;
This did not work either. If I am understanding, the entire statement needs to be in single quotes and %s is the correct way to call the argument as it is a text string. I appreciate your explanation and places to look.

Access object on another form with the form as a variable

I'm writing a program in Delphi which includes creating the same dynamic object on multiple forms (never simultaneously), and then a procedure in another unit writes certain text to it.
How the object (TMemo) is created:
memHulp := TMemo.Create(frmHome);
with memHulp do
begin
Parent := frmHome;
Top := 208;
Left := 88;
Height := 98;
Width := 209;
ReadOnly := True;
end;
The properties aren't that important, it's just to show the creation of the object and how it is referred to.
Now, I need to read certain text into the memo from a text file, which there is no problem with, but the problem comes when there are different forms involved that all use that same self-defined procedure.
It's easy to say frmHome.memHulp.Lines.Add() in this particular case, but when I need it to display the text on the memo named exactly the same in all cases, but on a different form, I'm having some trouble.
The frmHome part needs to be a variable. So I tried this:
var
Form: TForm;
begin
Form := Application.FindComponent('frmHome') as TForm;
end;
That doesn't warn me or give an error, but as soon as I try to say Form.memHulp.Lines.Add(), it does not work, and I understand that it probably doesn't have any properties for Form, but how do I make it look at the correct place? I need to be able to tell the program to look on whichever form name I pass as a parameter into the FindComponent() part.
If this is completely not possible, please suggest other solutions to achieve the same.
Form.memHulp doesn't work because Form is a plain vanilla TForm pointer, and TForm doesn't have a memHulp member. You could use Form.FindComponent('memHulp') instead, since you are assigning the TForm object as the Memo's Owner, but that would require you to assign a Name to the Memo, eg:
memHulp := TMemo.Create(frmHome);
with memHulp do
begin
Parent := frmHome;
Name := 'memHulp';
...
end;
Alternatively, since you say you are creating only 1 Memo object at a time, you could simply make memHulp be a global variable in some unit's interface section, and then you would have direct access to it without having to hunt for it.

How to send event to multiple forms in Delphi

In my application I have multiple forms that can be visible at the same time and they all show disk space (files, hard disk size etc.) in the same size units. So all of them show disk space in Bytes, KB, MB, GB or TB. I also have a seperate settings form in which the user can change the display size, he wants in the other forms. Once the user clicks OK in the settings form, I want all the other (open) forms to immediately change their size settings.
Every form has a protected procedure SetViewSettings, which takes care of the job. They are all descendants of an ancestor form which defines SetViewSettings as virtual and abstract. The actual displayed forms override the SetViewSettings method of the ancestor. So far no problems.
Because I don't want to call every individual form (FormX.SetViewSetttings, FormY.SetViewSettings, etc.), I am using the following solution:
procedure TApplicationForms.SetUnits;
var
I: Integer;
begin
for I := 0 to Screen.FormCount - 1 do
if Screen.Forms[I] is TfrAncestorInfo then
with Screen.Forms[I] as TfrAncestorInfo do
acSetUnits.Execute;
end;
This procedure is called from the SettingsForm as the user clicks OK.
TFrAncestorInfo is a descendant of TForm, declaring the SetViewSettings method as virtual and abstract. acSetUnits is an Action, declared in TfrAncestorInfo, which only calls SetViewSettings. This all works fine, but the risk lies in creating a new descendant form of TFrAncestorInfo, whilest forgetting to override the SetViewSettings method, in which case you will run into an 'Abstract Error' exception.
Are there any alternatives to calling the SetViewSettings method in the forms, without listing (calling) all the descendant forms individually? I know of messages and events, but I don't know how to use these in a multiple forms situation. In general: how can I directly send a message to or generate an event for all TFrAncestorInfo descendant forms, without listing them individually?
One option (there are many other possible options) would be to send a custom message to every Form. No need for worry about virtual/abstract overriding, type checking, etc. Only the Forms that implement a message handler will react to the message, the rest will simply ignore it.
const
WM_SETTINGS_UPDATED = WM_APP + 1;
procedure TApplicationForms.SetUnits;
var
I: Integer;
begin
for I := 0 to Screen.FormCount - 1 do
Screen.Forms[I].Perform(WM_SETTINGS_UPDATED, 0, 0);
end;
type
TSomeForm = class(TBaseForm)
private
procedure WMSettingsUpdated(var Message: TMessage); message WM_SETTINGS_UPDATED;
protected
procedure SetViewSettings;
end;
procedure TSomeForm.WMSettingsUpdated(var Message: TMessage);
begin
SetViewSettings;
end;
procedure TSomeForm.SetViewSettings;
begin
//...
end;

PL/pgSQL , How to make a function using Raise notices and export the messages from the console to a text file from the Code

I have to make a update function that have multiple conditions like this
BEGIN
OPEN cur3 FOR execute('select id_organigramme from ( select distinct id_personne,id_organigramme,idfax from requpdate where
id_personne= ' || VariableIDpersonne || ' and idfax is null) a where
a.id_organigramme not in (select distinct id_organigramme from
requpdate where id_personne= ' ||VariableIDpersonne || ' and idfax is
not null and a.id_personne=requpdate.id_personne ) ');
LOOP
FETCH cur3 INTO VariableIDorganigrammeFax;
if not found then
--Message here !!!
--Raise notice 'hello word!'
exit;
end if;
I have to show up messages if any condition exists I found out that I can do this with Raise Notice/info ... statement, but I have to make auto export of those messages into a text file when the function finishes.
Is this possible? Otherwise what can I use to make it.
I use PGAdminIII as a client.
What your logging options are depends entirely on your client configuration. But rather than using RAISE NOTICE I would suggest you use the NOTIFY \ LISTEN framework. Basically, in your function you issue a notice to a channel of your choosing (can be any string) and in your client you listen to that same channel, logging the messages as they come in. How exactly the listening and logging works depends on your client.
The code you show can also you use some improvements.
First of all, your query is an incredibly convoluted version of:
SELECT DISTINCT id_organigramme
FROM requpdate
WHERE id_personne = VariableIDpersonne
AND idfax IS NULL;
Secondly, you do not need a dynamic query, you can get by with variable substitution. Assuming id_personne is not a string, it is as simple as stated above, otherwise use quote_literal(VariableIDpersonne).
Lastly, unless there are parts of your function not shown that require a cursor, you can simply do:
FOR VariableIDorganigrammeFax IN [query above]
LOOP
... -- do your processing here
END LOOP;
IF NOT FOUND THEN -- the loop above did not iterate because no records were returned
SELECT pg_notify('logMyFunction', format('%s: No records found', VariableIDpersonne));
END IF;
The pg_notify() function is a wrapper around the NOTIFY command that makes it possible to pass variable strings.
Before you call the function, you should issue the command LISTEN logMyFunction so that your session will receive the notifications from the channel.

Is there anyway to reference the collection of parameters passed to a stored procedure, without referencing each one by name?

Is there any way to reference the collection of parameters passed to a stored proc, without referencing each one by name?
The context here is error logging. I'd like to develop a generic CATCH clause, or sub-clause, that grabs all parameter values as well as other error and execution info and logs it to a table (one or more).
The basic version looks something like this:
CREATE PROC dbo.Proc1 #Param1 INT, #Param2 INT
AS
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
DECLARE #params XML
SET #params = (
SELECT
#Param1 AS [Param1]
, #Param2 AS [Param2]
FOR XML PATH('params'), TYPE
)
EXEC dbo.LogError #procid = ##PROCID, #params = #params
EXEC dbo.RethrowError
END CATCH
Now, this template does work, except that for each individual procedure, I would have to edit the SET #params section manually.
I could script it out easily enough, but then I would still need to copy it in.
I could leave some sort of placeholder, and then dynamically update each definition w/ a correct SET statement. I could even write a database trigger that listens for CREATE and ALTER PROC statements and have it do this for me automagically.
But what I really want is just to grab the collection of parameters directly and be done with it. Is there any way?
EDIT: getting parameter metadata from the system tables is not enough. For example:
DECLARE #sql NVARCHAR(MAX)
SET #sql =
'SET #params = (SELECT '
+ STUFF((
SELECT ', '+name+' AS '+STUFF(name,1,1,'')
FROM sys.parameters WHERE object_id = ##PROCID
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
,1,2,'')
+ ' FOR XML PATH(''params''), TYPE)'
-- inline execute here....alas, there's isn't a mode for that
EXEC sp_executesql #sql, N'#params XML OUTPUT', #params OUTPUT
This, of course, generates an error, since I haven't declared parameters for the nested scope of sp_executesql. While I could script out the second param of sp_executesql, I can't assign them without explicitly assigning them one at a time by name.
Original question, rephrased: is there another flavor of sp_executesql that inherits variable "context" from the outer scope, that executes in the same frame, that inlines the command, rather than executing in a nested scope?
Why not use sys.dm_exec_sql_text(#sql_handle) to retrieve the SQL command, using sys.sysprocesses.sql_handle?