Porting Applications From Oracle To PostgreSQL

3,936 views

Published on

presented at the European PGDay 2008

Published in: Technology, Business
  • Be the first to comment

Porting Applications From Oracle To PostgreSQL

  1. 1. <ul><li>Peter Eisentraut </li></ul><ul><ul><ul><li>Sun Microsystems </li></ul></ul></ul>PORTING APPLICATIONS FROM ORACLE TO POSTGRESQL
  2. 2. Why? – Reasons for Porting <ul><li>Number One reasons: Cost </li></ul><ul><li>Most people appear to come from Oracle and Informix </li></ul><ul><li>But porting can be pretty difficult </li></ul><ul><li>A rewrite might be better </li></ul>
  3. 3. Tools <ul><li>Essential: </li></ul><ul><li>orafce </li></ul><ul><li>ora2pg </li></ul><ul><li>Also useful: </li></ul><ul><li>TOra </li></ul><ul><li>DBD::Oracle </li></ul><ul><li>Oracle Instant Client </li></ul>
  4. 4. Critical Syntax Differences <ul><li>Identifier quoting: “foo” vs. foo vs. FOO vs. “FOO” </li></ul><ul><ul><li>better not to mix quoted and unquoted </li></ul></ul><ul><li>SELECT foo [AS] bar FROM ... </li></ul><ul><ul><li>fixed in PostgreSQL 8.4 </li></ul></ul><ul><li>MINUS instead of EXCEPT </li></ul><ul><ul><li>search and replace </li></ul></ul><ul><li>SELECT ... FROM dual </li></ul><ul><ul><li>fixed through orafce </li></ul></ul><ul><li>SQL key words </li></ul>
  5. 5. Porting the SQL Schema <ul><li>Many things work without problems: </li></ul><ul><li>Table definition </li></ul><ul><li>Columns </li></ul><ul><li>Constraints </li></ul><ul><li>Views </li></ul><ul><li>Many queries </li></ul><ul><li>Locking, concurrency control </li></ul>
  6. 6. Data Types <ul><li>varchar2 -> varchar or text </li></ul><ul><li>clob, long -> varchar or text </li></ul><ul><li>nvarchar2, nclob -> varchar or text </li></ul><ul><li>number -> numeric or bigint or int or smallint or double precision or real (bug potential) </li></ul><ul><li>binary_float, binary_double -> real/double precision </li></ul><ul><li>blob, raw, long raw -> (bytea) </li></ul><ul><li>date -> date or timestamp </li></ul>
  7. 7. Data Types – Development Plan <ul><li>Implement missing SQL standard types in PostgreSQL: </li></ul><ul><li>blob, clob, nclob </li></ul><ul><li>Add some Oracle types to orafce: </li></ul><ul><li>varchar2, nvarchar2 </li></ul><ul><li>long </li></ul><ul><li>number </li></ul><ul><li>binary_float, binary_double </li></ul>
  8. 8. Built-in Functions <ul><li>PostgreSQL supports many compatibility functions. </li></ul><ul><li>orafce supports even more compatibility functions. </li></ul><ul><li>It's easy to write your own. </li></ul><ul><li>Manual work necessary for: </li></ul><ul><ul><li>sysdate -> current_timestamp or localtimestamp </li></ul></ul><ul><ul><li>decode -> CASE </li></ul></ul><ul><ul><li>seqname.nextval -> nextval('seqname') </li></ul></ul>
  9. 9. Functions with Default Parameters <ul><li>CREATE FUNCTION foo (a int, b int, c int = 0) ... </li></ul><ul><li>becomes </li></ul><ul><li>CREATE FUNCTION foo (a int, b int, c int) ... </li></ul><ul><li>CREATE FUNCTION foo (a int, b int) ... AS $$ SELECT foo(a, b, 0) $$; </li></ul><ul><li>This doesn't always work for the general case. </li></ul><ul><li>PostgreSQL might support this better in the future. </li></ul>
  10. 10. Outer Joins <ul><li>Oracle supports SQL join syntax, but most people don't use it. </li></ul><ul><li>To port: </li></ul><ul><li>SELECT * FROM a, b WHERE a.x = b.y(+) </li></ul><ul><li>becomes </li></ul><ul><li>SELECT * FROM a LEFT JOIN b ON a.x = b.y </li></ul><ul><li>Po </li></ul>
  11. 11. Null Values <ul><li>Oracle has NULL equivalent to '' </li></ul><ul><li>Therefore, '' = '' is not true </li></ul><ul><li>Causes all kinds of logical inconsistencies </li></ul><ul><li>Just hope your code doesn't rely too much on this </li></ul>
  12. 12. Triggers <ul><li>Same concept, different syntax: </li></ul><ul><li>CREATE TRIGGER foo AFTER action ON table AS BEGIN ... END; </li></ul><ul><li>becomes </li></ul><ul><li>CREATE OR REPLACE FUNCTION foo_tg() RETURNS TRIGGER LANGUAGE xxx AS $$ ... $$; </li></ul><ul><li>CREATE TRIGGER foo AFTER action ON table EXECUTE PROCEDURE foo_tg(); </li></ul>
  13. 13. Date/Time Processing <ul><li>Remember: date might be timestamp </li></ul><ul><ul><li>Then date + int might become timestamp + int, which doesn't work. </li></ul></ul><ul><li>to_char() is mostly compatible, but less robust </li></ul><ul><li>NLS_DATE_FORMAT -> locale settings </li></ul><ul><li>orafce helps: to_char(), last_day(), add_months(), ... </li></ul><ul><li>Code rewrite is sometimes preferrable. </li></ul>
  14. 14. ROWNUM and ROWID <ul><li>ROWNUM: </li></ul><ul><ul><li>Rewrite using LIMIT, or </li></ul></ul><ul><ul><li>Use generate_series, or </li></ul></ul><ul><ul><li>Handle in the client, or </li></ul></ul><ul><ul><li>Window functions in 8.4? </li></ul></ul><ul><li>ROWID: </li></ul><ul><ul><li>Similar to ctid </li></ul></ul><ul><ul><li>Not portable </li></ul></ul><ul><ul><li>Query can usually be rewritten </li></ul></ul><ul><ul><ul><li>Sometimes used as workaround for lack of joins in UPDATE or DELETE </li></ul></ul></ul>
  15. 15. Other Porting Issues <ul><li>Indexes </li></ul><ul><li>Optimizer hints </li></ul><ul><li>Encodings, locales </li></ul><ul><li>Partitioning </li></ul>
  16. 16. Things That Won't Work Easily <ul><li>CONNECT BY </li></ul><ul><li>Window functions </li></ul><ul><li>Materialized views, snapshots </li></ul><ul><li>Database links </li></ul><ul><li>Autonomous transactions </li></ul><ul><li>Synonyms </li></ul><ul><li>Virtual Private Database (VPD) </li></ul><ul><li>XML </li></ul>(= your project might balloon if you have a lot of these)
  17. 17. PL/SQL vs. PL/pgSQL <ul><li>Very similar, but not really that compatible </li></ul><ul><li>Count on having to manually touch up every single function/procedure </li></ul><ul><li>See also http://www.postgresql.org/docs/current/static/plpgsql-porting.html </li></ul>
  18. 18. PL/SQL vs. PL/pgSQL: Major Diffs <ul><li>CREATE FUNCTION ... RETURN -> RETURNS </li></ul><ul><li>Quote function body ($$ ... $$) </li></ul><ul><li>Add DECLARE for variable definitions block </li></ul><ul><li>Columns vs. variables name clashes </li></ul><ul><li>Packages </li></ul><ul><li>Package variables </li></ul><ul><li>cursorname%ROWTYPE -> RECORD </li></ul><ul><li>PERFORM procname(); </li></ul>
  19. 19. PL/SQL vs. PL/pgSQL: More Diffs <ul><li>Intra-procedure COMMIT and ROLLBACK </li></ul><ul><li>Exception handling </li></ul><ul><ul><li>Implicit rollback in PostgreSQL </li></ul></ul><ul><ul><li>Oracle code often has complex savepoint-using code to achieve the same -> delete it. </li></ul></ul><ul><ul><li>Exception names and error codes are different. </li></ul></ul><ul><li>NO_DATA_FOUND exceptions -> use SELECT INTO STRICT or IF NOT FOUND </li></ul>
  20. 20. sqlplus vs. psql <ul><li>sqlplus is more powerful for scripting. </li></ul><ul><li>psql is better for interactive use. </li></ul><ul><li>With careful naming conventions and use of variables, some scripts can be ported. </li></ul><ul><li>Better rewrite all the scripts. </li></ul>
  21. 21. Other Things to Think About <ul><li>Backup, recovery </li></ul><ul><li>Setup scripts </li></ul><ul><li>Maintenance scripts </li></ul><ul><li>Test suite </li></ul><ul><li>Long-term code maintenance </li></ul><ul><li>Legacy environments </li></ul><ul><li>Adjusting client code </li></ul>
  22. 22. Conclusions <ul><li>It's possible to write portable Oracle applications, but most people don't do it. </li></ul><ul><li>Porting projects range from trivial to nearly impossible. </li></ul><ul><li>Rewrites or complete redesigns might work better. </li></ul><ul><li>Careful evaluation and planning is advisable. </li></ul>
  23. 23. Contribute <ul><li>Porting projects are a good source for feature ideas and bug fixes. </li></ul><ul><li>Contribute your improvements: </li></ul><ul><ul><li>ora2pg </li></ul></ul><ul><ul><li>orafce </li></ul></ul><ul><ul><li>PL/pgSQL </li></ul></ul><ul><ul><li>PL/Java </li></ul></ul><ul><li>Record experiences in wiki </li></ul><ul><li>http://wiki.postgresql.org/wiki/Oracle_Compatibility_Tasks </li></ul>
  24. 24. PORTING ORACLE APPLICATIONS TO POSTGRESQL <ul><li>Peter Eisentraut </li></ul><ul><ul><li>[email_address] </li></ul></ul>

×