Flyway fails when One procedure calls another, in DB2 - db2

The following bit of SQL, fails with flyway v5.1.3 against DB2 LUW 10.5, but it works when executed directly in DB2 using a client.
The error message:
" DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884,
SQLERRMC=TEST_STATUS;PROCEDURE, DRIVER=4.19.26"
Definitely a problem with flyway. Does anyone know a workaround or fix?
CREATE OR REPLACE PROCEDURE TEST_STATUS
(
IN a INTEGER,
INOUT b INTEGER,
INOUT c INTEGER,
INOUT d INTEGER
)
BEGIN
END;
CREATE OR REPLACE PROCEDURE TEST_STATUS_MAIN
(
IN a INTEGER,
IN b INTEGER,
IN c INTEGER,
OUT d BIGINT
)
BEGIN
DECLARe e INTEGER DEFAULT 0;
CALL TEST_STATUS(a, b, c, e);
END;

This may happen if CURRENT SCHEMA is not in the CURRENT PATH list for the session.
Let's say,
VALUES CURRENT SCHEMA returns SCHEMA1
VALUES CURRENT PATH returns "SYSIBM","SYSFUN","SYSPROC","SYSIBMADM","SCHEMA2".
The routine TEST_STATUS is created in the SCHEMA1 schema, and it's being tried to be found in the "SYSIBM","SYSFUN","SYSPROC","SYSIBMADM","SCHEMA2" list, upon an attempt to create TEST_STATUS_MAIN.

Related

Pass an arbitrary table type as the polymorphic type parameter to a postgresql function

I'm trying to call a polymorphic function where the table type can be determined by a subsidiary function, say, which_table(). The problem is that I can't convert the returned varchar into an actual type
I'm trying to base a solution off of Erwin Brandstetter's "Various complete table types" section of one of his previous SO answers, as well as his comments in the answer to SQL Injection-safe call of polymorphic function. So, referencing examples there, the behavior I want is to be able to do
SELECT * FROM data_of(NULL::pcdmet, 17);
but be able to specify the table name dynamically, such as,
SELECT * FROM data_of( which_table('arg that evaluates totypeNULL::pcdmet') , 17 )
In my case, the pcdmet, "table" types can be designed to be either all regular tables, temp tables, or composite types (so a solution using any of these would be fully acceptable).
Issue #1
I've been trying to use a PREPARE/EXECUTE approach as suggested, but haven't been able to see what I'm doing wrong.
create or replace function fooprep (inint int, inchar varchar) RETURNS varchar
AS $$
begin
RETURN ''||inint||' '||inchar;
end;
$$ language plpgsql;
dev_db=> create type int_char as (coli int, colv varchar);
CREATE TYPE
dev_db=> prepare fooplan (int_char) as
select * from fooprep($1, $2);
ERROR: function fooprep(int_char, unknown) does not exist
LINE 2: select * from fooprep($1, $2);
Issue #2
But further more, even if I get #1 to work, how to I return it as a type from which_table() when I don't know which table that function will return? I've tried specifying regclass as the return type for a stub which_table() that just returns a constant NULL::testtable but that doesn't seem to be usable as a data type (I'd expected to be able to use it as a table type)
I've also tried something along the lines of
create or replace FUNCTION foofn (bar anyelement DEFAULT EXECUTE fooplan_mod(5))
but get an error there, too:
ERROR: syntax error at or near "fooplan"
LINE 1: ...ce FUNCTION foofn (bar anyelement DEFAULT EXECUTE fooplan_mod(5)...
^
I've tried a plethora of other things to the point that I've pretty much abandoned keyword capitalization (as you can see :-). I feel like I must be close but overlooking something.
I'm using PostgreSQL 13: psql (13.9 (Ubuntu 13.9-1.pgdg20.04+1), server 13.10 (Ubuntu 13.10-1.pgdg20.04+1))
Try the following approach using polymorphic types:
CREATE FUNCTION selectit(anycompatible, bigint)
RETURNS SETOF anycompatible
LANGUAGE plpgsql
AS $$BEGIN
RETURN QUERY EXECUTE
format('SELECT * FROM %s LIMIT %s',
pg_typeof($1),
$2);
END;$$;
Here is a test:
CREATE TABLE test (id integer PRIMARY KEY, value text);
INSERT INTO test VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT * FROM selectit(NULL::test, 2);
id │ value
════╪═══════
1 │ one
2 │ two
(2 rows)

Error: No function matches the given name and argument types

I try to get this function running. When I use pgadmin and manually call this function with
SELECT calculate_something(7) or SELECT common.calculate_something(7)
ERROR: function calculate_something(integer) doesn't exist
hint no function matches the given name and argument types
(translated from german)
I already tried to cast the call SELECT calculate_something(cast(7 as bigint));
What is wrong with that function or cast? :/
CREATE OR REPLACE FUNCTION common.calculate_something(id bigint)
RETURNS real AS
$BODY$
DECLARE
some_value_out REAL := 20;
BEGIN
-- I already removed that part for bug fixing and return a constant value (20)
RETURN some_value_out;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
Is your function actually called:
stoff_stueckgewicht(id bigint)
Or perhaps:
stoff_stückgewicht(id bigint)
?
The latter is a likely cause of problems if your locale settings are different between debian and PostgreSQL.
Alternatively, go through all the functions in all of the schemas on your database, using pgAdmin III and find the function manually.
Use this to diagnose your problem:
SELECT n.nspname AS schema, p.proname AS function
, pg_get_function_identity_arguments(p.oid) As args
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname LIKE 'calculate%';
How to get function parameter lists (so I can drop a function)
And check your search_path:
How does the search_path influence identifier resolution and the "current schema"
Either way, a bigint function can be called with a numeric literal - defaulting to integer, but there is a registered cast to bigint.
Consider Function Type Resolution:
PostgreSQL function call
Is there a way to disable function overloading in Postgres

PostgreSQL (9.4) temporary table scope

After some aggravation, I found (IMO) odd behavior when a function calls another. If the outer function creates a temporary table, and the inner function creates a temporary table with the same name, the inner function "wins." Is this intended? FWIW, I am proficient at SQL Server, and temporary tables do not act this way. Temporary tables (#temp or #temp) are scoped to the function. So, an equivalent function (SQL Server stored procedure) would return "7890," not "1234."
drop function if exists inner_function();
drop function if exists outer_function();
create function inner_function()
returns integer
as
$$
begin
drop table if exists tempTable;
create temporary table tempTable (
inner_id int
);
insert into tempTable (inner_id) values (1234);
return 56;
end;
$$
language plpgsql;
create function outer_function()
returns table (
return_id integer
)
as
$$
declare intReturn integer;
begin
drop table if exists tempTable; -- note that inner_function() also declares tempTable
create temporary table tempTable (
outer_id integer
);
insert into tempTable (outer_id) values (7890);
intReturn = inner_function(); -- the inner_function() function recreates tempTable
return query
select * from tempTable; -- returns "1234", not "7890" like I expected
end;
$$
language plpgsql;
select * from outer_function(); -- returns "1234", not "7890" like I expected
There are no problem with this behaviour, in PostgreSQL temp table can have two scopes:
- session (default)
- transaction
To use the "transaction" scope you should use "ON COMMIT DROP" at the end of the CREATE TEMP statement, i.e:
CREATE TEMP TABLE foo(bar INT) ON COMMIT DROP;
Anyway your two functions will be executed in one transaction so when you call the inner_function from the outer_function you'll be in the same transaction and PostgreSQL will detect that "tempTable" already exists in the current session and will drop it in "inner_function" and create again...
Is this intended?
Yes, these are tables in the database, similar to permanent tables.
They exist in a special schema, and are automatically dropped at the end of a session or transaction. If you create a temporary table with the same name as a permanent table, then you must prefix the permanent table with its schema name to reference it while the temporary table exists.
If you want to emulate the SQL Server implementation then you might consider using particular prefixes for your temporary tables.

Returning the Inserted Id as Out parameter in postgres

All,I am new to PostgreSQL and was playing around with that and .Net using NpgSql plugin.My intention is to capture the inserted id from the database and use that in the .Net 4.5 application
I created the PostgreSQL function.It compiles fine,but cannot get that to work in Pg Admin.When I try to call the function from Pg Admin, I see the column id doesnt exist error
My Postgres function is as follows
create or replace function appuser_address_create(address1 varchar(200), address2 varchar(200), zip varchar(15),district varchar(50),state varchar(100),out address_id int)
returns integer
as
$$
begin
insert into address(address1,address2,postalcode,district,state)
values (address1,address2,zip,district,state)
returning id into address_id;
end
$$ language plpgsql;
-- This gives me error,though the function compiles
select * from appuser_address_create('123 Mainstreet','Jacksonville','32218','District4','Florida')

SQL Server 2012 - Unable to drop User Defined function

The following syntax successfully creates a user defined function, but does not drop it. Can anyone identify where my error is?
-- Example 1 - scalar function
USE AdventureWorks2012
GO
CREATE FUNCTION Sales.uf_MostRecentCustomerOrderDate (#CustomerID int)
RETURNS
DATETIME
AS
BEGIN;
DECLARE #MostRecentOrderDate datetime;
SELECT #MostRecentOrderDate = MAX(OrderDate)
FROM Sales.SalesOrderHeader as soh
Where CustomerID = #CustomerID
RETURN #MostRecentOrderDate
END;
GO
-- Using user defined scalar function
SELECT Sales.uf_MostRecentCustomerOrderDate(29825); -- returns 2008-04-01 00:00:00.000
-- Delete existing scalar valued function
USE AdventureWorks2012;
GO
-- determines if function exists in database
IF OBJECT_ID (N'Sales.uf_MostRecentCustomerOrderDate', N'IF') IS NOT NULL
-- deletes function
DROP FUNCTION Sales.uf_MostRecentCustomerOrderDate;
GO
That function gets created with a type of FN (not IF as you've used).
Try this code to drop it:
-- determines if function exists in database
IF OBJECT_ID (N'Sales.uf_MostRecentCustomerOrderDate', N'FN') IS NOT NULL
-- deletes function
DROP FUNCTION Sales.uf_MostRecentCustomerOrderDate;
GO
Type IF stands for an inline table-valued function - this is not the case here.
Type FN stands for a scalar function - which this is.
See the TechNet docs on sys.objects which also lists all defined types in SQL Server catalog views