Hi All,

    Just finished Wikifying the initial guidelines on how to go about
porting to Postgres. You can find it here:

https://fedorahosted.org/spacewalk/wiki/PostgresPortingGuidelines

    These are my opinions on the issues I could see directly (in schema/ or
through grepping). There are many places where some debate is needed, and
then there are some places where core developers can help out making
decisions based on their knowledge.

    I am attaching the text file here. Lets discuss the issues here, and
finalize them, before going ahead with the actual modifications.

Best regards,
-- 
gurjeet[.sin...@enterprisedb.com
EnterpriseDB      http://www.enterprisedb.com

singh.gurj...@{ gmail | hotmail | indiatimes | yahoo }.com
== Open questions relevant to porting efforts ==
1. Which versions of Oracle are to be supported by Spacewalk?

2. Which versions of Postgres are to be supported by Spacewalk?

= Generic (query) porting issues =

1. Calling code should not use quotes around identifiers.
 This is not a limitation, but just a coding convention note so as to increase 
portabilty of the application code. If the application should use quotes, it 
should do so all across the code.

2. AS keyword necessary for column aliases in Postgres (fixed in 8.4).
 Suggestion is to modify even the Oracle code to use this convention, because 
this convention, being standard, is supported across very many databases, and 
will cause less pain to anybody trying to fix a bug in both versions (Oracle 
and Postgres) of code.

3. Reduce the usage of keywords as identifiers.
 TODO: explain

4. Set operator MINUS is not supported; use SQL standard EXCEPT instead.
 occurances in schema: 2; find ./ -name "*.sql" | xargs grep -iw minus

5. Use Orafce, which helps mitigate many porting issues. (TODO: more docs 
needed on this)

6. Oracle treats {quote}{quote} (empty string) as null, but PG does not.
 So either make the application aware of it, or attach a BEFORE EACH ROW 
trigger on every table which has a char/varchar column, and set 'if 
new.char_col = {quote}{quote}then new.char_col = null'.

 Triggers will not help in cases where app uses results of dynamically computed 
strings.

 occurrences in schema: 17; find ./ -name "*.sql" | xargs grep \'\' | grep -iv 
values | grep -v rhnFAQ_satdata.sql

7. Convert DECODE calls to CASE expressions.
 Although Orafce provides DECODE support, suggestion here is again to modify 
the Oracle code to use CASE expressions for the reason mentioned in point 2.

8. Make the app use standard Outer Join syntax instead of legacy Oracle syntax 
(+).
 Again, it is recommended that Oracle code also be modified to use the standard 
syntax.

 occurances in schema: 8 ; find ./ -name "*.sql" | xargs grep \(+\) 

9. Optimizer Hints are not supported by Postgres, but wouldn't cause a problem 
as they are technically just comments.
 It is suggested to keep them as they wouldn't hurt at all, instead they may 
aide in some way for debugging performance problem etc. Moreover, if the 
deployment is ever moved to Postgres compatible Postgres Plus Advanced Server, 
then they may again come handy as it supports Optimizer Hints.

10. Beware of date+int operations in the application; they mean different 
things in Oracle and PG.

11. ROWID is not supported by Postgres.
 Fortunately, ROWID keyword is used in very few places across the code, so it 
can be easily ported to Postgres by using the result of expression 
'tableoid::varchar || ctid::varchar' as a row identifier. Better still, using a 
Primary or Unique Key instead is recommended.

12. ROWNUM is not supported by Postgres.
 But LIMIT ... OFFSET clause can be used to achieve the same result.

13. Subquery in SET clause of UPDATE command which updates multiple columns is 
not supported in Postgres.
 Syntax supported:
{{{
UPDATE tbl SET col = (SELECT col from tbl2);
}}}

 Syntax not supported:
{{{
UPDATE tbl SET ( col1, col2 ) = (SELECT col1, col2 from tbl2);
}}}

14. TODO : Mention port from sysdate to CURRENT_TIMESTAMP, and research their 
differences (formatting etc.).

= Tablespaces =

 Talespaces are supported in Postgres, but they do not mean exactly the same 
thing as in Oracle. There is a GUC variable in Postgres that allows us to set a 
global tablespace (at system or session level), and any object being created 
that does not have a TABLESPACE clause gets created in that 
{quote}global{quote} tablespace.

 So we have two options.
  1. If having per-object tablespace is important, then we can keep these 
usages intact for Postgres.
  2. Or, strip off the TABLESPACE clause from all table and index creation 
scripts, and use the default_tablespace Postgres GUC variable.

Note: Tablespace feature was introduced in Postgres 8.0, and hence not 
available in Postgres version 7.4.

= Datatype handling =

 Special care needs to be taken while mapping datatypes. Following generic 
mappings are recommended, but we might need a few iterations to achieve optimal 
performance while retaining application behavior and portability.

 * varchar2, nvarchar2, clob, long -> varchar (or text)

 * nchar(p) -> char(n)

 * number -> numeric (alternatives: bigint, int, smallint, float, double, real)

 * date -> timestamp (because 'date' in PG stores time component as 00:00:00);
 Choose carefully, what does the application need? date, time or date+time?

 * blob, raw, longraw -> bytea (+application change needed)

= Porting tables =

 * Port the triggers to pl/pgsql language (created in the same script as the 
table).

 * Change DEFAULT clause of 'date' columns from
{{{
defualt (sysdate)
}}}
 to
{{{
default(CURRENT_TIMESTAMP)
}}}

 * TABLESPACE clause in PRIMARY KEY clause needs to be changed if porting to 
7.4 because 7.4 does not support tablespaces.

 * Strip out NOLOGGING clause. (incompatible)
 * Strip out ENABLE ROW MOVEMENT. (incompatible)
 * Strip out STORAGE clause. (incompatible)

= Porting Sequences =

 Sequences are available in both Oracle and Postgres, with minor differences.

 * Instead of seq_name.nextval, in Postgres we should do nextval( 'seqname' ).

 * Same applies to curval too.

 * MAXVAL clause of CREATE SEQUENCE command in Postgres is sensitive to the 
underlying datatype.

= Porting Views =

 * Oracle stryle Outer Join syntax should be changed to ANSI:
{{{
(+) -> {LEFT|RIGHT} [OUTER] JOIN
}}}
 Beware when there are many tables in the FROM clause.

 * Some occurances of a function multiset() are seen, which accepts a SELECT 
query; needs more research. TODO

= Porting Packages =

 * Break up packages into individual functions.

 * CURSOR package variables.
 Most package variables are CURSORs; see if they can be replaced with inline 
cursors in stored procedures. Porting these cursor variables will be 
problematic if these cursors are opened, executed and closed in different calls 
to database.

 * Non-CURSOR package variables.
 There is some usage of package-variables that are not CURSORs. These are 
mostly varchars like 'version'. It is recommended that a database table be 
created with package_name, variable_name, type, value as columns, and be used 
in the code. Hopefully, these variables are accesses only in the PL/SQL so the 
main application can be left alone.

 * Private variables.
 There seems to be some usage of package private-variables, but these are just 
declarations, with no code using them. Remove them after consensus from 
community.

= Porting Procedures/Functions/Trigger Bodies =

 * Default values for parameters. ( TODO, needs more research )

 * COMMIT/ROLLBACK inside PL/PGSQL.
 Transaction boundaries inside PL/PGSQL are not supported; need to handle this 
on per-case basis.

 COMMIT/ROLLBACK inside PL/SQL code means that the calling application relies 
heavily on the fact that the DB can do that. Get the developer's POV on getting 
rid of such use (even on Oracle PL/SQL).

 Note: SAVEPOINTs in PL/PGSQL 'are' supported using EXCEPTION handling feature.

 * Port DETERMINISTIC pragma to Postgres as IMMUTABLE/STABLE/VOLATILE.

 * RAISE mechanism of raisng exception needs to be migrated to use RAISE 
EXCEPTION.

 * Autonomous transactions... A BIG TODO.
 Use dblink in conjunction with views to get over this.

 * CURSOR variables are supported in PL/PGSQL, with a slight syntax difference.

 * BULK COLLECT: No direct mapping. TODO
 Posiibily convert into a slow non-BULK operation. The usage that has been 
noticed till now can be easily modified to not use this feature.

 * Implicit FOR .. LOOP variable declarations.
 PL/SQL does not require explicit declaration of variables used for LOOPing. We 
have to declare those variables explicitly in PL/PGSQL. The datatype for the 
CURSOR-FOR LOOP should be RECORD.

 * TODO Get alternative for DUP_VAL_ON_INDEX (one use in new_user_postop.sql)

 * %TYPE usage in parameter datatypes is supported.

 * PRAGMA RESTRICT_REFERENCES(org_channel_setting, WNDS, RNPS, WNPS);
 This is clearly not supported, understand it's necessity and remove if not 
needed.

 * RAISE_APPLICATION_ERROR() being used.
 Understand the need for it, and port it over to Postgres using RAISE so that 
the app feels minimal pain.

= Porting Objects =

 There's only one OBJECT type in the schema, evr_t. The only requirement that 
has been noticed of this object is that, that it has to have a ORDER member
function, so that the queries usin this type can perform ORDER BY based on this 
datatype.

 This simple usage of this feature can be easily ported to Postgres by using a 
combination of CREATE TYPE and CREATE OPERATOR <=(evr_t, evr_t).

= Porting Synonyms =

 Synonyms are not supported in Postgres.

 It seems that synonyms are being used as a convenience (after all, thats what 
they are!), so we propose that the calling code be changed to reference the 
objects directly. (Need to vet it out with the community).

= Porting Types =

 There are 4 TYPE objects in schema, and all of them are used only in stored 
procedures, and two views (using multiset()). So, hopefully it wil be easy to 
migrate that PL/SQL code, without afecting the rest of the code. TODO

occurances in schema: 16; find ./ -type f | grep -v .html | xargs grep -iwE 
'channel_name_t|user_group_id_tuser_group_id_t|user_group_label_t|user_group_name_t'

 Note: Its seems that these types are only being used as arrays (seen from 
behavior of functions channel_name_join(), ID_JOIN() and LABEL_JOIN() ). In 
that case, we can easily replace them by postgres ARRAYs.

= Porting Exceptions =

.) Port the RHN_Exception package using RAISE EXCEPTION.

.) Postgres version 7.4's PL/PGSQL does not have EXCEPTION support.

TODO:
=====

.) What would channel_name_join() return if the first IF condition succeeds?
'' or NULL?

.) One time anonymous block usage in new_user_postop.sql; handle it.

_______________________________________________
Spacewalk-devel mailing list
Spacewalk-devel@redhat.com
https://www.redhat.com/mailman/listinfo/spacewalk-devel

Reply via email to