Giter VIP home page Giter VIP logo

orafce / orafce Goto Github PK

View Code? Open in Web Editor NEW
477.0 40.0 157.0 2.31 MB

The "orafce" project implements in Postgres some of the functions from the Oracle database that are missing (or behaving differently).Those functions were verified on Oracle 10g, and the module is useful for production work.

License: Other

Makefile 0.30% C 57.73% PLpgSQL 38.90% Yacc 0.26% Lex 2.81%
postgresql extension c postgresql-extension oracle-to-postgres oracle orafce

orafce's Introduction

Orafce - Oracle’s compatibility functions and packages

Functions and operators that emulate a subset of functions and packages from the Oracle RDBMS.

There is an associated Google group - https://groups.google.com/forum/?hl=en#!forum/orafce-general

Oracle functions and Oracle packages

This module contains some useful functions that can help with porting Oracle application to PostgreSQL or that can be generally useful.

Built-in Oracle date functions have been tested against Oracle 10 for conformance. Date ranges from 1960 to 2070 work correctly. Dates before 1100-03-01 cannot be verified due to a bug in Oracle.

All functions are fully compatibles with Oracle and respect all known format strings. Detailed descriptions can be found on the internet. Use keywords like : oracle round trunc date iyyy.

List of format strings for trunc, round functions

Y,YY,YYY,YYYY,SYYY,SYEAR	year
I,IY,IYY,IYYY			iso year
Q,				quarter
WW				week, day as first day of year
IW				week, beginning Monday
W				week, day as first day of month
DAY,DY,D			first day of week, sunday
MONTH,MON,MM,RM			month
CC,SCC				century
DDD,DD,J			day
HH,HH12,HH24			hour
MI				minute

Functions round up. That is, a date of July 1st will be rounded to the next year. The 16th of July will be rounded to August.

Date Functions

  • add_months(date, integer) date - Returns date plus n months

    	add_months(date '2005-05-31',1) -> 2005-06-30
  • last_date(date) date - Returns last day of the month based on a date value

    	last_day(date '2005-05-24') -> 2005-05-31
  • next_day(date, text) date - Returns the first weekday that is greater than a date value

    	next_day(date '2005-05-24', 'monday') -> 2005-05-30
  • next_day(date, integer) date - Same as above. The second argument should be 1..7 and interpreted as Sunday..Satday.

    	next_day(date '2005-05-24', 1) -> 2005-05-30
  • months_between(date, date) numeric - Returns the number of months between date1 and date2. If a fractional month is calculated, the months_between function calculates the fraction based on a 31-day month.

    	months_between(date '1995-02-02', date '1995-01-01') -> 1.0322580645161
  • trunc(date, text) date - truncate date according to the specified format

    	trunc(date '2005-07-12', 'iw') -> 2005-07-11
  • round(date, text) date - will round dates according to the specified format

    	round(date '2005-07-12', 'yyyy') -> 2006-01-01
  • to_date(text) timestamp - will typecast input text to timestamp. The GUC orafce.nls_date_format is used to specify input text format for this function. If the value is left blank or set as DEFAULT then input text format according to PostgreSQL’s datestyle GUC setting.

    orafce.nls_date_format value to DEFAULT
    	to_date('2014-05-19 17:23:53+5:30') -> 2014-05-19 17:23:53
    orafce.nls_date_format='YYYY-MMDD HH24:MI:SS'
    	to_date('2014-0519 17:23:53+5:30')  -> 2014-05-19 17:23:53

oracle.date data type

This module contains implementation of oracle compatible DATE data type "oracle.date" and functions which are using DATE data type like oracle.add_months,oracle.last_day(),oracle.next_day(),oracle.months_between() etc.

Example:

    set search_path TO oracle,"$user", public, pg_catalog;
    create table oracle_date(col1 date);
    insert into oracle_date values('2014-06-24 12:12:11'::date);
    select * from oracle_date;
            col1
    ---------------------
     2014-06-24 12:12:11
    (1 row)

oracle.date functions

  • oracle.add_months(timestamp with time zone, integer) - Returns date and time plus n months

    	oracle.add_months(oracle.date'2005-05-31 10:12:12',1) -> 2005-06-30 10:12:12
  • oracle.last_day(timestamp with time zone) - Returns last day of the month based on a date value

    	oracle.last_day(oracle.date '2005-05-24 11:12:12') -> 2005-05-31 11:12:12
  • oracle.next_day(timestamp with time zone, text) - Returns the first weekday that is greater than a date value

    	oracle.next_day(oracle.date '2005-05-24 10:12:12', 'monday') -> 2005-05-30 10:12:12
  • oracle.next_day(timestamp with time zone, integer) - Same as above. The second argument should be 1..7 and interpreted as Sunday..Saturday.

    	oracle.next_day(oracle.date '2005-05-24 11:21:12', 1) -> 2005-05-29 11:21:12
  • oracle.months_between(timestamp with time zone, timestamp with time zone) - Returns the number of months between timestamp1 and timestamp2. If a fractional month is calculated, the months_between function calculates the fraction based on a 31-day month.

    	oracle.months_between(oracle.date '1995-02-02 10:00:00', oracle.date '1995-01-01 10:21:11') -> 1.03225806451613
  • oracle.to_date(text,text) - Returns timestamp without time zone.

    	oracle.to_date('02/16/09 04:12:12', 'MM/DD/YY HH24:MI:SS') -> 2009-02-16 04:12:12
  • oracle.to_date(text) - Returns oracle.date

    	oracle.to_date('02/16/09 04:12:12') -> 2009-02-16 04:12:12
  • oracle.sysdate() - Returns statement timestamp at server timezone (orafce.timezone)

    	oracle.sysdate() -> 2015-12-09 17:47:56
  • oracle.dbtimezone - Returns server time zone - emulated via orafce.timezone

    	oracle.dbtimezone() -> GMT
  • oracle.sessiontimezone() - Returns session timezone - current PostgreSQL timezone

    	oracle.sessiontimezone() -> Europe/Prague
  • oracle.to_char(timestamp) - Returns timestamp in nls_date_format.

    	orafce.nls_date_format='YY-MonDD HH24:MI:SS'
    	oracle.to_char(to_date('14-Jan08 11:44:49+05:30')) -> 14-Jan08 11:44:49
    	orafce.nls_date_format='YY-MonDD HH24:MI:SS'
    	oracle.to_char(oracle.to_date('21052014 12:13:44+05:30','DDMMYYYY HH24:MI:SS')) -> 14-May21 12:13:44

oracle.date Operators

  • oracle.+(oracle.date,smallint) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') + 9::smallint -> 2014-07-11 10:08:55
  • oracle.+(oracle.date,integer) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') + 9::integer -> 2014-07-11 10:08:55
  • oracle.+(oracle.date,bigint) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') + 9::bigint -> 2014-07-11 10:08:55
  • oracle.+(oracle.date,numeric) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') + 9::numeric -> 2014-07-11 10:08:55
  • oracle.-(oracle.date,smallint) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') - 9::smallint -> 2014-06-23 10:08:55
  • oracle.-(oracle.date,integer) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') - 9::integer -> 2014-06-23 10:08:55
  • oracle.-(oracle.date,bigint) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') - 9::bigint -> 2014-06-23 10:08:55
  • oracle.-(oracle.date,numeric) - Returns oracle.date

    	oracle.to_date('2014-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') - 9::numeric -> 2014-06-23 10:08:55
  • oracle.-(oracle.date,oracle.date) - Returns double precision

    	oracle.to_date('2014-07-17 11:10:15', 'yyyy-mm-dd hh24:mi:ss') - oracle.to_date('2014-02-01 10:00:00', 'yyyy-mm-dd hh24:mi:ss') -> 166.048785

You need to set search_path TO oracle,"$user", public, pg_catalog because functions like oracle.add_months,oracle.last_day,oracle.next_day,oracle.months_between are installed side-by-side with pg_catalog.add_months,pg_catalog.last_day,pg_catalog.next_day,pg_catalog.months_between.

Table dual

PostgreSQL does not need Oracle’s table 'dual', but since it is intensively used by Oracle users, it has been added in orafce. This table is in schema oracle. Usually you want allow unqualified access - so you should to add this schema to search_path configuration (like search_path = 'oracle, pg_catalog, "$user", public' in postgresql.conf).

Package dbms_output

PostgreSQL sends information to the client via RAISE NOTICE. Oracle uses dbms_output.put_line(). This works differently from RAISE NOTICE. Oracle has a session queue, put_line() adds a line to the queue and the function get_line() reads from queue. If flag 'serveroutput' is set, then client over all sql statements reads queue. You can use:

    select dbms_output.enable();
    select dbms_output.put_line('first_line');
    select dbms_output.put_line('next_line');
    select * from dbms_output.get_lines(0);

or

    select dbms_output.enable();
    select dbms_output.serveroutput('t');
    select dbms_output.put_line('first_line');

This package contains the following functions: enable(), disable(), serveroutput(), put(), put_line(), new_line(), get_line(), get_lines(). The package queue is implemented in the session’s local memory.

Package utl_file

This package allows PL/pgSQL programs to read from and write to any files that are accessible from server. Every session can open a maximum of ten files and max line size is 32K. This package contains following functions:

  • utl_file.fclose(file utl_file.file_type) - close file

  • utl_file.fclose_all() - close all files

  • utl_file.fcopy(src_location, src_filename, dest_location, dest_filename[, start_line][, end_line]) - copy text file

  • utl_file.fflush(file utl_file.file_type) - flushes all data from buffers

  • utl_file.fgetattr(location, filename) - get file attributes

  • utl_file.fopen(location text, filename text, file_mode text [, maxlinesize int] [, encoding name]) utl_file.file_type - open file

  • utl_file.fremove(location, filename) - remove file

  • utl_file.frename(location, filename, dest_dir, dest_file[, overwrite]) - rename file

  • utl_file.get_line(file utl_file.file_type) text - read one line from file

  • utl_file.get_nextline(file utl_file.file_type) text - read one line from file or returns NULL

  • utl_file.is_open(file utl_file.file_type) bool - returns true, if file is opened

  • utl_file.new_line(file utl_file.file_type [,rows int]) - puts some new line chars to file

  • utl_file.put(file utl_file.file_type, buffer text) - puts buffer to file

  • utl_file.put_line(file utl_file.file_type, buffer text) - puts line to file

  • utl_file.putf(file utl_file.file_type, format buffer [,arg1 text][,arg2 text][..][,arg5 text]) - put formatted text into file

  • utl_file.tmpdir() - get path of temp directory

Because PostgreSQL doesn’t support call by reference, some functions are slightly different: fclose and get_line.

  declare f utl_file.file_type;
  begin
    f := utl_file.fopen('/tmp', 'sample.txt', 'r');
    <<readl>>
    loop
      begin
        raise notice '%', utl_file.get_line(f);
      exception
        when no_data_found then
          exit readl;
      end;
    end loop;
    f := fclose(f);
  end;

or second (with PostgreSQL specific function get_nextline)

    declare
      f utl_file.file_type;
      line text;
    begin
      f := utl_file.fopen('/tmp', 'sample.txt', 'r');
      loop
        line := utl_file.get_nextline(f);
        exit when line is NULL;
        raise notice '%', line;
    exception
      when others then
        utl_file.fclose_all();
    end;

Before using the package you have to set the utl_file.utl_file_dir table. It contains all allowed directories without ending symbol ('/' or '\'). On WinNT platform, the paths have to end with symbol '\' every time.

Directory entries can be named (second column in table utl_file.utl_file_dir). The location parameter can be either the directory name or the dictionary path. The location is first interpreted and checked as a directory name. If not found (in 2nd column), then the location is interpreted and checked as a path.

Functions from utl_file package (schema on Postgres) requires a access to table utl_file.utl_file_dir. This fact can be used to control what users can use these functions or not. Default setting is READ for PUBLIC. INSERT, UPDATE can do only privileged user (super user). So unprivileged user can use functions from this package, but cannot to change list of safe directories (content of utl_file.utl_file_dir table). The content of this table is visible for PUBLIC (or should be visible for users who uses functions from this package).

package dbms_sql

This is implementation of Oracle’s API of package DBMS_SQL

It doesn’t ensure full compatibility, but should to decrease a work necessary for successful migration.

Attention: PostgreSQL architecture is different than Oracle’s architecture. PL/pgSQL is executed in same context like SQL engine. Then is not any reason to use Oracle’s patterns like bulk collect and iteration over collection in Postgres to get good performance. This code is designed to reduce work related to porting some applications from Oracle to Postgres, and it can work well. But there will not be any performance advantage aganst buildin PL/pgSQL statements. The emulation of Oracle’s API has memory and CPU overhead, that can be significant on bigger data.

Functionality

This extension implements subset of Oracle’s dbms_sql interface. The goal of this extension is not a compatibility with Oracle, it is designed to reduce some work related migration Oracle’s applications to Postgres. Some basic bulk DML functionality is supported:

    do $$
    declare
      c int;
      a int[];
      b varchar[];
      ca numeric[];
    begin
      c := dbms_sql.open_cursor();
      call dbms_sql.parse(c, 'insert into foo values(:a, :b, :c)');
      a := ARRAY[1, 2, 3, 4, 5];
      b := ARRAY['Ahoj', 'Nazdar', 'Bazar'];
      ca := ARRAY[3.14, 2.22, 3.8, 4];

      call dbms_sql.bind_array(c, 'a', a, 2, 3);
      call dbms_sql.bind_array(c, 'b', b, 3, 4);
      call dbms_sql.bind_array(c, 'c', ca);
      raise notice 'inserted rows %d', dbms_sql.execute(c);
    end;
    $$;

    do $$
    declare
      c int;
      a int[];
      b varchar[];
      ca numeric[];
    begin
      c := dbms_sql.open_cursor();
      call dbms_sql.parse(c, 'select i, ''Ahoj'' || i, i + 0.003 from generate_series(1, 35) g(i)');
      call dbms_sql.define_array(c, 1, a, 10, 1);
      call dbms_sql.define_array(c, 2, b, 10, 1);
      call dbms_sql.define_array(c, 3, ca, 10, 1);

      perform dbms_sql.execute(c);
      while dbms_sql.fetch_rows(c) > 0
      loop
        call dbms_sql.column_value(c, 1, a);
        call dbms_sql.column_value(c, 2, b);
        call dbms_sql.column_value(c, 3, ca);
        raise notice 'a = %', a;
        raise notice 'b = %', b;
        raise notice 'c = %', ca;
      end loop;
      call dbms_sql.close_cursor(c);
    end;
    $$;

There is function dbms_sql.describe_columns_f, that is like procedure dbms_sql.describe_columns. Attention, the type ids are related to PostgreSQL type system. The values are not converted to Oracle’s numbers

    do $$
    declare
      c int;
      r record;
      d dbms_sql.desc_rec;
    begin
      c := dbms_sql.open_cursor();
      call dbms_sql.parse(c, 'select * from pg_class');
      r := dbms_sql.describe_columns(c);
      raise notice '%', r.col_cnt;

      foreach d in array r.desc_t
      loop
        raise notice '% %', d.col_name, d.col_type::regtype;
      end loop;

      call dbms_sql.close_cursor(c);
    end;
    $$;

    do $$
    declare
      c int;
      n int;
      d dbms_sql.desc_rec;
      da dbms_sql.desc_rec[];
    begin
      c := dbms_sql.open_cursor();
      call dbms_sql.parse(c, 'select * from pg_class');
      call dbms_sql.describe_columns(c, n, da);
      raise notice '%', n;

      foreach d in array da
      loop
        raise notice '% %', d.col_name, d.col_type::regtype;
      end loop;

      call dbms_sql.close_cursor(c);
    end;
    $$;

Package dbms_pipe

This package is an emulation of dbms_pipe Oracle package. It provides inter-session communication. You can send and read any message with or without waiting; list active pipes; set a pipe as private or public; and, use explicit or implicit pipes.

The maximum number of pipes is 50.

Shared memory is used to send messages.

An example follows:

-- Session A
select dbms_pipe.create_pipe('my_pipe',10,true); -- explicit pipe creating
select dbms_pipe.pack_message('neco je jinak');
select dbms_pipe.pack_message('anything is else');
select dbms_pipe.send_message('my_pipe',20,0); -- change limit and send without waiting
select * from dbms_pipe.db_pipes; -- list of current pipes

-- Session B
select dbms_pipe.receive_message('my_pipe',1); -- wait max 1 sec for message
select dbms_pipe.next_item_type(); -- -> 11, text
select dbms_pipe.unpack_message_text();
select dbms_pipe.next_item_type(); -- -> 11, text
select dbms_pipe.unpack_message_text();
select dbms_pipe.next_item_type(); -- -> 0, no more items
select dbms_pipe.remove_pipe('my_pipe');

There are some differences compared to Oracle, however:

  • limit for pipes isn’t in bytes but in elements in pipe

  • you can send message without waiting

  • you can send empty messages

  • next_item_type knows about TIMESTAMP (type 13)

  • PostgreSQL doesn’t know about the RAW type, use bytea instead

Package dbms_alert

Another means of inter-process communication.

-- Session A
select dbms_alert.register('boo');
select * from dbms_alert.waitany(10);

-- Session B
select dbms_alert.register('boo');
select * from dbms_alert.waitany(10);

-- Session C
select dbms_alert.signal('boo','Nice day');

Package PLVdate

This module contains some functions for working with business days from package PLVdate. Detailed documentation can be found in PLVision library. This package is multicultural, but default configurations are only for european countries (see source code).

You should define your own non-business days (max 50 days) and own holidays (max 30 days). A holiday is any non-business day, which is the same every year. For example, Christmas day in Western countries.

Functions

  • plvdate.add_bizdays(day date, days int) date - Get the date created by adding <n> business days to a date

  • plvdate.nearest_bizday(day date) date - Get the nearest business date to a given date, user defined

  • plvdate.next_bizday(day date) date - Get the next business date from a given date, user defined

  • plvdate.bizdays_between(day1 date, day2 date) int - Get the number of business days between two dates

  • plvdate.prev_bizday(day date) date - Get the previous business date from a given date

  • plvdate_isbizday(date) bool - Call this function to determine if a date is a business day

  • plvdate.set_nonbizday(dow varchar) - Set day of week as non bussines day

  • plvdate.unset_nonbizday(dow varchar) - Unset day of week as non bussines day

  • plvdate.set_nonbizday(day date) - Set day as non bussines day

  • plvdate.unset_nonbizday(day date) - Unset day as non bussines day

  • plvdate.set_nonbizday(day date, repeat bool) - Set day as non bussines day, if 'repeat' is true, then day is nonbiz every year

  • plvdate.unset_nonbizday(day date, repeat bool) - Unset day as non bussines day, if 'repeat' is true, then day is nonbiz every year

  • plvdate.use_easter() - Easter Sunday and easter monday will be holiday

  • plvdate.unuse_easter();

  • plvdate.use_easter(useit boolean);

  • plvdate.using_easter() bool - If we use easter then returns true

  • plvdate.use_great_friday() - Easter Great Friday will be holiday

  • plvdate.unuse_easter();

  • plvdate.use_easter(useit boolean);

  • plvdate.using_easter() bool - If we use easter Great Friday as holiday then returns true

  • plvdate.include_start() - Include starting date in bizdays_between calculation

  • plvdate.noinclude_start();

  • plvdate.include_start(include boolean);

  • plvdate.including_start() bool;

  • plvdate.default_holidays(varchar) - load default configurations. You can use the following configurations: Czech, German, Austria, Poland, Slovakia, Russia, GB and USA at this moment.

  • configuration contains only common holidays for all regions. You can add your own regional holiday with plvdate.set_nonbizday(nonbizday, true)

Example:

postgres=# select plvdate.default_holidays('czech');
 default_holidays
 -----------------

(1 row)
postgres=# select to_char(current_date, 'day'),
           plvdate.next_bizday(current_date),
	   to_char(plvdate.next_bizday(current_date),'day');
  to_char  | next_bizday |  to_char
 ----------+-------------+-----------
 saturday  | 2006-03-13  | monday
(1 row)

Change for non-European environment:

select plvdate.unset_nonbizday('saturday');
select plvdate.unset_nonbizday('sunday');
select plvdate.set_nonbizday('friday');
select plvdate.set_nonbizday('2006-05-19', true);
select plvdate.unuse_easter();

Package PLVstr and PLVchr

This package contains some useful string and character functions. Each function supports positive and negative offsets — i.e., offset from the end of the string. For example:

plvstr.left('abcdef',2) -> ab
plvstr.left('abcdef',-2) -> abcd
plvstr.substr('abcdef',1,1) -> a
plvstr.substr('abcdef',-1,1) -> f
plvstr.substr('abcde',-2,1) -> d

List of functions:

  • plvstr.normalize(str text) - Normalize string - Replace white chars by space, replace spaces by space

  • plvstr.is_prefix(str text, prefix text, cs bool) - Returns true, if prefix is prefix of str

  • plvstr.is_prefix(str text, prefix text) - Returns true, if prefix is prefix of str

  • plvstr.is_prefix(str int, prefix int) - Returns true, if prefix is prefix of str

  • plvstr.is_prefix(str bigint, prefix bigint) - Returns true, if prefix is prefix of str

  • plvstr.substr(str text, start int, len int) - Returns substring started on start_in to end

  • plvstr.substr(str text, start int) - Returns substring started on start_in to end

  • plvstr.instr(str text, patt text, start int, nth int) - Search pattern in string

  • plvstr.instr(str text, patt text, start int) - Search pattern in string

  • plvstr.instr(str text, patt text) - Search pattern in string

  • plvstr.lpart(str text, div text, start int, nth int, all_if_notfound bool) - Call this function to return the left part of a string

  • plvstr.lpart(str text, div text, start int, nth int) - Call this function to return the left part of a string

  • plvstr.lpart(str text, div text, start int) - Call this function to return the left part of a string

  • plvstr.lpart(str text, div text) - Call this function to return the left part of a string

  • plvstr.rpart(str text, div text, start int, nth int, all_if_notfound bool) - Call this function to return the right part of a string

  • plvstr.rpart(str text, div text, start int, nth int) - Call this function to return the right part of a string

  • plvstr.rpart(str text, div text, start int) - Call this function to return the right part of a string

  • plvstr.rpart(str text, div text) - Call this function to return the right part of a string

  • plvstr.lstrip(str text, substr text, num int) - Call this function to remove characters from the beginning

  • plvstr.lstrip(str text, substr text) - Call this function to remove characters from the beginning

  • plvstr.rstrip(str text, substr text, num int) - Call this function to remove characters from the end

  • plvstr.rstrip(str text, substr text) - Call this function to remove characters from the end

  • plvstr.rvrs(str text, start int, _end int) - Reverse string or part of string

  • plvstr.rvrs(str text, start int) - Reverse string or part of string

  • plvstr.rvrs(str text) - Reverse string or part of string

  • plvstr.left(str text, n int) - Returns firs num_in characters. You can use negative num_in

  • plvstr.right(str text, n int) - Returns last num_in characters. You can use negative num_ni

  • plvstr.swap(str text, replace text, start int, length int) - Replace a substring in a string with a specified string

  • plvstr.swap(str text, replace text) - Replace a substring in a string with a specified string

  • plvstr.betwn(str text, start int, _end int, inclusive bool) - Find the Substring Between Start and End Locations

  • plvstr.betwn(str text, start text, _end text, startnth int, endnth int, inclusive bool, gotoend bool) - Find the Substring Between Start and End Locations

  • plvstr.betwn(str text, start text, _end text) - Find the Substring Between Start and End Locations

  • plvstr.betwn(str text, start text, _end text, startnth int, endnth int) - Find the Substring Between Start and End Locations

  • plvchr.nth(str text, n int) - Call this function to return the Nth character in a string

  • plvchr.first(str text) - Call this function to return the first character in a string

  • plvchr.last(str text) - Call this function to return the last character in a string

  • plvchr.is_blank(c int) - Is blank

  • plvchr.is_blank(c text) - Is blank

  • plvchr.is_digit(c int) - Is digit

  • plvchr.is_digit(c text) - Is digit

  • plvchr.is_quote(c int) - Is quote

  • plvchr.is_quote(c text) - Is quote

  • plvchr.is_other(c int) - Is other

  • plvchr.is_other(c text) - Is other

  • plvchr.is_letter(c int) - Is letter

  • plvchr.is_letter(c text) - Is letter

  • plvchr.char_name(c text) - Returns the name of the character to ascii code as a VARCHAR.

  • plvchr.quoted1(str text) - Quoted text between '''

  • plvchr.quoted2(str text) - Quoted text between '"'

  • plvchr.stripped(str text, char_in text) - Strips a string of all instances of the specified characters

Package PLVsubst

The PLVsubst package performs string substitutions based on a substitution keyword.

  • plvsubst.string(template_in text, vals_in text[]) - Scans a string for all instances of the substitution keyword and replace it with the next value in the substitution values list

  • plvsubst.string(template_in text, vals_in text[], subst_in text)

  • plvsubst.string(template_in text, vals_in text, delim_in text)

  • plvsubst.string(template_in text, vals_in text, delim_in text, subst_in text)

  • plvsubst.setsubst(str text) - Set substitution keyword to default '%s'

  • plvsubst.subst() - Retrieve substitution keyword

Examples:

select plvsubst.string('My name is %s %s.', ARRAY['Pavel','Stěhule']);
          string
 --------------------------
 My name is Pavel Stěhule.
(1 row)

select plvsubst.string('My name is %s %s.', 'Pavel,Stěhule');
          string
 --------------------------
 My name is Pavel Stěhule.
(1 row)

select plvsubst.string('My name is $$ $$.', 'Pavel|Stěhule','|','$$');
          string
 --------------------------
 My name is Pavel Stěhule.
(1 row)

Package DBMS_utility

  • dms_utility.format_call_stack()  — return a formatted string with content of call stack

postgres=# select foo2();
               foo2
 ---------------------------------
 -----  Call Stack  -----
   line             object
 number  statement  name
      1  return     function foo
      1  return     function foo1
      1  return     function foo2
(1 row)

Package PLVlex

This package isn’t compatible with original PLVlex.

postgres=# select * from
	plvlex.tokens('select * from a.b.c join d ON x=y', true, true);

 pos | token  | code |  class  | separator | mod
 ----+--------+------+---------+-----------+------
   0 | select |  527 | KEYWORD |           |
   7 | *      |   42 | OTHERS  |           | self
   9 | from   |  377 | KEYWORD |           |
  25 | a.b.c  |      | IDENT   |           |
  20 | join   |  418 | KEYWORD |           |
  25 | d      |      | IDENT   |           |
  27 | on     |  473 | KEYWORD |           |
  30 | x      |      | IDENT   |           |
  31 | =      |   61 | OTHERS  |           | self
  32 | y      |      | IDENT   |           |
(10 rows)

Warning: Keyword’s codes can be changed between PostgreSQL versions! o plvlex.tokens(str text, skip_spaces bool, qualified_names bool) - Returns table of lexical elements in str.

DBMS_ASSERT

This package protects user input against SQL injection.

  • dbms_assert.enquote_literal(varchar) varchar - Add leading and trailing quotes, verify that all single quotes are paired with adjacent single quotes.

  • dbms_assert.enquote_name(varchar [, boolean]) varchar - Enclose name in double quotes. Optional second parameter ensure loweralize of name. Attention - On Oracle is second parameter capitalize!

  • dbms_assert.noop(varchar) varchar - Returns value without any checking.

  • dbms_assert.qualified_sql_name(varchar) varchar - This function verifies that the input string is qualified SQL name.

  • dbms_assert.schema_name(varchar) varchar - Function verifies that input string is an existing schema name.

  • dbms_assert.simple_sql_name(varchar) varchar -This function verifies that the input string is simple SQL name.

  • dbms_assert.object_name(varchar) varchar - Verifies that input string is qualified SQL identifier of an existing SQL object.

PLUnit

This unit contains some assert functions.

  • plunit.assert_true(bool [, varchar]) - Asserts that the condition is true.

  • plunit.assert_false(bool [, varchar]) - Asserts that the condition is false.

  • plunit.assert_null(anyelement [, varchar]) - Asserts that the actual is null.

  • plunit.assert_not_null(anyelement [, varchar]) - Asserts that the actual isn’t null.

  • plunit.assert_equals(anyelement, anyelement [, double precision] [, varchar]) - Asserts that expected and actual are equal.

  • plunit.assert_not_equals(anyelement, anyelement [, double precision] [, varchar]) - Asserts that expected and actual are equal.

  • plunit.fail([varchar]) - Fail can be used to cause a test procedure to fail immediately using the supplied message.

Package DBMS_random

  • dbms_random.initialize(int) - Initialize package with a seed value.

  • dbms_random.normal() - Returns random numbers in a standard normal distribution.

  • dbms_random.random() - Returns random number from -2^31 .. 2^31.

  • dbms_random.seed(int)

  • dbms_random.seed(text) - Reset seed value.

  • dbms_random.string(opt text(1), len int) - Create random string

  • dbms_random.terminate() - Terminate package (do nothing in Pg)

  • dbms_random.value() - Returns a random number from [0.0 - 1.0)

  • dbms_random.value(low double precision, high double precision) - Returns a random number from [low - high)

Others functions

This module contains implementation of functions: concat, nvl, nvl2, lnnvl, decode, greatest, least, bitand, nanvl, sinh, cosh, tanh, oracle.substr and oracle.mod.

  • oracle.substr(str text, start int, len int) - Oracle compatible substring

  • oracle.substr(str text, start int) - Oracle compatible substring

  • oracle.substr(str numeric, start numeric) - Oracle compatible substring

  • oracle.substr(str numeric, start numeric, len numeric) - Oracle compatible substring

  • oracle.substr(str varchar, start numeric) - Oracle compatible substring

  • oracle.substr(str varchar, start numeric,len numeric) - Oracle compatible substring

  • oracle.lpad(string, length [, fill]) - Oracle compatible lpad

  • oracle.rpad(string, length [, fill]) - Oracle compatible rpad

  • oracle.ltrim(string text [, characters text]) - Oracle compatible ltrim

  • oracle.rtrim(string text [, characters text]) - Oracle compatible rtrim

  • oracle.btrim(string text [, characters text]) - Oracle compatible btrim

  • oracle.length(string char) - Oracle compatible length

  • oracle.listagg(str text [, separator text]) - aggregate values to list

  • oracle.wm_concat(str text) - aggregate values to comma separatated list

  • oracle.median(float4) - calculate a median

  • oracle.median(float8) - calculate a median

  • oracle.to_number(text) - converts a string to a number

  • oracle.to_number(numeric) - converts a string to a number

  • oracle.to_number(numeric,numeric) - converts a string to a number

  • public.to_multi_byte(text) - Convert all single-byte characters to their corresponding multibyte characters

  • public.to_single_byte(text) - Convert all multi-byte characters to their corresponding single-byte characters

  • oracle.greatest(anyelement, anyelement[]) - Oracle compatibility greatest, return NULL on NULL input

  • oracle.least(anyelement, anyelement[]) - Oracle compatibility least, return NULL on NULL input

  • oracle.mod(int, int) - Oracle compatibility mod, If the second parameter is zero, it returns the first parameter

  • oracle.remainder(int, int) - returns remainder of number divided by another number

  • oracle.remainder(numeric, numeric) - returns remainder of number divided by another number

  • oracle.sys_guid() - returns bytea - 16 bytes of global uniq id

You might need to set search_path to 'oracle, pg_catalog, "$user", public' because oracle.substr, oracle.lpad, oracle.rpad, oracle.ltrim, oracle.rtrim, oracle.btrim, oracle.length are installed side-by-side with pg_catalog.substr, pg_catalog.lpad, pg_catalog.rpad, pg_catalog.ltrim, pg_catalog.rtrim, pg_catalog.btrim, pg_catalog.length respectively.

Functions oracle.decode, oracle.greatest and oracle.least must always be prefixed by the schema name even if the oracle is before pg_catalog in the search_path because these functions are implemented inside PostgreSQL parser and analyzer. Without the schema name the internal functions will always be used.

Note that in case of lpad and rpad, parameters string and fill can be of types CHAR, VARCHAR, TEXT, VARCHAR2 or NVARCHAR2 (note that the last two are orafce-provided types). The default fill character is a half-width space. Similarly for ltrim, rtrim and btrim.

Note that oracle.length has a limitation that it works only in units of characters because PostgreSQL CHAR type only supports character semantics.

The oracle.substr with three arguments can returns different result (null or empty string) in dependency to setting orafce.using_substring_zero_width_in_substr variable (oracle, warning_oracle, orafce, warning_orafce). This different result is returned only when third argument (substring_length) is zero. Default is warning_oracle, thats means raising warning and returning null.

oracle.sys_guid() function

This functions returns global unique id. It calls specified functions from "uuid-ossp" extension, and then this function should be installed before function sys_guid is used. By default this function uses function uuid_generate_v1, but function uuid_generate_v1mc, uuid_generate_v4 can be used too (by setting orafce.sys_guid_source). oracle.sys_guid can use builin gen_random_uuid func too. In this case the extension "uuid-ossp" is not required.

VARCHAR2 and NVARCHAR2 Support

orafce’s VARCHAR2 implements parts of Oracle database specification about VARCHAR2:

  • Unit of type modifier = 'bytes' (for character semantics, see NVARCHAR2)

  • Unlike PostgreSQL varchar, implicit cast to VARCHAR2 does not truncate white spaces over declared maximum length

  • For these types is possible to use null safe || operator, when you enable orafce.varchar2_null_safe_concat TO true . The behaviour is very similar to Oracle.

    Attention: - when result is empty string, then result is NULL. This behaviour is
    disabled by default.
    Attention: - there is possible incompatibility between 3.7 and older Orafce
    releases. A operator function is now marked as stable (was immutable before).
    It's not possible to create functional indexes over stable or volatile expressions.
-- null safe concat (disabled by default)
SELECT NULL || 'hello'::varchar2 || NULL;

SET orafce.varchar2_null_safe_concat TO true;
SELECT NULL || 'hello'::varchar2 || NULL;

Please note that PostgreSQL does not allow to dynamically specify how we interpret varchar strings. It always interprets them as 'character' strings as determined by database encoding. So, we cannot support both BYTE and CHARACTER semantics for a given varchar type in the same database. We chose to implement the BYTE semantics as that is default in Oracle. For CHARACTER semantics, please see NVARCHAR2 which by default always implements the CHARACTER semantics.

Please be careful when using the above type to store strings consisting of multibyte encoded characters wherein each character may be composed of an arbitrary number of bytes.

NVARCHAR2 implements the following:

  • Unit of type modifier = 'characters' (using the character set/encoding of the database)

Use this type if character semantics is preferred.

Please note that unlike Oracle, orafce’s VARCHAR2 and NVARCHAR2 do not impose the 4000 bytes limit on the 'declared' size. In fact it is same as that of PostgreSQL varchar, which is about 10MB (although varchar can theoretically store values of size up to 1GB)

Some byte-based string functions to be used with VARCHAR2 strings

  • substrb(VARCHAR2, int [, int]) - extract a substring of specified length (in bytes) starting at a given byte position (counting from one); if the third argument isnot specified then length to the end of the string is considered

  • strposb(VARCHAR2, VARCHAR2) - returns the location of specified substring in a given string (counting from one)

  • lengthb(VARCHAR2) - returns the length (in bytes) of a given string

Triggers

Oracle doesn’t make differences between NULL and empty string (when a value is used as text). For Postgres NULL and empty string are different values. For simplicity is good to ensure (in Postgres database) use only NULLs (and don’t use empty strings) or use only empty strings (and don’t use NULLs) for text type columns. Both variants has some advantages and disadvantages.

This can be enusured with trigger functions:

oracle.replace_empty_strings([ 'on' | 'true' | 'warning' | 'error' ])
oracle.replace_null_strings([ 'on' | 'true' | 'warning' | 'error' ])

Optional string argument is used as indicator so these functions should to raise warning (possibly error) when row was changed inside these functions.

CREATE TABLE test(id serial, name varchar, surname varchar);
CREATE TRIGGER test_trg
  BEFORE INSERT OR UPDATE
  ON test
  FOR EACH ROW
  EXECUTE PROCEDURE oracle.replace_empty_strings();

INSERT INTO test(name, surname) VALUES('', 'Stehule');

-- name will be replaced by NULL

Emulated views

  • oracle.user_tab_columns

  • oracle.user_tables

  • oracle.user_cons_columns

  • oracle.user_constraints

  • oracle.product_componenent_version

  • oracle.user_objects

  • oracle.dba_segments

TODO

  • better documentation

  • better seralization in dbms_pipe (via _send and _recv functions)

  • alter shared memory structures by temporary tables: only locks are in shmem, (bitmaps), data in tmp tbl

License

This module is released under BSD licence.

Contributors

The project was founded in 2008 by Pavel Stehule <[email protected]>.

Other contributors:

  • Gabriele Bartolini (gbartolini)

  • Jeffrey Cohen (jcohen)

  • Giles Darold (darold)

  • Pavan Deolasee (pavanvd)

  • Peter Eisentraut (petere)

  • Beena Emerson (b-emerson)

  • Takahiro Itagaki (itagaki)

  • Zdenek Kotala (hlipa)

  • Amit Langote (amitlan)

  • Heikki Linnakangas (hlinnaka)

  • Fujii Masao

  • Marco Nenciarini (mnencia)

  • Vinayak Pokale

  • Gavin Sherry (swm)

  • Pavel Stehule (okbob)

  • Rahila Syed (rahila)

orafce's People

Contributors

amitlan avatar b-emerson avatar cstarc1 avatar danielgustafsson avatar dark-athena avatar darold avatar df7cb avatar esabol avatar gbartolini avatar gilles-migops avatar gsherry avatar higuchi-daisuke avatar hlinnaka avatar hslightdb avatar huangsongz avatar itgacky avatar japinli avatar kato-sho avatar kommiharibabu avatar leo-xm-zeng avatar mnencia avatar nori-shinoda avatar okbob avatar pavanvd avatar petere avatar sherlockcpp avatar sunhm89 avatar sunwei-ch avatar vinpokale avatar zhuqx-fnst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

orafce's Issues

Installing orafce on PostgreSQL version 10.1

Hi,
I'm trying to upgrade my postgresql version from 9.6.3 to 10.1. I'm running the pg_upgrade check option and I get the next error : could not load library "$libdir/orafce": ERROR: could not load library "path" undefined symbol: Float8GetDatum.

I downloaded the current source code and installed it via make install and I didnt get any errors.
Any idea how to handle it ? Does it suitable for version 10.1?

ROUND(double precision, integer)

It seems that ROUND(double precision, integer) is not supported in PostgreSQL.

But it is supported in Oracle:

ROUND(n, integer)

ROUND returns n rounded to integer places to the right of the decimal point. If you omit integer, then n is rounded to 0 places. The argument integer can be negative to round off digits left of the decimal point.

n can be any numeric datatype or any nonnumeric datatype that can be implicitly converted to a numeric datatype. The argument integer must be an integer. If you omit integer, then the function returns the same datatype as the numeric datatype of the argument. If you include integer, then the function returns NUMBER.

This also applyes to TRUNC(double precision, integer)

Here are the founctions that could be added to solve this issue:

CREATE or REPLACE FUNCTION oracle.round(double precision, int)
RETURNS numeric
AS $$SELECT pg_catalog.round($1::numeric, $2)$$
LANGUAGE sql;

CREATE or REPLACE FUNCTION oracle.trunc(double precision, int)
RETURNS numeric
AS $$SELECT pg_catalog.trunc($1::numeric, $2)$$
LANGUAGE sql;

Can't create extension orafce in Postgresql

Hi,
my os is redhat 7.3 and I am trying to install orafce to postgresql with psql version 9.2 and server version 9.6. Firstly, i try to install via the script orafce downloaded on github but after reading some topics about extension in postgresql, i understood that the installation only requires to run

CREATE EXTENSION orafce;

in psql because the file in .sql is already present in extension directory of postgresql. But my problem is, when i run this commands it said

ERROR: could not access file "$libdir/orafce: No such file or directory".

When i run the command

SELECT * FROM pg_available_extensions;

to find which version of orafce is compatible with my postgresql version it said version "3.1". So i run the command

CREATE EXTENSION orafce--3.1;

in my database with a superuser and this time it doesn't give any errors. But when i check the extension list in my database as the same user with

\dx

I don't see orafce and I can't use the orafce functions in my pgplsql code.

compile error : Cannot open include file: 'libintl.h' or 'sqlparse.h'

with visual studio 2010, I have an error while compiling the project.
the error messages are :

c:\program files\postgresql\9.2\include\server\c.h(96): fatal error C1083: Cannot open include file: 'libintl.h': No such file or directory

..\plvlex.c(23): fatal error C1083: Cannot open include file: 'sqlparse.h'

do you have other dependencies then PostgreSQL we need to install befole compiling the project ?

sqlparse.y:88:17: error: 'result' undeclared (first use in this function)

gcc -O3 -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv -fno-aggressive-loop-optimizations -I/usr/include/libxml2 -fpic -I. -I../../src/include -D_GNU_SOURCE -I/home/hawq/apache-hawq-src-2.3.0.0-incubating/depends/libhdfs3/build/install/usr/local/hawq/include -I/home/hawq/apache-hawq-src-2.3.0.0-incubating/depends/libyarn/build/install/usr/local/hawq/include -c -o sqlparse.o sqlparse.c
sqlparse.y: In function 'orafce_sql_yyparse':
sqlparse.y:88:17: error: 'result' undeclared (first use in this function)
elements { ((void*)result) = $1; }
^

ERROR: function nvl(integer, integer) is not unique

Hello,
using orafce 3.7
here is what I get

set search_path=oracle,public,pg_catalog;
select nvl(1,1);
org.postgresql.util.PSQLException: ERROR: function nvl(integer, integer) is not unique
Indice : Could not choose a best candidate function. You might need to add explicit type casts.
Position : 8

I don't understand why there are 3 nvl definitions (one under puplic, 2 under oracle schema) ?
Thanks in advance for your help

Regards
PAscal

Install Error when schema public doesn't exist

Hello guys,

I try to create extension in another schema than public, using postgreSQL syntax:

db1=# CREATE EXTENSION IF NOT EXISTS orafce WITH SCHEMA common;
ERROR: schema "public" does not exist

Creating public schema solves the issue it seems orafce create a view to emulate Oracle 'dual' table.

Thank you

Issue with UTL_FILE.PUT_LINE()

Hi i am migrating a function from oracle to postgresql.

    `CREATE OR REPLACE FUNCTION pda.purge ( IN_REQ_EXPORT text, IN_HEAD_EXPORT text, IN_TABLE       text, IN_NAME text, IN_CONDITION text, OUT_ERREUR OUT integer) AS $body$
   DECLARE


reqSelect varchar(10000) := '';
reqDelete varchar(10000) := '';
csv_file UTL_FILE.FILE_TYPE;
ligne varchar(10000);
records refcursor;


    BEGIN
OUT_ERREUR:=0;

reqSelect := IN_REQ_EXPORT || ' WHERE ' || IN_CONDITION;
reqDelete := ' DELETE FROM ' || IN_TABLE || ' WHERE ' || IN_CONDITION;

OPEN records FOR EXECUTE reqSelect;
    FETCH records INTO ligne;

IF Not records%NOTFOUND THEN

	csv_file := UTL_FILE.FOPEN(location     => 'EXTRACT_DIR',
	                           filename     => IN_NAME || '_' || to_char(clock_timestamp(), 'yyyyMMddhh24miss') || '.csv',
	                           open_mode    => 'w',
	                           max_linesize => 32767);

	UTL_FILE.PUT_LINE(file  => csv_file,
                  buffer => IN_HEAD_EXPORT);`

And it crash at the line UTL_FILE.PUT_LINE(file => csv_file, buffer => IN_HEAD_EXPORT);

reporting this error : ERROR: syntax error at or near "UTL_FILE"

I have the orafce well installed and all the other functions of UTL_FILE work well.
# \dx List of installed extensions Name | Version | Schema | Description ---------+---------+------------+----------------------------------------------------------------------------------------------- orafce | 3.1 | public | Functions and operators that emulate a subset of functions and packages from the Oracle RDBMS plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (2 rows)
I can't get what i am doing wrong.

make plvlex.c had some warning

plvlex.c: In function ‘plvlex_tokens’:
plvlex.c:209: warning: call to function ‘orafce_sql_yyparse’ without a real prototype
plvlex.c:39: note: ‘orafce_sql_yyparse’ was declared here

plvlex.c:39: extern int orafce_sql_yyparse();
plvlex.c:209: if (orafce_sql_yyparse(&lexems) != 0)

nvl and decode not working for different numbers data types like oracle

when using nvl or decode with different numeric data types like numeric and integer
like
select nvl(0,1.0) from dual;
it generates error
function nvl(integer, numeric) does not exist
HINT: No function matches the given name and argument types. You might need to add explicit type casts.

the workaround may be using select nvl(0.0,1.0) from dual;

utl_file P0001 UTL_FILE_INVALID_PATH

Hi there
I'm using this extension to write a file

I know every directory must be in the utl_file.utl_file_dir table

if I add /tmp then it works

if I add /tmp/wam then I always get an UTL_FILE_INVALID_PATH error

Is there a bug?

Thanks

Martin

Overflow problem on median compute

In aggregate.c the following method is erroneous:

int orafce_float8_cmp(const void a, const void *b)
{
return (int) (
((float8 ) a) - *((float8) b));
}

cast float8 to int can lead to overflow problems.

On 32 bits platforms orafce_float4_cmp is erroneous too.

This code correct the problem:

int orafce_float8_cmp(const void a, const void *b)
{
float8 diff = *((float8 *) a) - *((float8
) b);
if(diff==0)
return 0;
else if(diff<0)
return -1;
}
return 1;

acces to file via UTL_FILE

Hi , i've an issue (how do the package works)..
if i've understood, when you have install Orafce for using UTL_FILE,
It creates a table "utl_file.utl_file_dir " where directory path is stored.
To access to it i have just in my "PUT_LINE" function to specify the path directory not to make a select into that table?
that works if the directory is in the same computer (server) where postgresql is install..
if i want to acces to a specific directory in another server where there is not postgres install , how do i do?

help me

Problem when installing on macOS 10.14.1 and Postgres 10.6

Hi guys,

I'm trying to install orafce in a Mac that runs Postgres 10.6.
Running make and make install throwed no errors but when I run CREATE EXTENSION orafce; I get this error:

WARNING:  operator attribute "function" not recognized
ERROR:  operator procedure must be specified

If I try to create the extension using pgAdmin orafce appears in the combo of available extensions but after the confirmation the same error is thrown.

Any ideas?

Thanks!

Crashes due to insufficent argument checking

Running sqlsmith on a DB with orafce installed yielded a couple of
core dumps due to insufficient argument checking in some functions.
The following statements crash trying to dereference a null pointer:

select dbms_random.string(null, 42);
select dbms_pipe.create_pipe(null);
select plunit.assert_not_equals(1,2,3);

Calls orafce_sql_yyerror() with wrong arguments

That's the original definition of yyerror():

sqlparse.y:void orafce_sql_yyerror(List **result, const char *message);

But plvex.c calls that without the first argument, which will crash:

plvlex.c:extern void orafce_sql_yyerror(const char *message);
plvlex.c:           orafce_sql_yyerror("bogus input");

(Originally reported at https://bugs.debian.org/749804)

encoding bug while using orafce (ult_file)

hi there

we are trying to process some files with orafce by reading line by line

the file encoding is

file aadf.txt
aadf.txt: UTF-8 Unicode text, with very long lines

chardetect aadf.txt
aadf.txt: utf-8 with confidence 0.99

so we assume it's really a utf-8 file

the SERVER_ENCODING is UTF8
the CLIENT_ENCODING is UTF8
as well

nevertheless we get an ERROR while reading with orafce ult_file the file

ERROR: invalid byte sequence for encoding "UTF8": 0xc3
CONTEXT: PL/pgSQL function read2(text) line 24 at assignment

this is the line where it happens
line_content= utl_file.get_nextline(f);

line_content is of type text

we are processing the same file with python to insert it in the same database and that is working fine

do you have any suggestions?

Thanks

Best Regards

Martin

to_date() crashes on 32 bit with certain date formats

In the latest version 3.0.7 for PostgreSQL 9.4, orafce's tests now fail on 32 bit intel (i386) architecture because the server crashes:

test orafunc                  ... FAILED (test process exited with exit code 2)
[...]
2014-08-22 01:14:01 UTC [5095-2] LOG:  server process (PID 5164) was terminated by signal 11: Segmentation fault
2014-08-22 01:14:01 UTC [5095-3] DETAIL:  Failed process was running: select to_date('14-Jan08 11:44:49+05:30');

The full log can be seen at https://jenkins.qa.ubuntu.com/job/utopic-adt-orafce/ARCH=i386,label=adt/13/console . Notably the very same test succeeds on x86_64. Previous versions (up to 3.0.6) worked fine, but they didn't include this test yet.

This can be reproduced quite easily:

$ createdb test; psql test
test=# CREATE EXTENSION orafce;
CREATE EXTENSION
test=# set orafce.nls_date_format='DDMMYYYY HH24:MI:SS';
SET
test=# select to_date('21052014 12:13:44+05:30');
The connection to the server was lost. Attempting reset: Failed.
!> 

This is with PostgreSQL 9.4 beta 2.

Wrong function name in COMMENT command

CREATE FUNCTION oracle.dbtimezone() RETURNS text AS 'MODULE_PATHNAME','orafce_dbtimezone' LANGUAGE C STABLE STRICT; COMMENT ON FUNCTION oracle.sessiontimezone() IS 'Ruturns server time zone (orafce.timezone)';

invalid ECHO statement breaks tests with PostgreSQL 9.4.1

PostgreSQL 9.4.1 now writes an error message on invalid values of \set ECHO. orafce's tests have two invalid statements:

sql/dbms_pipe_session_B.sql:\set ECHO all;
sql/dbms_pipe_session_A.sql:\set ECHO all;

The semicolon is invalid and interpreted as part of the value, so tests fail with:

*** /tmp/adt-run.kPtv9H/build.I1z/orafce-3.0.7/expected/dbms_pipe_session_A.out 2014-07-27 20:10:01.000000000 +0000
--- /tmp/adt-run.kPtv9H/build.I1z/orafce-3.0.7/results/dbms_pipe_session_A.out  2015-02-08 10:12:42.305125312 +0000
***************
*** 9,14 ****
--- 9,15 ----
              0
  (1 row)

+ unrecognized value "all;" for "ECHO"; assuming "none"
   createimplicitpipe 
  --------------------

(same for the _B test). Merely dropping the semicolon isn't enough as the expected values aren't actually containing the echoed commands. So I suggest to either just drop the two \set ECHO all; lines, or drop the semicolon and add the echoed commands to the expected output.

Installing Orafce with Postgres 10.4 -

Hello guys,

We have been using Oracfe for both PG 9 and 10, most recent version we used was 10.2. This week, we have upgraded to 10.4 (binary download from EDB site) and hit the error below while compiling oracfe on top of it.

orafce]$ make
/usr/bin/bison -d -o sqlparse.c sqlparse.y
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -g -O2 -DMAP_HUGETLB=0x40000 -fPIC -I. -I./ -I/home/xxx/platform/vendor/postgres/postgresql-10.4-1-linux-x64-CentOS7/include/postgresql/server -I/home/xxx/platform/vendor/postgres/postgresql-10.4-1-linux-x64-CentOS7/include/postgresql/internal -I/opt/local/Current/include -D_GNU_SOURCE -I/opt/local/Current/include/libxml2 -I/opt/local/Current/include -c -o convert.o convert.c
convert.c: In function ‘orafce_to_multi_byte’:
convert.c:401:2: error: unknown type name ‘__int64’
__int64 dstlen;
^
convert.c: In function ‘orafce_to_single_byte’:
convert.c:477:2: error: unknown type name ‘__int64’
__int64 dstlen;
^
make: *** [convert.o] Error 1

Is Oracfe already supporting 10.4? Thank you.

Integration with PGXS

The current head of the repository fails when used with CREATE EXTENSION command. There are couple of issues that needs to be fixed before we can get it working.

  1. Version number mismatch - orafce.control file mentions the current version as 3.0.5, but we haven't yet renamed orafce--3.0.sql and orafce--unpackaged--3.0.sql to the corresponding 3.0.5 names.
  2. Even if we do (1), CREATE EXTENSION still fails because many CREATE FUNCTION statements in orafce--3.0.sql file have LANGUAGE specified as 'C' (quoted C). Since the catalog has the language name in lower case, these statements fail to execute.

While we can fix (2) by changing these CREATE FUNCTION statements so that the language name is not quoted, I wonder if a better strategy is to create these files from the other source sql files ? Otherwise we will have two separate sql files to maintain all the time. Comments ?

On a related note, I see that we go out of way to create appropriate orafunc.sql based on the PostgreSQL server version against we are building the module. But the uninstall script is common across all server versions. Is that OK ? Is there a possibility that we will leak certain functions after uninstall, especially if not all orafce functions are available across all PG versions ?

LOADFROMFILE

Hi,
Can we use utl_file to read the complete file and put it in a text variable so that we can insert the variable into a table ?

Thanks

ERROR: syntax error at or near "decode"

raise this error when i create extension

postgres=# create extension orafce;
ERROR:  syntax error at or near "decode"

greenplum version is gpdb-6X_STABLE and the os is CentOS Linux release 7.6.1810 (Core)

please help!!!!

RDS version?

Is there a way we could package up all the objects in orafce so that we could install them on a RDS PG instance?

Looking at what is installed via create extension orafce, it appears I just need to consolidate all the objects like functions, types, casts, etc. and then just deploy them manually to an RDS PG instance database.

Can this be done and if so what is the best way to accomplish this?

SUBSTR with negative values

This query: select SUBSTR('abcdefg',-5,4) from dual;
In Oracle gets back: "cdef"
In PostgreSQL gets back an empty string.

rpad() add a half space to the beggining instead of the end when padding multi-byte character.

When padding multi-byte characters using rpad(), a half-width space was added at the beggining.Encoding is UTF8.

$cat test.sql 
select '|' || oracle.RPAD(TO_MULTI_BYTE('±'),10,'') || '|' from dual;
$psql -f test.sql postgres                                                                             
 
  ?column?   
--------------
 | ±ああああ|
(1 行)

In such a case, the oracle rpad() adds a half-width space at the end.
I use Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit.

SQL> select '|' || RPAD(TO_MULTI_BYTE('±'),10,'') || '|' from dual;

'|'||RPAD(TO_MULT
-----------------
|±ああああ |

I think this is an error of the orafce rpad(), is it correct?

could not find function "orafce_dump"

Hi,
i am trying to create ext on postgresql 10 using this command 'CREATE EXTENSION orafce;'
and i am using windows 10, and i got this error
ERROR: could not find function "orafce_dump" in file "C:\PostgreSQL\pg10\share\postgresql\extension\orafce-10-x64.dll"

can't compile `sqlparse.y:54.1-5: invalid directive: `%code'`

I can't compile on macOS with postgresql 10.0. I also had this issue with 9.6, but was able to compile with version 3.3.0.

balrog:orafce-VERSION_3_6_0 n$ brew config
HOMEBREW_VERSION: 1.3.6-8-g15096e7
ORIGIN: https://github.com/Homebrew/brew
HEAD: 15096e7289b25ef19baa6c0455f2051583665f70
Last commit: 11 hours ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: 150c67bb6de8c16e0a8a4bb083009ed3ff8ad6fe
Core tap last commit: 2 hours ago
HOMEBREW_PREFIX: /usr/local
HOMEBREW_REPOSITORY: /usr/local/Homebrew
HOMEBREW_CELLAR: /usr/local/Cellar
HOMEBREW_BOTTLE_DOMAIN: https://homebrew.bintray.com
CPU: quad-core 64-bit haswell
Homebrew Ruby: 2.3.3 => /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.3.3/bin/ruby
Clang: 9.0 build 900
Git: 2.14.2 => /usr/local/bin/git
Perl: /usr/local/bin/perl => /usr/local/Cellar/perl/5.26.1/bin/perl
Python: /usr/local/opt/python/libexec/bin/python => /usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/bin/python2.7
Ruby: /Users/n/.rvm/rubies/ruby-2.4.2/bin/ruby
Java: 1.8.0_45
macOS: 10.12.6-x86_64
Xcode: 9.0
CLT: 9.0.0.0.1.1504363082
X11: 2.7.9 => /opt/X11
balrog:orafce-VERSION_3_6_0 n$ make
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o convert.o convert.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o file.o file.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o datefce.o datefce.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o magic.o magic.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o others.o others.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o plvstr.o plvstr.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o plvdate.o plvdate.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o shmmc.o shmmc.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o plvsubst.o plvsubst.c
clang -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -O2  -I. -I./ -I/usr/local/Cellar/postgresql/10.0/include/server -I/usr/local/Cellar/postgresql/10.0/include/internal  -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/libxml2   -c -o utility.o utility.c
/usr/bin/bison -d  -o sqlparse.c sqlparse.y
sqlparse.y:54.1-5: invalid directive: `%code'
sqlparse.y:54.7-14: syntax error, unexpected identifier
make: *** [sqlparse.c] Error 1

New release with PG10 support?

Hi,
I see that master has been updated to support PG 10, thanks for that.
Would you consider releasing a new version with these patches so I can update the packages for Debian and apt.postgresql.org?
Thanks!

Bug in to_number

Oracle: select to_number('') from dual returns NULL
PostgreSql: select to_number('') from dual throws exception ERROR: invalid input syntax for type numeric: ""

Should add check for empty string in Datum orafce_to_number(PG_FUNCTION_ARGS). Something like:
if( !buf || !*buf ) { PG_RETURN_NULL(); }

Declarations of the round and the trunc functions are duplicated

float with no precision specified is taken to mean double precision

https://www.postgresql.org/docs/9.0/static/datatype-numeric.html

CREATE OR REPLACE FUNCTION oracle.round(double precision, int)
RETURNS numeric
AS $$SELECT pg_catalog.round($1::numeric, $2)$$
LANGUAGE sql IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION oracle.round(float, int)
RETURNS numeric
AS $$SELECT pg_catalog.round($1::numeric, $2)$$
LANGUAGE sql IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION oracle.trunc(double precision, int)
RETURNS numeric
AS $$SELECT pg_catalog.trunc($1::numeric, $2)$$
LANGUAGE sql IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION oracle.trunc(float, int)
RETURNS numeric
AS $$SELECT pg_catalog.trunc($1::numeric, $2)$$
LANGUAGE sql IMMUTABLE STRICT;

sysdate() function

would it be possible to add SYSDATE() funtion

based on
CREATE or REPLACE FUNCTION SYSDATE()
RETURNS oracle.date AS $$
SELECT statement_timestamp()::oracle.date ;
$$ LANGUAGE sql ...

that returns the current date and time when statement starts (not transaction start) set for the operating system on which the database resides. The datatype of the returned value is (Oracle) DATE, and the format returned depends on the value of the NLS_DATE_FORMAT initialization parameter. The function requires no arguments.

9.5 build error

Hi,

I'm getting these while trying to build orafce against 9.5:

  • make -j3
    pipe.c: In function 'dbms_pipe_create_pipe':
    pipe.c:1093:72: error: too few arguments to function 'GetUserNameFromId'
    user = (char_)DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(p->uid)));
    ^
    In file included from pipe.c:11:0:
    /usr/pgsql-9.5/include/server/miscadmin.h:299:14: note: declared here
    extern char *GetUserNameFromId(Oid roleid, bool noerr);
    ^
    make[1]: *_* [pipe.o] Error 1
    make[1]: *** Waiting for unfinished jobs....

An error occured in VARCHAR2 type column.

Hi,
When creating INDEX with VARCHAR 2 type column or executing sort,
the following problem occurred.

ERROR:  could not determine which collation to use for string comparison
HINT:  Use the COLLATE clause to set the collation explicitly.

CentOS 7.3
PostgreSQL 9.6.2
orafce master branch

Procedure for reproducing:

$ initdb -D ~/local/pg962/data --no-locale --encoding=utf8
$ pg_ctl -D ~/local/pg962/data start
$ psql postgres -c "create extension orafce"
CREATE EXTENSION
$ psql postgres -c "create table test(x varchar2(10))"
CREATE TABLE
$ psql postgres -c "insert into test values ('1'),('aaa')"
INSERT 0 2
$ psql postgres -c "create index ON test(x)"
ERROR:  could not determine which collation to use for string comparison
HINT:  Use the COLLATE clause to set the collation explicitly.
STATEMENT: create index on test(x)
ERROR:  could not determine which collation to use for string comparison
HINT:  Use the COLLATE clause to set the collation explicitly.
$ psql postgres -c "select * from test order by x"
ERROR:  could not determine which collation to use for string comparison
HINT:  Use the COLLATE clause to set the collation explicitly.
STATEMENT: select * from test order by x
ERROR:  could not determine which collation to use for string comparison
HINT:  Use the COLLATE clause to set the collation explicitly.

I think that it is caused by not setting collatable to true with CREATE TYPE option.
A same error also occurs in NVARCHAR2.

The error is solved by the following fixes.

$ git diff
diff --git a/orafce--3.5.sql b/orafce--3.5.sql
index ebebb14..341deaf 100644
--- a/orafce--3.5.sql
+++ b/orafce--3.5.sql
@@ -2171,7 +2171,8 @@ receive = varchar2recv,
 send = varchar2send,
 category = 'S',
 typmod_in = varchar2typmodin,
-typmod_out = varchar2typmodout
+typmod_out = varchar2typmodout,
+collatable = true
 );
 
 /* CREATE CAST */
@@ -2373,7 +2374,8 @@ receive = nvarchar2recv,
 send = nvarchar2send,
 category = 'S',
 typmod_in = nvarchar2typmodin,
-typmod_out = nvarchar2typmodout
+typmod_out = nvarchar2typmodout,
+collatable = true
 );
 
 /* CREATE CAST */

regards,
ikki

Issue with UNKNOWN type in DECODE/TRUNC/SUM functions

Hello Team,

I have installed ORAFCE (3.4, 3.6) with my PostgreSQL versions (9.6 Linux and 10.0 on windows).
Most of the functions are working fine except below case

FYI - We have migrated from Oracle to PostgreSQL

Case #1

When I try to run a select query like below with decode function

select decode(lotid,1,'Lot Id Found','Lot Id not found') from public.test_decode; FYI - lotid column is of numeric type
It is showing an error like below

ERROR: function decode(numeric, integer, unknown, unknown) does not exist
LINE 1: select decode(lotid,1,'Lot Id Found','Lot Id not found') fro...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********

ERROR: function decode(numeric, integer, unknown, unknown) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 8

Case #2

At the same time, When I try to run a select query

select decode(lotid::integer,1,'Lot Id Found','Lot Id not found') from public.test_decode;
It is giving proper result

image

I already have DECODE function as decode(anyelement,anyelement,text,text) still my case 1 failed

image

FYI - My application contains many such instances of decode function with different number/types o of input

Case #3:
To make Case #1 work,

I created a function in orafce like below

CREATE OR REPLACE FUNCTION public.decode(
numeric,
integer,
text,
text)
RETURNS text AS
'$libdir/orafce', 'ora_decode'
LANGUAGE c IMMUTABLE
COST 1;
ALTER FUNCTION public.decode(numeric, integer, text, text)
OWNER TO postgres;

Now when I run a select query as in CASE #1
select decode(lotid,1,'Lot Id Found','Lot Id not found') from public.test_decode;

Now,Its terminating my session (database connection) and saying connection to the server has lost,
I didn't understand why is this happening.

CASE #4
Finally, I have created a function manually with CASE statement in it

CREATE OR REPLACE FUNCTION public.decode(
input1 numeric,
input2 integer,
input3 text,
input4 text)
RETURNS text AS
$BODY$
DECLARE

returnValue text;
BEGIN

IF input1 = input2 THEN
returnValue = input3;
ELSE
returnValue = input4;
END IF;

RETURN returnValue;
END;
$BODY$
LANGUAGE plpgsql STABLE
COST 100;
ALTER FUNCTION public.decode(numeric, integer, text, text)
OWNER TO postgres;

It is working fine as expected

My question is, why am I not able to achieve this with orafce plugin even though a function already exists?

Please let me know if I miss anything in the process.

Thanks,
Praveen

should make "all" the default target

So that this doesn't happen:

co-pg-test:/usr/local/src/pg931/orafce-VERSION_3_0_6 # make USE_PGXS=1
cp expected/orafunc2.out expected/orafunc.out
co-pg-test:/usr/local/src/pg931/orafce-VERSION_3_0_6 #

dbms_alert tests are unreliable

In automatic testing, the dbms_alert_session_X.sql test fail for me about once every 10 times, presumably because the machine is fairly busy and so cannot stay within the timeouts. I suggest to increase the timeouts in all of the tests. Alternatively, maybe there should be a way to disable that group of tests if it cannot be made more reliable.

Wrong comment on pg_catalog.substrb(varchar2, integer)

Here is it:

CREATE OR REPLACE FUNCTION pg_catalog.substrb(varchar2, integer) RETURNS varchar2 AS 'bytea_substr_no_len' LANGUAGE internal STRICT IMMUTABLE; COMMENT ON FUNCTION pg_catalog.substrb(varchar2, integer, integer) IS 'extracts specified number of bytes from the input varchar2 string starting at the specified byte position (1-based) and returns as a varchar2 string';

(from orafce--3.7.sql)

incorrect bizdays_between calculation

version is 3.2.1 from community yum repo, platform Fedora 22 x86_64

db=> select plvdate.bizdays_between('2016-06-06','2016-06-11');
 bizdays_between 
-----------------
               3
(1 row)

db=> select plvdate.bizdays_between('2016-06-06','2016-06-10');
 bizdays_between 
-----------------
               3
(1 row)

First result should be 4, as there are 4 business days between Monday and Saturday.

Even if this is what Oracle does it seems quite nonsensical.

regression test error in PG9.6 (RHEL/CentOS7 RPM)

Hello,

I tried the orafce 3.4.0 source, but an error occurs in the regression test.

RHEL/CentOS 7 posrgresql9.6 RPM provided by the community,
regression test will coredump.
Because the configure option "-enable-dtrace" is enabled in PG9.6 (RHEL/CentOS7).

I used the postgresql RPM below.
https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/repoview/postgresqldbserver96.group.html

But, there is no problem as PG9.6(RHEL/CentOS 6) RPM by the community does not have "-enable-dtrace" option.
PostgreSQL RPM configure option is different in RHEL/CentOS 6 and 7.

***** regression test *****

$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
$ psql --version
psql (PostgreSQL) 9.6.2
$
$ make installcheck
/usr/pgsql-9.6/lib/pgxs/src/makefiles/../../src/test/regress/pg_regress --inputdir=./ --bindir='/usr/pgsql-9.6/bin'    --load-language=plpgsql --schedule=parallel_schedule --encoding=utf8 --dbname=contrib_regression orafce orafce2 dbms_output dbms_utility files varchar2 nvarchar2 aggregates nlssort dbms_random
(using postmaster on Unix socket, default port)
============== dropping database "contrib_regression" ==============
DROP DATABASE
============== creating database "contrib_regression" ==============
CREATE DATABASE
ALTER DATABASE
============== installing plpgsql                     ==============
CREATE LANGUAGE
============== running regression test queries        ==============
test init                     ... ok
parallel group (2 tests):  dbms_pipe_session_A dbms_pipe_session_B
     dbms_pipe_session_A      ... FAILED (test process exited with exit code 2)
     dbms_pipe_session_B      ... FAILED (test process exited with exit code 2)
parallel group (3 tests):  dbms_alert_session_B dbms_alert_session_A dbms_alert_session_C
     dbms_alert_session_A     ... FAILED (test process exited with exit code 2)
     dbms_alert_session_B     ... FAILED (test process exited with exit code 2)
     dbms_alert_session_C     ... FAILED (test process exited with exit code 2)
test orafce                   ... FAILED (test process exited with exit code 2)
test orafce2                  ... ok
test dbms_output              ... ok
test dbms_utility             ... ok
test files                    ... ok
test varchar2                 ... ok
test nvarchar2                ... ok
test aggregates               ... ok
test nlssort                  ... ok
test dbms_random              ... ok

=======================
 6 of 16 tests failed.
=======================

***** backtrace from coredump. ******

$ gdb postgres core
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /usr/pgsql-9.6/bin/postgres...Reading symbols from /usr/lib/debug/usr/pgsql-9.6/bin/postgres.debug...done.
done.
[New LWP 828]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `postgres: postgres contrib_r'.
Program terminated with signal 11, Segmentation fault.
#0  0x00000000006c2265 in LWLockAcquire (lock=lock@entry=0x7f58f1e8ea08, mode=mode@entry=LW_EXCLUSIVE) at lwlock.c:1314
1314            TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), mode);
Missing separate debuginfos, use: debuginfo-install audit-libs-2.6.5-3.el7_3.1.x86_64 bzip2-libs-1.0.6-13.el7.x86_64 cyrus-sasl-lib-2.1.26-20.el7_2.x86_64 elfutils-libelf-0.166-2.el7.x86_64 elfutils-libs-0.166-2.el7.x86_64 glibc-2.17-157.el7_3.1.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.14.1-27.el7_3.x86_64 libattr-2.4.46-12.el7.x86_64 libcap-2.22-8.el7.x86_64 libcap-ng-0.7.5-4.el7.x86_64 libcom_err-1.42.9-9.el7.x86_64 libgcc-4.8.5-11.el7.x86_64 libgcrypt-1.5.3-13.el7_3.1.x86_64 libgpg-error-1.12-3.el7.x86_64 libselinux-2.5-6.el7.x86_64 libxml2-2.9.1-6.el7_2.3.x86_64 nspr-4.13.1-1.0.el7_3.x86_64 nss-3.28.2-1.6.el7_3.x86_64 nss-softokn-freebl-3.16.2.3-14.4.el7.x86_64 nss-util-3.28.2-1.1.el7_3.x86_64 openldap-2.4.40-13.el7.x86_64 openssl-libs-1.0.1e-60.el7_3.1.x86_64 pam-1.1.8-18.el7.x86_64 pcre-8.32-15.el7_2.1.x86_64 systemd-libs-219-30.el7_3.7.x86_64 xz-libs-5.2.2-1.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0  0x00000000006c2265 in LWLockAcquire (lock=lock@entry=0x7f58f1e8ea08, mode=mode@entry=LW_EXCLUSIVE) at lwlock.c:1314
#1  0x00007f58e9091edb in ora_lock_shmem (size=size@entry=30720, max_pipes=max_pipes@entry=30, max_events=max_events@entry=30, max_locks=max_locks@entry=256,
    reset=reset@entry=0 '\000') at pipe.c:323
#2  0x00007f58e9092bd7 in add_to_pipe (limit_is_valid=0 '\000', limit=0, ptr=0x294ef40, pipe_name=0x290fb88) at pipe.c:506
#3  dbms_pipe_send_message (fcinfo=) at pipe.c:937
#4  0x00000000005c4132 in ExecMakeFunctionResultNoSets (fcache=0x293d950, econtext=0x293d760, isNull=0x293e3f8 "\020", isDone=)
    at execQual.c:2041
#5  0x00000000005c9c5e in ExecTargetList (tupdesc=, isDone=0x7ffdcce3cf94, itemIsDone=0x293e510, isnull=0x293e3f8 "\020", values=0x293e3e0,
    econtext=0x293d760, targetlist=0x293e4e0) at execQual.c:5423
#6  ExecProject (projInfo=, isDone=isDone@entry=0x7ffdcce3cf94) at execQual.c:5647
#7  0x00000000005dec42 in ExecResult (node=node@entry=0x293d650) at nodeResult.c:155
#8  0x00000000005c3208 in ExecProcNode (node=node@entry=0x293d650) at execProcnode.c:392
#9  0x00000000005bf577 in ExecutePlan (dest=0x293b6f0, direction=, numberTuples=0, sendTuples=1 '\001', operation=CMD_SELECT,
    use_parallel_mode=, planstate=0x293d650, estate=0x293d540) at execMain.c:1569
#10 standard_ExecutorRun (queryDesc=0x28b4d10, direction=, count=0) at execMain.c:338
#11 0x00000000006d20e7 in PortalRunSelect (portal=portal@entry=0x28ad030, forward=forward@entry=1 '\001', count=0, count@entry=9223372036854775807,
    dest=dest@entry=0x293b6f0) at pquery.c:948
#12 0x00000000006d34fb in PortalRun (portal=0x28ad030, count=9223372036854775807, isTopLevel=, dest=0x293b6f0, altdest=0x293b6f0,
    completionTag=0x7ffdcce3d420 "") at pquery.c:789
#13 0x00000000006d1146 in PostgresMain (argc=, argv=, dbname=, username=) at postgres.c:1094
#14 0x000000000046f605 in BackendRun (port=0x28b5150) at postmaster.c:4271
#15 BackendStartup (port=0x28b5150) at postmaster.c:3945
#16 ServerLoop () at postmaster.c:1701
#17 0x00000000006748f8 in PostmasterMain (argc=argc@entry=1, argv=argv@entry=0x288da60) at postmaster.c:1309
#18 0x000000000047026e in main (argc=1, argv=0x288da60) at main.c:228
(gdb)

Probably,
I think that orafce needs to call LWLockRegisterTranche() before LWLockAcquire() in each process(session).

It was written as follows in lwlock.h

lwlock.h

> /*
>  * There is another, more flexible method of obtaining lwlocks. First, call
>  * LWLockNewTrancheId just once to obtain a tranche ID; this allocates from
>  * a shared counter.  Next, each individual process using the tranche should
>  * call LWLockRegisterTranche() to associate that tranche ID with appropriate
>  * metadata.  Finally, LWLockInitialize should be called just once per lwlock,
>  * passing the tranche ID as an argument.
>  *
>  * It may seem strange that each process using the tranche must register it
>  * separately, but dynamic shared memory segments aren't guaranteed to be
>  * mapped at the same address in all coordinating backends, so storing the
>  * registration in the main shared memory segment wouldn't work for that case.
>  */

For example, if you do the following in pipe.c,
then regression test will be OK.

Example:

pipe.c

----------
ora_lock_shmem()
:
:
#if PG_VERSION_NUM >= 90600

#if PG_VERSION_NUM < 100000                                                           //add
                                                                                      //add
                        {                                                             //add
                                static LWLockTranche tranche;                         //add
                                                                                      //add
                                 tranche.name = "orafce";                              //add
                                 tranche.array_base = &sh_mem->shmem_lock;             //add
                                 tranche.array_stride = sizeof(LWLock);                //add
                                 LWLockRegisterTranche(sh_mem->tranche_id, &tranche);  //add
                                                                                       //add
                         }                                                             //add
                                                                                       //add
 #endif                                                                                //add
                         shmem_lockid = &sh_mem->shmem_lock;
 
 #else
 
                         shmem_lockid = sh_mem->shmem_lockid;
 
 #endif
 
                         LWLockAcquire(shmem_lockid, LW_EXCLUSIVE);
 :
 :
----------

Regards,
kfuru

hi everyone, Issue with UTL_FILE package

I'm looking out how to use UTL_FILE package..
Every time i do"perform UTL_FILE.PUT_LINE ( myUTLfileType, ' text i want to add');"
I've my pgadmin server disconnect...and my application crashes...
what could be the problem?
thanks for your help in advance..

question on utl_file

Hi,

I'm migrating a stored procedure wich invokes oracle utl_file.fopen.
Then there an exception block, above the translation from ora2pg

do you have these error codes in orafce ?

UTL_FILE.INVALID_PATH
UTL_FILE.INVALID_MODE
UTL_FILE.INVALID_OPERATION

Thank you very much for you help

    EXCEPTION
            when UTL_FILE.INVALID_PATH then
                    RAISE NOTICE 'INVALID PATH';
                    RAISE EXCEPTION '%', 'Ouverture du fichier de traces : INVALID_PATH' USING ERRCODE = '45010';
            when  UTL_FILE.INVALID_MODE then
                    RAISE NOTICE 'INVALID MODE';
                    RAISE EXCEPTION '%', 'Ouverture du fichier de traces : INVALID_MODE' USING ERRCODE = '45010';
            when  UTL_FILE.INVALID_OPERATION then
                    RAISE NOTICE 'INVALID OPERATION';
                    RAISE EXCEPTION '%', 'Ouverture du fichier de traces : INVALID_OPERATION' USING ERRCODE = '45010';
            when  others THEN
                    RAISE NOTICE 'OTHERS :Erreur SQL%.', DBMS_UTILITY.FORMAT_ERROR_STACK;
                    RAISE EXCEPTION '%', 'Erreur SQL' || DBMS_UTILITY.FORMAT_ERROR_STACK || '.' USING ERRCODE = '45010';

do you know code returned by orafce.fopen in this case ?

Thanks
Best regarf

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.