Is it possible to use the %TYPE and array together?
CREATE FUNCTION role_update(
IN id "role".role_id % TYPE,
IN name "role".role_name % TYPE,
IN user_id_list "user".user_id % TYPE[],
IN permission_id_list INT[]
)
I got syntax error by this, but I don't want to duplicate any column type, so I want to use "user".user_id % TYPE instead of simply INT because then it is easier to modify any column type later.
As the manual explains here:
The type of a column is referenced by writing table_name.column_name%TYPE. Using this feature can sometimes help make a function independent of changes to the definition of a table.
The same functionality can be used in the RETURNS clause.
But there is no simple way to derive an array type from a referenced column, at least none that I would know of.
About modifying any column type later:
You are aware that this type of syntax is only a syntactical convenience to derive the type from a table column? Once created, there is no link whatsoever to the table or column involved.
It helps to keep a whole create script in sync. But id doesn't help with later changes to live objects in the database.
Related answer on dba.SE:
Array of template type in PL/pgSQL function using %TYPE
Using referenced types in function's parameters has no sense (in PostgreSQL), because its translated intermediately to actual types, and it is stored as actual types. Sorry, PostgreSQL doesn't support this functionality - something different is using referenced types inside function, where actual type is detected every first time execution in session.
Related
I've created a Postgresql database with a few tables and am fairly content with how they work. I've also written some Ada code to interface with and perform simple queries. This all running on Slackware 14.2 using GNAT 2020.
One of my table columns is of an array type, an array of BIGINT.
The problem I have is when I try to create the schema for my Ada using gnatcoll_db2ada.
The schema file ("all-schema.txt") includes the following line:
item_list | BIGINT[] | | | |
When I do
gnatcoll_db2ada -dbmodel all-schema.txt
I get
Error: unknown field type "BIGINT[]"
all-schema.txt:33 gnatcoll-sql-inspect.adb:1420
gnatcoll-sql-inspect.adb:1420
Is what I'm trying to do actually possible?
The documentation suggests that database fields of array types are not supported (i.e. they are not mentioned as being supported). From the document SQL: Database interface:
The type of the field is the SQL type ("INTEGER", "TEXT", "TIMESTAMP", "DATE", "DOUBLE PRECISION", "MONEY", "BOOLEAN", "TIME", "CHARACTER(1)"). Any maximal length can be specified for strings, not just 1 as in this example. The tool will automatically convert these to Ada when generating Ada code. A special type ("AUTOINCREMENT") is an integer that is automatically incremented according to available ids in the table. The exact type used will depend on the specific DBMS.
Note that while the scalar field type "BIGINT" is not mentioned in the documentation, it is mentioned in the source code (see gnatcoll-sql.ads).
If you really need support for the "BIGINT" array type, then a quick glance at the source code suggests that you can extend the GNATCOLL DB interface with new field types by
using the generic package GNATCOLL.SQL_Impl.Field_Types (see here) and
the creation of a new field mapping (i.e. a new concrete type based on GNATCOLL.SQL.Inspect.Field_Mapping, see here).
It seems that new field types are typically placed in package GNATCOLL.SQL_Fields (see here).
Note that I never did this myself, so I cannot tell how much effort it will be and whether this is really all that is needed; The exact requirements for implementing a new field type are (at the time of writing) not documented.
I suspected as much, having briefly looked at the source.
What I'll do is spin off the array into another table. This at least has helped clarify what I need to, and the array, to be fair, always felt a bit clunky. Thanks for the the comments.
I might be doing something silly or just have a lack of understanding but I am currently working with a table of data and when I change the variable type of a column using the table.column notation when I check using the table(:,1) notation it returns a 0.
For example in my table the first column is Creditability (where table is the name of the table) so I changed the variable type using table.Creditability = logical(table.Creditability)
Then when I use islogical(table.Creditability) it returns 1
But when I use islogical(table(:,1)) it returns 0 yet when I type table(:,1) it returns a logical variable in true or false form.
I may just have a lack of understanding as I am new to this but any help would be appreciated.
Thanks
Of course it will return 0. This is because of basic point you are missing.
"table" is a structure variable in which a field named "Creditability" is created.
While "Creditability" is a logical array, it's parent "table" is still a structure.
Now, you are not getting error with statement table(:,1) although table is scalar. That is because, MATLAB treats everything as matrix. In this case, table is 1x1 matrix.
I hope it is clear now.
As title shown, when reading the manul, I found type record type and row type, which are both composite type. However, I want to figure out their difference.
They're similar once defined but tend to have different use cases.
A RECORD type has no predefined structure and is typically used when the row type might change or is out of your control, for example if you're referencing a record in a FOR LOOP.
ROWTYPE is predefined of a particular table row structure and thus if anything deviates from that structure you will get runtime errors.
It all depends what you're trying to achieve.
For cursor loops I use a RECORD>
For more information:
http://www.postgresql.org/docs/current/static/plpgsql-declarations.html
With DB2 I'm able to declare anonymous custom types (e.g. row types or composite types) for my user defined functions - see the following example (especially the last line):
DB2 example:
CREATE OR REPLACE FUNCTION myFunction(IN input1 DECIMAL(5), IN input2 DECIMAL(5))
RETURNS DECIMAL(2)
READS SQL DATA
LANGUAGE SQL
NO EXTERNAL ACTION
NOT DETERMINISTIC
BEGIN
DECLARE TYPE customAnonymousType AS ROW(a1 DECIMAL(2), a2 DECIMAL(2), a3 DECIMAL(2));
/* do something fancy... */
Can I do something similar with PL/pgSQL? I know I would be able to use existing row types, also existing user defined types - but do I really have to define the type in advance?
I also know about the RECORD type, but as far as I understand I would not be able to use it in arrays (and also it would not be a well defined type).
Comments asked for an example, even though it does lengthen the question a lot I tried to define a quite simple example (still for DB2):
CREATE OR REPLACE FUNCTION myFunction(IN input1 DECIMAL(5), IN input2 DECIMAL(5))
RETURNS DECIMAL(2)
READS SQL DATA
LANGUAGE SQL
NO EXTERNAL ACTION
NOT DETERMINISTIC
BEGIN
DECLARE TYPE customAnonymousType AS ROW(a1 DECIMAL(2), a2 CHARACTER VARYING(50));
DECLARE TYPE customArray AS customAnonymousType ARRAY[INTEGER];
DECLARE myArray customArray;
SET myArray[input1] = (50, 'Product 1');
SET myArray[input2] = (99, 'Product 2');
RETURN myArray[ARRAY_FIRST(myArray)].a1;
END
This function of course only serves as a dummy function (but I suppose it is already quite long for a question here). Actually it just decides which number to return depending on if input1 is greater than input2. If input1 is smaller than input2, it returns 50, if input2 is smaller or equal than input2 it would return 99.
I know I'm not even using my a2 character field of my type (so in this case I would also be able to just use an number array) and that there are probably many, many better solutions to return two fixed numbers depending on the input values, but still my original questions remains if I am able to use anonymous custom types in PL/pgSQL (as I would in Oracle or DB2 procedures) - or if there are any similar alternatives.
You cannot to create types with local visibility in Postgres. This functionality is not supported. Postgres support global custom composite types only.
See CREATE TYPE doc. This statement cannot be used in DECLARE part of plpgsql block.
I have been implementing user defined types in Postgresql 9.2 and got confused.
In the PostgreSQL 9.2 documentation, there is a section (35.11) on user defined types. In the third paragraph of that section, the documentation refers to input and output functions that are used to construct a type. I am confused about the purpose of these functions. Are they concerned with on-disk representation or only in-memory representation? In the section referred to above, after defining the input and output functions, it states that:
If we want to do anything more with the type than merely store it,
we must provide additional functions to implement whatever operations
we'd like to have for the type.
Do the input and output functions deal with serialization?
As I understand it, the input function is the one which will be used to perform INSERT INTO and the output function to perform SELECT on the type so basically if we want to perform an INSERT INTO then we need a serialization function embedded or invoked in the input or output function. Can anyone help explain this to me?
Types must have a text representation, so that values of this type can be expressed as literals in a SQL query, and returned as results in output columns.
For example, '2013-20-01' is a text representation of a date. It's possible to write VALUES('2013-20-01'::date) in a SQL statement, because the input function of the date type recognizes this string as a date and transforms it into an internal representation (for both using it in memory and storing to disk).
Conversely, when client code issues SELECT date_field FROM table, the values inside date_field are returned in their text representation, which is produced by the type's output function from the internal representation (unless the client requested a binary format for this column).