Timers
Question
--------
If a timer expires during a long running query when is it
handled ?
Answer
------
The timer will always wait to be handled until the current
operation has been completed. In other words, the query is
completed before the timer is serviced.
Question
--------
If a REPEAT timer expires between a long query, does it
repeat prior to being serviced by a WHEN-TIMER-EXPIRED at
the end of the query or does it wait for servicing before
repeating ?
Answer
------
A repeating timer will never be restarted until after it has
been serviced by an appropriate firing of
WHEN-TIMER-EXPIRED. A simple corollary to that fact is that
no timer can ever exist twice in the "timers to be serviced"
stack.
Trigger
Question
--------
What is the difference between the following triggers :
- Post-Fetch vs. Post_Query
- Post-Forms-Commit vs. Post-Database-Commit
- Pre-Query vs. Pre-Select
Answer
------
A comparison of these triggers follows :
Post-Fetch vs. Post-Query
POST-FETCH fires just after each attempt to fetch records
from the database. Depending on the value of "Array Size"
for the block in question, and how many records are
actually delivered from the database in response to our
request this trigger may fire fewer times.
In contrast, POST-QUERY fires once for *each* record that
is brought from the waiting area (where records first go
after their fetched in a bunch from the database) and
added to the end of the current block's list of records.
Post-Forms-Commit vs. Post-Database-Commit
POST-FORMS-COMMIT is the renamed version of POST-COMMIT
from V3. It fires as the last trigger which is still part
of the current transaction during commit-time processing
(ie before the actual 'COMMIT' has been issued).
The POST-DATABASE-COMMIT triggers fires just after the
'COMMIT' statement is issued by forms to close the current
transaction.
Pre-Query vs. Pre-Select
PRE-QUERY fires just before Forms begins to prepare the
SQL statement that will be required to query the
appropriate records from the database in response to the
query criteria that have been entered into the example
record.
It is the designers last chance to "deposit" query
criteria into the items in the block as if they had been
entered into the example record by the operator.
PRE-SELECT fires after the PRE-QUERY trigger has fired,
and just before the actual, physical construction of the
SELECT statement begins. It would typically be used in
conjunction with an ON-SELECT trigger in which the
designer would be supplanting the normal construction of
the SELECT statement with a user exit of his own to
construct and prepare the SELECT statement for execution
(perhaps against a foreign datasource).
Locking
Question
--------
Is it possible to defer locking of a record until commit
time ?
Answer
------
Yes, in Forms 4.5 there is a block property called 'Locking
Mode', which can be either 'Immediate' or 'Delayed'. If you
set it to 'Delayed', then a record in a block is not locked
until commit-time, specifically until changes are 'posted'.
At that time, the current forms value is compared to the DB
value before issuing the update statement. The user will
get an error if the record has been updated since it was
fetched.
'Locking Mode' can be changed at runtime in a trigger with
the Set_Block_Property builtin.
Images
Questions
--------
How can I get an image from a file to be stored in my
database ?
Answer
------
To store images in the database, you need to read them from
the file system in one of the supported standard file
formats :
'PCX'
'BMP'
READ_IMAGE_FILE('file_name', 'TIFF', 'block.image_item');
'JFIF'
'PICT'
Into an item in the form. Then commit it to the database :
COMMIT_FORM;
Make sure that 'block.image_item' is a database item in a
database block and that the 'image_item' column in the base
table on which the block is based is declared as LONG RAW.
Monday, April 20, 2009
PL/SQL Integration
Question
--------
How is SQL within PL/SQL dealt with by Forms ?
Answer
------
Since PL/SQL blocks in a form can have Forms builtins, we
cannot send the whole block to the database.
Forms processes the cursors which PL/SQL tell it are
required for DML operations within PL/SQL within Forms.
That means SQL within PL/SQL takes advantage of the
techniques to reduced network traffic implemented in 4.5.
These changes dramatically reduce the level of traffic seen
using SQL*Forms 3.0.
To send entire blocks of PL/SQL to the DB, you can:
(1) Use Forms_DDL() built-in to send a lengthly
string which makes up a block of code you want
to be executed on the server:
Forms_DDL('begin ... end;');
(2) Call Stored procedures/functions/packages which
have the bundled DML inside them and call these
stored program units from forms.
Question
--------
How are the constants like INSERT_ALLOWED and PROPERTY_ON
dealt with by PL/SQL ?
Answer
------
All of these tokens that you pass to builtins are numeric
constants. If you write a generic procedure that sets the
properties of objects you need to make sure that the
parameters passed are typed as NUMBER to ensure that no
datatyping conflicts occur.
--------
How is SQL within PL/SQL dealt with by Forms ?
Answer
------
Since PL/SQL blocks in a form can have Forms builtins, we
cannot send the whole block to the database.
Forms processes the cursors which PL/SQL tell it are
required for DML operations within PL/SQL within Forms.
That means SQL within PL/SQL takes advantage of the
techniques to reduced network traffic implemented in 4.5.
These changes dramatically reduce the level of traffic seen
using SQL*Forms 3.0.
To send entire blocks of PL/SQL to the DB, you can:
(1) Use Forms_DDL() built-in to send a lengthly
string which makes up a block of code you want
to be executed on the server:
Forms_DDL('begin ... end;');
(2) Call Stored procedures/functions/packages which
have the bundled DML inside them and call these
stored program units from forms.
Question
--------
How are the constants like INSERT_ALLOWED and PROPERTY_ON
dealt with by PL/SQL ?
Answer
------
All of these tokens that you pass to builtins are numeric
constants. If you write a generic procedure that sets the
properties of objects you need to make sure that the
parameters passed are typed as NUMBER to ensure that no
datatyping conflicts occur.
Program Units and Libraries Question
Program Units and Libraries Question
Question
--------
If I want to create a procedure should I use a library, a
database stored procedure or a local form procedure ?
Answer
------
These different forms of procedures will produce different
performance results depending on what you are trying to
achieve. The database procedure will be invoked on the
server side and will perform all of the processing there.
This may help reduce network traffic, but may overload the
server if many clients are doing this.
Local form and library procedures are quite similar in that
they are both stored and run on the client with any SQL
statements being passed to the server.
The local procedures are typically faster on execution
because they are actually part of the .fmx file, but may use
more memory and have a longer startup time when the .fmx
file is initially invoked.
Library procedures may be better in terms of overall memory
as procedures are only loaded into memory in 4K chunks when
they are required. However, once loaded they are read from
memory.
They have the additional advantage that the library can be
attached to a number of forms and the code within the
library is then available to the forms.
If the code within the library procedures is altered, the
form does not require re-generation. That can be a *big*
advantage.
Question
--------
How does the use of libraries affect the size of the .FMX
file ?
Answer
------
If the library code were included in the FRM, there would
have been no reason to redo them the way we have. The beauty
of the new scheme is that the library modules remain
separate and compiled (into .PLL or .PLX files) so that runform
can bring program units into memory at runtime without adding to
the size of each and every FMX file.
Think of it like a DLL. The only overhead that's added to
the form that attaches a library is that negligible amount
required to remember the name of the libraries on which it
depends.
Question
--------
How should I make a reference to a block in my library
program units ?
Answer
------
At compile time, forms will attempt to resolve all
references to objects. Therefore, if you have code thus :
:BLOCK1.ITEM1 := 'Value';
or
IF
:BLOCK1.ITEM1 = 'Y'
THEN
....
Forms will attempt to resolve the reference to
:BLOCK1.ITEM1. When you are writing library code, there is
no way to resolve these references, since the library could
potentially be attached to *any* form.
Instead you need to use the Copy() and Name_In() builtins
when referencing Forms objects within libraries.
These builtins do not attempt to resolve references at
compile time. So the above code would become :
Copy ('Value','BLOCK1.ITEM1');
or
IF
Name_In ('BLOCK1.ITEM1') = 'Y'
THEN
...
Question
--------
If I want to create a procedure should I use a library, a
database stored procedure or a local form procedure ?
Answer
------
These different forms of procedures will produce different
performance results depending on what you are trying to
achieve. The database procedure will be invoked on the
server side and will perform all of the processing there.
This may help reduce network traffic, but may overload the
server if many clients are doing this.
Local form and library procedures are quite similar in that
they are both stored and run on the client with any SQL
statements being passed to the server.
The local procedures are typically faster on execution
because they are actually part of the .fmx file, but may use
more memory and have a longer startup time when the .fmx
file is initially invoked.
Library procedures may be better in terms of overall memory
as procedures are only loaded into memory in 4K chunks when
they are required. However, once loaded they are read from
memory.
They have the additional advantage that the library can be
attached to a number of forms and the code within the
library is then available to the forms.
If the code within the library procedures is altered, the
form does not require re-generation. That can be a *big*
advantage.
Question
--------
How does the use of libraries affect the size of the .FMX
file ?
Answer
------
If the library code were included in the FRM, there would
have been no reason to redo them the way we have. The beauty
of the new scheme is that the library modules remain
separate and compiled (into .PLL or .PLX files) so that runform
can bring program units into memory at runtime without adding to
the size of each and every FMX file.
Think of it like a DLL. The only overhead that's added to
the form that attaches a library is that negligible amount
required to remember the name of the libraries on which it
depends.
Question
--------
How should I make a reference to a block in my library
program units ?
Answer
------
At compile time, forms will attempt to resolve all
references to objects. Therefore, if you have code thus :
:BLOCK1.ITEM1 := 'Value';
or
IF
:BLOCK1.ITEM1 = 'Y'
THEN
....
Forms will attempt to resolve the reference to
:BLOCK1.ITEM1. When you are writing library code, there is
no way to resolve these references, since the library could
potentially be attached to *any* form.
Instead you need to use the Copy() and Name_In() builtins
when referencing Forms objects within libraries.
These builtins do not attempt to resolve references at
compile time. So the above code would become :
Copy ('Value','BLOCK1.ITEM1');
or
IF
Name_In ('BLOCK1.ITEM1') = 'Y'
THEN
...
Record Groups, Global Variables and Parameters Question
Record Groups, Global Variables and Parameters Question
--------
What should I be using Record Groups for ?
Answer
------
Structurally, a Record Group is similar to an in-memory
Oracle table in that it has a row/column framework and
columns with datatypes of NUMBER, CHAR, and DATE. Analogous
to how storing data in a table occupies space on the
physical media, storing data in a record group allocates (or
occupies) space in the user's current process memory. The
more columns and rows the record group contains, the more
memory it will occupy.
Since record groups do not currently have any record
buffering mechanism in Forms 4.5 akin to that offered by the
database block object, populating a record group from a
query should be done with caution. Using a query that
returns 10,000 records will allocate memory to fetch and
store all rows returned from the query.
In particular, record groups are not designed to be a
replacement for database tables while your applications is
running. They may be optimal for relatively small lists of
lookup values, or medium-sized data structures for
application record-keeping on the client side, and are
generally most effectively used where your application might
have required arrays.
Question
--------
When should I use globals vs parameters ?
Answer
------
There is no *one* right way to use either, but here are some
guidelines that might help you decide:
Datatype: Globals are on CHAR data
Parameters are NUMBER, CHAR, or DATE
Storage: Globals each take about 260 bytes, regardless of
length
Parameters take what they need.
Creation: Globals are created the first time they are
assigned.
Parameters must be named and typed at design time,
or alternately may be added to a parameter list at
runtime with the Add_Parameter() built-in.
Default: Globals must have a default value programmatically
Values assigned.
Parameters can be assigned a default value of the
proper datatype at design time.
Assignment: Globals are assigned directly thru PL/SQL
assignment with the bind variable notation
(:GLOBAL.GLOBAL_NAME), or indirectly with the
Copy() built-in.
Parameters in the default parameter list (those
created at design time) are assigned directly
thru PL/SQL with the bind variable notation
(:PARAMETER.PARAM_NAME), indirectly with the
Copy() built-in. If part of a parameter list is
not the default parameter list, then
the Set_Parameter_Attr() built-in is used. In
addition, parameters which are declared at
design time can be supplied with values on the
command line using the "PARAMNAME=Value" syntax.
Reference: Globals can be referenced directly with bind
variable notation, or indirectly with the
Name_In() built-in.
Parameters in the default parameter list may be
referenced directly with bind variable notation,
or indirectly with the Name_In() built-in. If
part of a parameter list which is not the default
parameter list, then the Get_Parameter_Attr()
built-in used.
Scope: Globals preserve their value for the entire duration
of the Runform session, unless explicitly
Erased. They are visible to all forms which get
called during the session. Any modification made in
a called form to a global variable is visible to any
calling form and all subsequent forms in the session.
Parameters are only visible to the form in which they
are declared, unless they are passed as part of a
parameter list. In this case they supply incoming
values for the form-level parameters declared for the
called form.
The value of the parameter in the calling form is
thus visible to the called form in this way. Any
modification made in a called form to a parameter is
not visible to calling form. The called form gets
"fed" a snapshot of the parameter values a they
existed at the moment of the Call_Form(), and works
with private copies of the values.
Documentation: Globals can be created anywhere in any
trigger. Unless a Forms developer is
disciplined and uses some sort of
methodology, globals variables can be very
hard to find and document.
Parameters exist as named object at the form
level, can have meaningful default values,
and can be documented with object comments
like any other forms object.
Question
--------
How do I pass a Record Group from Forms to Reports or
Graphics ?
Answer
------
A record group is passed to Reports or Graphics as a DATA
parameter. This DATA parameter is a special type of
parameter that gives a signal to the integration code to
substitute the contents of the record group whose name you
give for the results of the query named by the query name
you indicate. Simple example:
(1) In Oracle Reports V2.5 you create a report with a query:
Query Name: FOOBAR_QUERY
Query: SELECT DEPTNO, DNAME FROM DEPT
(2) In Forms you create a record group in your favorite way
such that it has two columns, one NUMBER and one CHAR,
then you populate that record group (still on the forms
side). Say the record group is called PETE, and has two
columns A and B:
DECLARE
f RecordGroup;
g GroupColumn;
BEGIN
f := CREATE_GROUP('Pete');
g := ADD_GROUP_COLUMN( f , 'A', NUMBER_COLUMN);
g := ADD_GROUP_COLUMN( f , 'B', CHAR_COLUMN, 20);
/*
** Then populate the group in your favorite way
*/
END;
(3) When you setup the parameter list that you'll pass from
forms to the other tool, you create a parameter named
'FOOBAR_QUERY' and give it the value of 'PETE'. Since
it is a DATA parameter, this pairing of 'FOOBAR_QUERY'
to 'PETE' tells the integration code what to do when it
starts up the other tool. Instead of running the select
statement that defines 'FOOBAR_QUERY' in Reports, the
values from the 'PETE' record group will be substituted
as if they *were* the result.
Question
--------
Can I access the contents of a record group within a user
exit ?
Answer
------
To access the contents of a record group within a user
exits, the values will first have to be placed within a
database block. At present, user exits do not have any
knowledge of the data structure of an Forms record
group.
With the advent of ORA_FFI it is likely that the need
for user exits will now diminish as you can make MS
Windows SDK and SLL function calls directly from PL/SQL.
You will thus still have access to the Record Group
values.
--------
What should I be using Record Groups for ?
Answer
------
Structurally, a Record Group is similar to an in-memory
Oracle table in that it has a row/column framework and
columns with datatypes of NUMBER, CHAR, and DATE. Analogous
to how storing data in a table occupies space on the
physical media, storing data in a record group allocates (or
occupies) space in the user's current process memory. The
more columns and rows the record group contains, the more
memory it will occupy.
Since record groups do not currently have any record
buffering mechanism in Forms 4.5 akin to that offered by the
database block object, populating a record group from a
query should be done with caution. Using a query that
returns 10,000 records will allocate memory to fetch and
store all rows returned from the query.
In particular, record groups are not designed to be a
replacement for database tables while your applications is
running. They may be optimal for relatively small lists of
lookup values, or medium-sized data structures for
application record-keeping on the client side, and are
generally most effectively used where your application might
have required arrays.
Question
--------
When should I use globals vs parameters ?
Answer
------
There is no *one* right way to use either, but here are some
guidelines that might help you decide:
Datatype: Globals are on CHAR data
Parameters are NUMBER, CHAR, or DATE
Storage: Globals each take about 260 bytes, regardless of
length
Parameters take what they need.
Creation: Globals are created the first time they are
assigned.
Parameters must be named and typed at design time,
or alternately may be added to a parameter list at
runtime with the Add_Parameter() built-in.
Default: Globals must have a default value programmatically
Values assigned.
Parameters can be assigned a default value of the
proper datatype at design time.
Assignment: Globals are assigned directly thru PL/SQL
assignment with the bind variable notation
(:GLOBAL.GLOBAL_NAME), or indirectly with the
Copy() built-in.
Parameters in the default parameter list (those
created at design time) are assigned directly
thru PL/SQL with the bind variable notation
(:PARAMETER.PARAM_NAME), indirectly with the
Copy() built-in. If part of a parameter list is
not the default parameter list, then
the Set_Parameter_Attr() built-in is used. In
addition, parameters which are declared at
design time can be supplied with values on the
command line using the "PARAMNAME=Value" syntax.
Reference: Globals can be referenced directly with bind
variable notation, or indirectly with the
Name_In() built-in.
Parameters in the default parameter list may be
referenced directly with bind variable notation,
or indirectly with the Name_In() built-in. If
part of a parameter list which is not the default
parameter list, then the Get_Parameter_Attr()
built-in used.
Scope: Globals preserve their value for the entire duration
of the Runform session, unless explicitly
Erased. They are visible to all forms which get
called during the session. Any modification made in
a called form to a global variable is visible to any
calling form and all subsequent forms in the session.
Parameters are only visible to the form in which they
are declared, unless they are passed as part of a
parameter list. In this case they supply incoming
values for the form-level parameters declared for the
called form.
The value of the parameter in the calling form is
thus visible to the called form in this way. Any
modification made in a called form to a parameter is
not visible to calling form. The called form gets
"fed" a snapshot of the parameter values a they
existed at the moment of the Call_Form(), and works
with private copies of the values.
Documentation: Globals can be created anywhere in any
trigger. Unless a Forms developer is
disciplined and uses some sort of
methodology, globals variables can be very
hard to find and document.
Parameters exist as named object at the form
level, can have meaningful default values,
and can be documented with object comments
like any other forms object.
Question
--------
How do I pass a Record Group from Forms to Reports or
Graphics ?
Answer
------
A record group is passed to Reports or Graphics as a DATA
parameter. This DATA parameter is a special type of
parameter that gives a signal to the integration code to
substitute the contents of the record group whose name you
give for the results of the query named by the query name
you indicate. Simple example:
(1) In Oracle Reports V2.5 you create a report with a query:
Query Name: FOOBAR_QUERY
Query: SELECT DEPTNO, DNAME FROM DEPT
(2) In Forms you create a record group in your favorite way
such that it has two columns, one NUMBER and one CHAR,
then you populate that record group (still on the forms
side). Say the record group is called PETE, and has two
columns A and B:
DECLARE
f RecordGroup;
g GroupColumn;
BEGIN
f := CREATE_GROUP('Pete');
g := ADD_GROUP_COLUMN( f , 'A', NUMBER_COLUMN);
g := ADD_GROUP_COLUMN( f , 'B', CHAR_COLUMN, 20);
/*
** Then populate the group in your favorite way
*/
END;
(3) When you setup the parameter list that you'll pass from
forms to the other tool, you create a parameter named
'FOOBAR_QUERY' and give it the value of 'PETE'. Since
it is a DATA parameter, this pairing of 'FOOBAR_QUERY'
to 'PETE' tells the integration code what to do when it
starts up the other tool. Instead of running the select
statement that defines 'FOOBAR_QUERY' in Reports, the
values from the 'PETE' record group will be substituted
as if they *were* the result.
Question
--------
Can I access the contents of a record group within a user
exit ?
Answer
------
To access the contents of a record group within a user
exits, the values will first have to be placed within a
database block. At present, user exits do not have any
knowledge of the data structure of an Forms record
group.
With the advent of ORA_FFI it is likely that the need
for user exits will now diminish as you can make MS
Windows SDK and SLL function calls directly from PL/SQL.
You will thus still have access to the Record Group
values.
Items, Records and Blocks Question
Items, Records and Blocks Question
--------
How does a Display Item differ from a normal Text Item ?
Answer
------
A Display Item is essentially a permanently non-enterable
text-item. It can be used for implementing variable
boilerplate text, or for any on-screen values which do not
require operator interaction (date/time for example).
Since Display Items are a special "subset" of the features
that a Text Item provide, they require slightly less memory
for their definition because many of the text-items
property's do not apply to the display item.
Question
--------
Why do a get a null entry in my poplists at startup ?
Answer
------
Consider a poplist with the values:
Label Value
------- --------
One 1
Two 2
Three 3
If you have a poplist that is in a block where no record has
yet to be instantiated, then the poplist item has a NULL
value. To visually reflect this, we show a null label in
the poplist. To show a null label in the poplist, we need to
add a null entry to the list at the bottom, and tell the
toolkit that *that* is the current value of the widget.
In addition, if the item is not required, then we
automatically add an empty list element to your set of
choices so that the user can pick NULL as one of the values.
The trick is, like for any item, if you want some value to
appear in the item at startup, you have to set the value or
instantiate the record in the block where that item belongs
so that those items take on their default values.
Question
--------
How can I dynamically prevent the user from entering a new
record ?
Answer
------
Have a Pre-Record trigger that does:
IF ((dynamic-condition-is-true) AND
:System.Record_Status = 'NEW')
THEN
RAISE Form_Trigger_Failure;
END IF;
Question
--------
How can I dynamically make an entire block query-only at
runtime ?
Answer
------
Issue the following :
Set_Block_Property('blockname', INSERT_ALLOWED,
PROPERTY_OFF);
Set_Block_Property('blockname', UPDATE_ALLOWED,
PROPERTY_OFF);
Question
--------
How can I change the colour and font of an item dynamically
at runtime ?
Answer
------
Using the builtin Set_Item_Property :
Set_Item_Property( 'Blockname.Itemname',
VISUAL_ATTRIBUTE,
'VisualAttributeName' );
Where 'VisualAttributeName' is either the name of a visual
attribute you've set up in the form (which has foreground,
background, font, etc.), or is the name of a logical visual
attribute from the resource file.
Question
--------
How can I have an item which acts like a disabled item , but
is not greyed out ?
Answer
------
The INSERT_ALLOWED and UPDATE_ALLOWED attributes solve this
problem. INSERT_ALLOWED=OFF, UPDATE_ALLOWED=OFF items don't
show as like disabled items but do not allow the user to
change the values in either new or queried records.
Question
--------
What exactly does 'Query Hits' and 'Query Options' mean in
the context of a block ?
Answer
------
Set_Block_Property(.., QUERY_HITS) lets your ON-COUNT
transactional trigger tell Forms how many records the query
(that you are handling yourself) will return so it may print
out the message :
"FRM-xxxxx: Query will retrieve nnn record(s)."
Getting this property via Get_Block_Property(.., QUERY_HITS)
simply returns the number of records that have been
retrieved by the query.
Get_Block_Property(.., QUERY_OPTIONS) lets your
transactional trigger know whether it's supposed to be doing
a normal query, a COUNT(*) type query, or a lock record
query.
Question
--------
What is the difference between the block properties of ARRAY
SIZE and RECORDS BUFFERED ?
Answer
------
ARRAY SIZE is the number of records that get fetched each
time forms goes to the database.
The RECORDS BUFFERED specifies the minimum number of records
that should be placed in memory when records are fetched
from the database. Even if you specify a low value of 3,
the minimum per form is slightly over 300.
As more records are brought back from the database (eg
records 303-306) they get moved between memory and the file
buffer as the user scrolls down.
--------
How does a Display Item differ from a normal Text Item ?
Answer
------
A Display Item is essentially a permanently non-enterable
text-item. It can be used for implementing variable
boilerplate text, or for any on-screen values which do not
require operator interaction (date/time for example).
Since Display Items are a special "subset" of the features
that a Text Item provide, they require slightly less memory
for their definition because many of the text-items
property's do not apply to the display item.
Question
--------
Why do a get a null entry in my poplists at startup ?
Answer
------
Consider a poplist with the values:
Label Value
------- --------
One 1
Two 2
Three 3
If you have a poplist that is in a block where no record has
yet to be instantiated, then the poplist item has a NULL
value. To visually reflect this, we show a null label in
the poplist. To show a null label in the poplist, we need to
add a null entry to the list at the bottom, and tell the
toolkit that *that* is the current value of the widget.
In addition, if the item is not required, then we
automatically add an empty list element to your set of
choices so that the user can pick NULL as one of the values.
The trick is, like for any item, if you want some value to
appear in the item at startup, you have to set the value or
instantiate the record in the block where that item belongs
so that those items take on their default values.
Question
--------
How can I dynamically prevent the user from entering a new
record ?
Answer
------
Have a Pre-Record trigger that does:
IF ((dynamic-condition-is-true) AND
:System.Record_Status = 'NEW')
THEN
RAISE Form_Trigger_Failure;
END IF;
Question
--------
How can I dynamically make an entire block query-only at
runtime ?
Answer
------
Issue the following :
Set_Block_Property('blockname', INSERT_ALLOWED,
PROPERTY_OFF);
Set_Block_Property('blockname', UPDATE_ALLOWED,
PROPERTY_OFF);
Question
--------
How can I change the colour and font of an item dynamically
at runtime ?
Answer
------
Using the builtin Set_Item_Property :
Set_Item_Property( 'Blockname.Itemname',
VISUAL_ATTRIBUTE,
'VisualAttributeName' );
Where 'VisualAttributeName' is either the name of a visual
attribute you've set up in the form (which has foreground,
background, font, etc.), or is the name of a logical visual
attribute from the resource file.
Question
--------
How can I have an item which acts like a disabled item , but
is not greyed out ?
Answer
------
The INSERT_ALLOWED and UPDATE_ALLOWED attributes solve this
problem. INSERT_ALLOWED=OFF, UPDATE_ALLOWED=OFF items don't
show as like disabled items but do not allow the user to
change the values in either new or queried records.
Question
--------
What exactly does 'Query Hits' and 'Query Options' mean in
the context of a block ?
Answer
------
Set_Block_Property(.., QUERY_HITS) lets your ON-COUNT
transactional trigger tell Forms how many records the query
(that you are handling yourself) will return so it may print
out the message :
"FRM-xxxxx: Query will retrieve nnn record(s)."
Getting this property via Get_Block_Property(.., QUERY_HITS)
simply returns the number of records that have been
retrieved by the query.
Get_Block_Property(.., QUERY_OPTIONS) lets your
transactional trigger know whether it's supposed to be doing
a normal query, a COUNT(*) type query, or a lock record
query.
Question
--------
What is the difference between the block properties of ARRAY
SIZE and RECORDS BUFFERED ?
Answer
------
ARRAY SIZE is the number of records that get fetched each
time forms goes to the database.
The RECORDS BUFFERED specifies the minimum number of records
that should be placed in memory when records are fetched
from the database. Even if you specify a low value of 3,
the minimum per form is slightly over 300.
As more records are brought back from the database (eg
records 303-306) they get moved between memory and the file
buffer as the user scrolls down.
Subscribe to:
Posts (Atom)