Declaring global exception in PL/SQL package - sql

I have some procedures/functions in the package which catch the -2291 exception when a FOREIGN KEY constraint is violated.
I removed the exception from the different procedures and declared it in the package body like so:
e_ouder_niet_gevonden EXCEPTION;
PRAGMA EXCEPTION_INIT(e_ouder_niet_gevonden,-2291);
Now when I use one of the procedures in the package there is no problem. What I would like to achieve, however, is that ANY procedure/function can use that exception. How would I go about doing this?

SOLUTION:
Instead of putting the exception in the package body, you need to put in the package specification. If you then want to use the exception in a procedure outside of the package you can put this in the EXCEPTION block:
WHEN packagename.exception_name THEN
This works without problems.

Related

What does $$ (double dollar) mean in Oracle SQL?

This Create package query executes in a SQLPlus util cli without error -
create or replace package PACKAGE2 as
$if $$install_ad_zd_sys $then
procedure LOG( X_MODULE varchar2, X_LEVEL varchar2, X_MESSAGE varchar2);
function LITERAL(X_VALUE varchar2) return varchar2;
else procedure LOG_VER;
$end
end;
/
Just want to know what does double dollar mean here?
Is it a sqlplus specific keyword?
I tried running this whole block as part of jdbc but it gives error 'Invalid column index'. So, I am suspecting the sign is specific to sqlplus, but not able to find the meaning of it.
This is how I am executing the above sql in java jdbc
plSqlstatement = connection.prepareCall(sqlBuffer.toString());
//sqlBuffer contains the whole create package block
//like sqlBuffer.append("CREATE OR REPLACE
//PACKAGE ....").append("/n").append(..next Line) and so on.
It's an inquiry directive:
An inquiry directive provides information about the compilation environment.
An inquiry directive typically appears in the boolean_static_expression of a selection directive, ...
... which is how you are using it, as it's within the $if conditional compilation directive.
You would need to assign a value, which you don't seem to be doing in either execution. But it will compile anyway, through SQL*Plus or JDBC (as in this db<>fiddle).
If you are getting an error from your JDBC call then you need to look at how you are running it - particularly if you are making get/set calls for arguments, as the error message suggests - since there are no arguments to set or retrieve.

Does PHP 7 have a way to crash on non-existing class when using the `MyClass::class` notation?

A basic use case would be calling MyEventListener::class without having imported use MyNamespace\MyEventListener. The result would be a broken piece of code that's relatively hard to debug.
Does PHP 7 provide a directive to crash instead of returning the class name if no class exists? For example:
After calling use Foo\Bar;, Bar::class would return 'Foo\Bar'.
But if no import statement, PHP returns 'Bar', even though the class doesn't exist, not even in the global namespace.
Can I make it crash somehow?
The thing you need to keep in mind is that use Foo\Bar; is not "importing" anything. It is telling the compiler: when I say "Bar" I mean Bar from the namespace Foo.
Bar::class is substituted blindly with the string "Foo\Bar". It isn't checking anything.
Until you attempt to instantiate or interact with a class it will not check to see if it exists. That said, it does not throw an Exception, it throws an Error:
// this doesn't exist!
use Foo/Bar;
try {
$instanceOfBar = new Bar();
}
catch (Error $e) {
// catching an Exception will not work
// Throwable or Error will work
}
You can trap and check for non-existent classes at run time, but until you do it will happily toss around strings referring to classes that don't exist.
This is a blessing in the case of Laravel's IoC container and autoloader that abuses this to alias classes as convenient top-level objects. A curse, if you were expecting PHP to throw a fuss on ::class not existing.
Update:
My suggestion for anyone worried about this problem is to use PHPStan in your testing pipeline. It prevents a lot of mistakes, and unlike php -l it will catch if you were to try and interact with a non-existent class.
As far as I know you're going to get a nice error message when you try to instantiate a class that cannot be found through autoloading or explicitly added.
If you want to check if the class exists, first, try this:
$classOutsideNamespaceExists = class_exists('Bar');
$classInsideNameSpaceExists = class_exists('\\Foo\\Bar'));
Or you could try this syntax available since PHP 5.5:
class_exists(MyClass::class)
Finally, you can always use the tried and true method of a try-catch block.
try {
$instanceOfMyClass = new MyClass();
}
catch (Exception $e) {
// conclude the class does not exist and handle accordingly
}
PhpStorm proposes and generates hints like ArrayShape, Pure, etc.
But automatically it is adding
php use JetBrains\PhpStorm\ArrayShape;
or another.
Is not that dangerous that on some production server I will get error
'Class JetBrains\PhpStorm\ArrayShape not found'?
(c)LazyOne:
Well, just use composer require --dev jetbrains/phpstorm-attributes to add such classes to your project. See github.com/JetBrains/phpstorm-attributes
As long as instance of such a class is not actually gets instantiated (created) you should have no error because use statement is just a declaration.

Catch `concurrent update` error in PostgreSQL

Assume I created a function that I execute in REPEATABLE_READ isolation level in PostgresSQL, e.g.
CREATE FUNCTION some_stuff() RETURNS void AS $$
BEGIN
-- do stuff that could throw an error
END;
$$ LANGUAGE plpgsql;
It's possible for this function internally to throw the following error:
ERROR: could not serialize access due to concurrent update. Is there a way to catch this error and repeat the function/transaction internally?
So have something like this:
CREATE FUNCTION some_stuff() RETURNS void AS $$
BEGIN
try {
-- do stuff that could throw an error
} catch (error) { call some_stuff(); }
END;
$$ LANGUAGE plpgsql;
Or has this error catching to be done in the application level, i.e. in Java that is calling this function?
It's possible for this function internally to throw the following error: ERROR: could not serialize access due to concurrent update. Is there a way to catch this error and repeat the function/transaction internally?
No, it is not.
PostgreSQL's functions are implicitly wrapped in a transaction if one isn't already in progress. There is no way to obtain a new transaction snapshot from within a function in repeatable read or serializable isolation. You can't rollback and begin a new transaction.
For this to work PostgreSQL would need to support top-level procedures with autonomous commit.
You must have the controlling code on a separate connection. This means doing it from a client, or (ab)using dblink for the purpose.

Package got invalidated in oracle 11g [duplicate]

I am using oracle 10g and toad 11.5. I am trying to call an api from an anonymous block.
If I recompile the api after adding dbms_output.put_line and then try to execute the anonymous block, it shows error as:
"ORA-06508: PL/SQL: could not find program unit being called".
However if I end current session and open a new session, then the anonymous block will execute with out the error.
Due to this issue, i am made to reconnect the session everytime i make a change to API.
Can anyone help if this issue can be resolved by making any configurations in toad or database level.
I suspect you're only reporting the last error in a stack like this:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "schema.package" has been invalidated
ORA-04065: not executed, altered or dropped package body "schema.package"
ORA-06508: PL/SQL: could not find program unit being called: "schema.package"
If so, that's because your package is stateful:
The values of the variables, constants, and cursors that a package
declares (in either its specification or body) comprise its package
state. If a PL/SQL package declares at least one variable, constant,
or cursor, then the package is stateful; otherwise, it is stateless.
When you recompile the state is lost:
If the body of an instantiated, stateful package is recompiled (either
explicitly, with the "ALTER PACKAGE Statement", or implicitly), the
next invocation of a subprogram in the package causes Oracle Database
to discard the existing package state and raise the exception
ORA-04068.
After PL/SQL raises the exception, a reference to the package causes
Oracle Database to re-instantiate the package, which re-initializes
it...
You can't avoid this if your package has state. I think it's fairly rare to really need a package to be stateful though, so you should revisit anything you have declared in the package, but outside a function or procedure, to see if it's really needed at that level. Since you're on 10g though, that includes constants, not just variables and cursors.
But the last paragraph from the quoted documentation means that the next time you reference the package in the same session, you won't get the error and it will work as normal (until you recompile again).
seems like opening a new session is the key.
see this answer.
and here is an awesome explanation about this error
Based on previous answers. I resolved my issue by removing global variable at package level to procedure, since there was no impact in my case.
Original script was
create or replace PACKAGE BODY APPLICATION_VALIDATION AS
V_ERROR_NAME varchar2(200) := '';
PROCEDURE APP_ERROR_X47_VALIDATION ( PROCESS_ID IN VARCHAR2 ) AS BEGIN
------ rules for validation... END APP_ERROR_X47_VALIDATION ;
/* Some more code
*/
END APPLICATION_VALIDATION; /
Rewritten the same without global variable V_ERROR_NAME and moved to procedure under package level as
Modified Code
create or replace PACKAGE BODY APPLICATION_VALIDATION AS
PROCEDURE APP_ERROR_X47_VALIDATION ( PROCESS_ID IN VARCHAR2 ) AS
**V_ERROR_NAME varchar2(200) := '';**
BEGIN
------ rules for validation... END APP_ERROR_X47_VALIDATION ;
/* Some more code
*/
END APPLICATION_VALIDATION; /
I recompiled the package specification, even though the change was only in the package body. This resolved my issue

Raising IO Exceptions in SML

Exception IO has structure:
Exception IO of {
name: string
....
...}
some other arguments that I do not understand.
Do I have to assign all these. I mean what do I do after this?
exception IO of {inputfile}
I usually define exception and then raise. but I do not even define an exception this way.
All I want to do is raise an exception if input file is not existant. What do I do here?
Thank You
Yes, you have to supply all three fields when creating an exception of type Io. The meanings of the fields are explained in the documentation:
This is the principal exception raised when an error occurs in the I/O subsystem. The components of Io are:
name: The name component of the reader or writer.
function: The name of the function raising the exception.
cause: The underlying exception raised by the reader or writer, or detected at the stream I/O level.
Some of the standard causes are:
OS.SysErr if an actual system call was done and failed.
*Subscript if ill-formed arguments are given.
BlockingNotSupported
NonblockingNotSupported
ClosedStream
The cause field of Io is not limited to these particular exceptions. Users who create their own readers or writers may raise any exception they like, which will be reported as the cause field of the resulting Io exception.
Note that openIn already raises an Io exception if the file does not exist (with "openIn" as the function, the filename as the name and a SysErr as the cause), so there's no need for you to raise your own.