oracle中orand使用,Postgres兼容Oracle研究——orafce调研

一、背景

PostgreSQL是和Oracle最接近的企业数据库,包括数据类型,功能,架构和语法等几个方面。甚至大多数的日常应用的性能也不会输给Oracle。

但是Oracle有些函数或者包,默认PostgreSQL是没有的,需要安装orafce包来实现这些兼容性。

orafce是PostgreSQL的一个extension,主要是为PostgreSQL提供Oracle的部分语法、函数、字典表等兼容。

二、安装orafce

版本:orafce 3.7 + PostgreSQL 10.5

注意,目前GitHub的主线版本是3.7版本,未发布。

编译安装:

解压后进入源码目录执行 make & make install

进入postgresql执行 create extension orafce

【注意事项】

下载的源码中,orafce--3.7.sql文件中下面这段sql,需要将 'BASE_TABLE' 改成 'BASE TABLE' 再编译安装

create view oracle.user_tables as

select table_name

from information_schema.tables

where table_type = 'BASE_TABLE';

三、orafce包含的内容

类型 date, varchar2 and nvarchar2

函数 concat, nvl, nvl2, lnnvl, decode, bitand, nanvl, sinh, cosh, tanh and oracle.substr

dual 表

package :

dbms_alert

dbms_assert

dbms_output

dbms_pipe

dbms_random

dbms_utility

plunit

plvchr

plvdate

plvlex

plvstr

plvsubst

utl_file

##Oracle兼容 包列表:

##在PostgreSQL里用 schema+函数 来实现。

atlas=# \dn

List of schemas

Name | Owner

--------------+--------

dbms_alert | appusr

dbms_assert | appusr

dbms_output | appusr

dbms_pipe | appusr

dbms_random | appusr

dbms_utility | appusr

oracle | appusr

plunit | appusr

plvchr | appusr

plvdate | appusr

plvlex | appusr

plvstr | appusr

plvsubst | appusr

public | appusr

utl_file | appusr

(15 rows)

## 查看包

例如dbms_output包:

atlas=# \df dbms_output.*

List of functions

Schema | Name | Result data type | Argument data types | Type

-------------+--------------+------------------+------------------------------------------+--------

dbms_output | disable | void | | normal

dbms_output | enable | void | | normal

dbms_output | enable | void | buffer_size integer | normal

dbms_output | get_line | record | OUT line text, OUT status integer | normal

dbms_output | get_lines | record | OUT lines text[], INOUT numlines integer | normal

dbms_output | new_line | void | | normal

dbms_output | put | void | a text | normal

dbms_output | put_line | void | a text | normal

dbms_output | serveroutput | void | boolean | normal

(9 rows)

##Oracle兼容 公共函数 列表:

atlas=# \df

List of functions

Schema | Name | Result data type | Argument data types | Type

--------+---------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------

public | bitand | bigint | bigint, bigint | normal

public | cosh | double precision | double precision | normal

public | decode | bigint | anyelement, anyelement, bigint | normal

public | decode | bigint | anyelement, anyelement, bigint, anyelement, bigint | normal

public | decode | bigint | anyelement, anyelement, bigint, anyelement, bigint, anyelement, bigint | normal

public | decode | bigint | anyelement, anyelement, bigint, anyelement, bigint, anyelement, bigint, bigint | normal

public | decode | bigint | anyelement, anyelement, bigint, anyelement, bigint, bigint | normal

public | decode | bigint | anyelement, anyelement, bigint, bigint | normal

public | decode | character | anyelement, anyelement, character | normal

public | decode | character | anyelement, anyelement, character, anyelement, character | normal

public | decode | character | anyelement, anyelement, character, anyelement, character, anyelement, character | normal

public | decode | character | anyelement, anyelement, character, anyelement, character, anyelement, character, character | normal

public | decode | character | anyelement, anyelement, character, anyelement, character, character | normal

public | decode | character | anyelement, anyelement, character, character | normal

public | decode | date | anyelement, anyelement, date | normal

public | decode | date | anyelement, anyelement, date, anyelement, date | normal

public | decode | date | anyelement, anyelement, date, anyelement, date, anyelement, date | normal

public | decode | date | anyelement, anyelement, date, anyelement, date, anyelement, date, date | normal

public | decode | date | anyelement, anyelement, date, anyelement, date, date | normal

public | decode | date | anyelement, anyelement, date, date | normal

public | decode | integer | anyelement, anyelement, integer | normal

public | decode | integer | anyelement, anyelement, integer, anyelement, integer | normal

public | decode | integer | anyelement, anyelement, integer, anyelement, integer, anyelement, integer | normal

public | decode | integer | anyelement, anyelement, integer, anyelement, integer, anyelement, integer, integer | normal

public | decode | integer | anyelement, anyelement, integer, anyelement, integer, integer | normal

public | decode | integer | anyelement, anyelement, integer, integer | normal

public | decode | numeric | anyelement, anyelement, numeric | normal

public | decode | numeric | anyelement, anyelement, numeric, anyelement, numeric | normal

public | decode | numeric | anyelement, anyelement, numeric, anyelement, numeric, anyelement, numeric | normal

public | decode | numeric | anyelement, anyelement, numeric, anyelement, numeric, anyelement, numeric, numeric | normal

public | decode | numeric | anyelement, anyelement, numeric, anyelement, numeric, numeric | normal

public | decode | numeric | anyelement, anyelement, numeric, numeric | normal

public | decode | text | anyelement, anyelement, text | normal

public | decode | text | anyelement, anyelement, text, anyelement, text | normal

public | decode | text | anyelement, anyelement, text, anyelement, text, anyelement, text | normal

public | decode | text | anyelement, anyelement, text, anyelement, text, anyelement, text, text | normal

public | decode | text | anyelement, anyelement, text, anyelement, text, text | normal

public | decode | text | anyelement, anyelement, text, text | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone, anyelement, timestamp without time zone | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone, anyelement, timestamp without time zone, anyelement, timestamp without time zone | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone, anyelement, timestamp without time zone, anyelement, timestamp without time zone, timestamp without time zone | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone, anyelement, timestamp without time zone, timestamp without time zone | normal

public | decode | timestamp without time zone | anyelement, anyelement, timestamp without time zone, timestamp without time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone, anyelement, timestamp with time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone, anyelement, timestamp with time zone, anyelement, timestamp with time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone, anyelement, timestamp with time zone, anyelement, timestamp with time zone, timestamp with time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone, anyelement, timestamp with time zone, timestamp with time zone | normal

public | decode | timestamp with time zone | anyelement, anyelement, timestamp with time zone, timestamp with time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone, anyelement, time without time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone, anyelement, time without time zone, anyelement, time without time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone, anyelement, time without time zone, anyelement, time without time zone, time without time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone, anyelement, time without time zone, time without time zone | normal

public | decode | time without time zone | anyelement, anyelement, time without time zone, time without time zone | normal

public | dump | character varying | "any" | normal

public | dump | character varying | "any", integer | normal

public | dump | character varying | text | normal

public | dump | character varying | text, integer | normal

public | nanvl | double precision | double precision, character varying | normal

public | nanvl | double precision | double precision, double precision | normal

public | nanvl | numeric | numeric, character varying | normal

public | nanvl | numeric | numeric, numeric | normal

public | nanvl | real | real, character varying | normal

public | nanvl | real | real, real | normal

public | nvarchar2 | nvarchar2 | nvarchar2, integer, boolean | normal

public | nvarchar2_transform | internal | internal | normal

public | nvarchar2in | nvarchar2 | cstring, oid, integer | normal

public | nvarchar2out | cstring | nvarchar2 | normal

public | nvarchar2recv | nvarchar2 | internal, oid, integer | normal

public | nvarchar2send | bytea | nvarchar2 | normal

public | nvarchar2typmodin | integer | cstring[] | normal

public | nvarchar2typmodout | cstring | integer | normal

public | nvl | anyelement | anyelement, anyelement | normal

public | nvl2 | anyelement | anyelement, anyelement, anyelement | normal

public | sinh | double precision | double precision | normal

public | tanh | double precision | double precision | normal

public | to_multi_byte | text | str text | normal

public | to_single_byte | text | str text | normal

public | varchar2 | varchar2 | varchar2, integer, boolean | normal

public | varchar2_transform | internal | internal | normal

public | varchar2in | varchar2 | cstring, oid, integer | normal

public | varchar2out | cstring | varchar2 | normal

public | varchar2recv | varchar2 | internal, oid, integer | normal

public | varchar2send | bytea | varchar2 | normal

public | varchar2typmodin | integer | cstring[] | normal

public | varchar2typmodout | cstring | integer | normal

(88 rows)

atlas=# \df oracle.*

List of functions

Schema | Name | Result data type | Argument data types | Type

--------+-----------------------+-----------------------------+----------------------------------------------------+--------

oracle | add_days_to_timestamp | timestamp without time zone | oracle.date, bigint | normal

oracle | add_days_to_timestamp | timestamp without time zone | oracle.date, integer | normal

oracle | add_days_to_timestamp | timestamp without time zone | oracle.date, numeric | normal

oracle | add_days_to_timestamp | timestamp without time zone | oracle.date, smallint | normal

oracle | add_months | timestamp without time zone | timestamp with time zone, integer | normal

oracle | btrim | text | character | normal

oracle | btrim | text | character, character | normal

oracle | btrim | text | character, nvarchar2 | normal

oracle | btrim | text | character, text | normal

oracle | btrim | text | character, varchar2 | normal

oracle | btrim | text | nvarchar2 | normal

oracle | btrim | text | nvarchar2, character | normal

oracle | btrim | text | nvarchar2, nvarchar2 | normal

oracle | btrim | text | nvarchar2, text | normal

oracle | btrim | text | nvarchar2, varchar2 | normal

oracle | btrim | text | text | normal

oracle | btrim | text | text, character | normal

oracle | btrim | text | text, nvarchar2 | normal

oracle | btrim | text | text, text | normal

oracle | btrim | text | text, varchar2 | normal

oracle | btrim | text | varchar2 | normal

oracle | btrim | text | varchar2, character | normal

oracle | btrim | text | varchar2, nvarchar2 | normal

oracle | btrim | text | varchar2, text | normal

oracle | btrim | text | varchar2, varchar2 | normal

oracle | dbtimezone | text | | normal

oracle | get_full_version_num | text | | normal

oracle | get_major_version | text | | normal

oracle | get_major_version_num | text | | normal

oracle | get_platform | text | | normal

oracle | get_status | text | | normal

oracle | last_day | timestamp without time zone | timestamp with time zone | normal

oracle | length | integer | character | normal

oracle | lpad | text | bigint, integer, integer | normal

oracle | lpad | text | character, integer | normal

oracle | lpad | text | character, integer, character | normal

oracle | lpad | text | character, integer, nvarchar2 | normal

oracle | lpad | text | character, integer, text | normal

oracle | lpad | text | character, integer, varchar2 | normal

oracle | lpad | text | integer, integer, integer | normal

oracle | lpad | text | numeric, integer, integer | normal

oracle | lpad | text | nvarchar2, integer | normal

oracle | lpad | text | nvarchar2, integer, character | normal

oracle | lpad | text | nvarchar2, integer, nvarchar2 | normal

oracle | lpad | text | nvarchar2, integer, text | normal

oracle | lpad | text | nvarchar2, integer, varchar2 | normal

oracle | lpad | text | smallint, integer, integer | normal

oracle | lpad | text | text, integer | normal

oracle | lpad | text | text, integer, character | normal

oracle | lpad | text | text, integer, nvarchar2 | normal

oracle | lpad | text | text, integer, text | normal

oracle | lpad | text | text, integer, varchar2 | normal

oracle | lpad | text | varchar2, integer | normal

oracle | lpad | text | varchar2, integer, character | normal

oracle | lpad | text | varchar2, integer, nvarchar2 | normal

oracle | lpad | text | varchar2, integer, text | normal

oracle | lpad | text | varchar2, integer, varchar2 | normal

oracle | ltrim | text | character | normal

oracle | ltrim | text | character, character | normal

oracle | ltrim | text | character, nvarchar2 | normal

oracle | ltrim | text | character, text | normal

oracle | ltrim | text | character, varchar2 | normal

oracle | ltrim | text | nvarchar2 | normal

oracle | ltrim | text | nvarchar2, character | normal

oracle | ltrim | text | nvarchar2, nvarchar2 | normal

oracle | ltrim | text | nvarchar2, text | normal

oracle | ltrim | text | nvarchar2, varchar2 | normal

oracle | ltrim | text | text | normal

oracle | ltrim | text | text, character | normal

oracle | ltrim | text | text, nvarchar2 | normal

oracle | ltrim | text | text, text | normal

oracle | ltrim | text | text, varchar2 | normal

oracle | ltrim | text | varchar2 | normal

oracle | ltrim | text | varchar2, character | normal

oracle | ltrim | text | varchar2, nvarchar2 | normal

oracle | ltrim | text | varchar2, text | normal

oracle | ltrim | text | varchar2, varchar2 | normal

oracle | months_between | numeric | timestamp with time zone, timestamp with time zone | normal

oracle | next_day | timestamp without time zone | timestamp with time zone, integer | normal

oracle | next_day | timestamp without time zone | timestamp with time zone, text | normal

oracle | numtodsinterval | interval | double precision, text | normal

oracle | nvl | bigint | bigint, integer | normal

oracle | nvl | numeric | numeric, integer | normal

oracle | round | numeric | double precision, integer | normal

oracle | round | numeric | real, integer | normal

oracle | rpad | text | character, integer | normal

oracle | rpad | text | character, integer, character | normal

oracle | rpad | text | character, integer, nvarchar2 | normal

oracle | rpad | text | character, integer, text | normal

oracle | rpad | text | character, integer, varchar2 | normal

oracle | rpad | text | nvarchar2, integer | normal

oracle | rpad | text | nvarchar2, integer, character | normal

oracle | rpad | text | nvarchar2, integer, nvarchar2 | normal

oracle | rpad | text | nvarchar2, integer, text | normal

oracle | rpad | text | nvarchar2, integer, varchar2 | normal

oracle | rpad | text | text, integer | normal

oracle | rpad | text | text, integer, character | normal

oracle | rpad | text | text, integer, nvarchar2 | normal

oracle | rpad | text | text, integer, text | normal

oracle | rpad | text | text, integer, varchar2 | normal

oracle | rpad | text | varchar2, integer | normal

oracle | rpad | text | varchar2, integer, character | normal

oracle | rpad | text | varchar2, integer, nvarchar2 | normal

oracle | rpad | text | varchar2, integer, text | normal

oracle | rpad | text | varchar2, integer, varchar2 | normal

oracle | rtrim | text | character | normal

oracle | rtrim | text | character, character | normal

oracle | rtrim | text | character, nvarchar2 | normal

oracle | rtrim | text | character, text | normal

oracle | rtrim | text | character, varchar2 | normal

oracle | rtrim | text | nvarchar2 | normal

oracle | rtrim | text | nvarchar2, character | normal

oracle | rtrim | text | nvarchar2, nvarchar2 | normal

oracle | rtrim | text | nvarchar2, text | normal

oracle | rtrim | text | nvarchar2, varchar2 | normal

oracle | rtrim | text | text | normal

oracle | rtrim | text | text, character | normal

oracle | rtrim | text | text, nvarchar2 | normal

oracle | rtrim | text | text, text | normal

oracle | rtrim | text | text, varchar2 | normal

oracle | rtrim | text | varchar2 | normal

oracle | rtrim | text | varchar2, character | normal

oracle | rtrim | text | varchar2, nvarchar2 | normal

oracle | rtrim | text | varchar2, text | normal

oracle | rtrim | text | varchar2, varchar2 | normal

oracle | sessiontimezone | text | | normal

oracle | substr | text | character varying, numeric | normal

oracle | substr | text | character varying, numeric, numeric | normal

oracle | substr | text | numeric, numeric | normal

oracle | substr | text | numeric, numeric, numeric | normal

oracle | substr | text | str text, start integer | normal

oracle | substr | text | str text, start integer, len integer | normal

oracle | subtract | timestamp without time zone | oracle.date, bigint | normal

oracle | subtract | timestamp without time zone | oracle.date, integer | normal

oracle | subtract | timestamp without time zone | oracle.date, numeric | normal

oracle | subtract | double precision | oracle.date, oracle.date | normal

oracle | subtract | timestamp without time zone | oracle.date, smallint | normal

oracle | sysdate | oracle.date | | normal

oracle | to_char | text | timestamp without time zone | normal

oracle | to_date | oracle.date | text | normal

oracle | to_date | oracle.date | text, text | normal

oracle | trunc | numeric | double precision, integer | normal

oracle | trunc | numeric | real, integer | normal

(143 rows)

## Oracle兼容 系统表 视图:

atlas=# \dv oracle.*

List of relations

Schema | Name | Type | Owner

--------+---------------------------+------+--------

oracle | dba_segments | view | appusr

oracle | product_component_version | view | appusr

oracle | user_cons_columns | view | appusr

oracle | user_constraints | view | appusr

oracle | user_ind_columns | view | appusr

oracle | user_objects | view | appusr

oracle | user_procedures | view | appusr

oracle | user_source | view | appusr

oracle | user_tab_columns | view | appusr

oracle | user_tables | view | appusr

oracle | user_views | view | appusr

(11 rows)

## Oracle兼容 dual表,在PG里用了一个视图来实现。

atlas=# \dv

List of relations

Schema | Name | Type | Owner

--------+------+------+--------

public | dual | view | appusr

(1 row)

atlas=# \d+ dual

View "public.dual"

Column | Type | Collation | Nullable | Default | Storage | Description

--------+-------------------+-----------+----------+---------+----------+-------------

dummy | character varying | | | | extended |

View definition:

SELECT 'X'::character varying AS dummy;

atlas=# select * from dual;

dummy

-------

X

(1 row)

atlas=# select 1 from dual;

?column?

----------

1

(1 row)

四、实现过程

1.添加自定义类型

orafce添加了varchar2 和nvarchar2两种类型,varchar2的实现过程如下:

## 自定义类型

/* CREATE TYPE */

CREATE TYPE varchar2 (

internallength = VARIABLE,

input = varchar2in,

output = varchar2out,

receive = varchar2recv,

send = varchar2send,

category = 'S',

typmod_in = varchar2typmodin,

typmod_out = varchar2typmodout,

collatable = true

);

## 创建转换函数

/* CREATE CAST */

CREATE CAST (varchar2 AS text)

WITHOUT FUNCTION

AS IMPLICIT;

CREATE CAST (text AS varchar2)

WITHOUT FUNCTION

AS IMPLICIT;

CREATE CAST (varchar2 AS char)

WITHOUT FUNCTION

AS IMPLICIT;

...

## 其他varchar2的操作函数:

## 此函数使用pg内核提供的C函数,部分函数会采用orafce动态库自定义的C函数

CREATE OR REPLACE FUNCTION pg_catalog.substrb(varchar2, integer, integer) RETURNS varchar2

AS 'bytea_substr'

LANGUAGE internal

STRICT IMMUTABLE;

...

2.对date类型增加oracle相关的特性

orafce为postgres的date类型做了增强,尽量减少oracle迁移至postgres的代码修改量

## 创建oracle对应的date类型:

CREATE DOMAIN oracle.date AS timestamp(0);

## 对oracle.date类型增强操作符支持

CREATE OPERATOR oracle.+ (

LEFTARG = oracle.date,

RIGHTARG = INTEGER,

PROCEDURE = oracle.add_days_to_timestamp

);

CREATE OPERATOR oracle.- (

LEFTARG = oracle.date,

RIGHTARG = INTEGER,

PROCEDURE = oracle.subtract

);

CREATE OPERATOR oracle.+ (

LEFTARG = oracle.date,

RIGHTARG = bigint,

PROCEDURE = oracle.add_days_to_timestamp

);

CREATE OPERATOR oracle.- (

LEFTARG = oracle.date,

RIGHTARG = bigint,

PROCEDURE = oracle.subtract

);

CREATE OPERATOR oracle.+ (

LEFTARG = oracle.date,

RIGHTARG = smallint,

PROCEDURE = oracle.add_days_to_timestamp

);

CREATE OPERATOR oracle.- (

LEFTARG = oracle.date,

RIGHTARG = smallint,

PROCEDURE = oracle.subtract

);

CREATE OPERATOR oracle.+ (

LEFTARG = oracle.date,

RIGHTARG = numeric,

PROCEDURE = oracle.add_days_to_timestamp

);

CREATE OPERATOR oracle.- (

LEFTARG = oracle.date,

RIGHTARG = numeric,

PROCEDURE = oracle.subtract

);

CREATE OPERATOR oracle.- (

LEFTARG = oracle.date,

RIGHTARG = oracle.date,

PROCEDURE = oracle.subtract

);

## 操作符实现(以 date + int 为例):

CREATE OR REPLACE FUNCTION oracle.add_days_to_timestamp(oracle.date,integer)

RETURNS timestamp AS $$

SELECT $1 + interval '1 day' * $2;

$$ LANGUAGE SQL IMMUTABLE;

...

3.用视图代替oracle的dual虚表

在oracle中,查询系统变量或者函数返回值时,经常会用到虚表dual。

例如:

select 1 from dual

但是在postgres中,对应的sql为:

select 1

orafce为了兼容oracle的dual用法,添加了一个名为dual的视图,并授权给public:

CREATE VIEW public.dual AS SELECT 'X'::varchar AS dummy;

REVOKE ALL ON public.dual FROM PUBLIC;

GRANT SELECT, REFERENCES ON public.dual TO PUBLIC;

4.oracle的sysdate实现

在oracle中,提供了部分系统变量,可以通过select获取其中值。例如oracle的sysdate

## Oracle 数据库使用

select sysdate from dual

在postgres中,没有sysdate,为了实现此功能,提供一个oracle.sysdate()函数。实现思路:

CREATE FUNCTION oracle.sysdate()

RETURNS oracle.date

AS 'MODULE_PATHNAME','orafce_sysdate'

LANGUAGE C STABLE STRICT;

COMMENT ON FUNCTION oracle.sysdate() IS 'Ruturns statement timestamp at server time zone';

注意,这个函数是C语言函数,由动态库实现过程,代码如下:

/* src:datefce.c */

/********************************************************************

*

* ora_sysdate - sysdate

*

* Syntax:

*

* timestamp sysdate()

*

* Purpose:

*

* Returns statement_timestamp in server time zone

* Note - server time zone doesn't exists on PostgreSQL - emulated

* by orafce_timezone

*

********************************************************************/

Datum

orafce_sysdate(PG_FUNCTION_ARGS)

{

Datum sysdate;

Datum sysdate_scaled;

sysdate = DirectFunctionCall2(timestamptz_zone,

CStringGetTextDatum(orafce_timezone),

TimestampTzGetDatum(GetCurrentStatementStartTimestamp()));

/* necessary to cast to timestamp(0) to emulate Oracle's date */

sysdate_scaled = DirectFunctionCall2(timestamp_scale,

sysdate,

Int32GetDatum(0));

PG_RETURN_DATUM(sysdate_scaled);

}

postgres+orafce的用法:

select oracle.sysdate() from dual

5.语法解析

整个orafce都没有实现hook的切入。使用extension的用意,估计是为了初始化和挂载so文件。

因为在“create extension orafce”,就会创建所有的自定义类型、函数、字典表等对象。

但是在orafce的源码中,却发现了词法分析和语法分析两个文件:

3b8e1c47fecf?tdsourcetag=s_pcqq_aiomsg

image.png

经过代码分析,语法分析时作为函数调用的,对应的函数为 plvlex.tokens。

其实现过程:

## 创建函数plvlex.tokens,为C语言函数

CREATE SCHEMA plvlex;

CREATE FUNCTION plvlex.tokens(IN str text, IN skip_spaces bool, IN qualified_names bool,

OUT pos int, OUT token text, OUT code int, OUT class text, OUT separator text, OUT mod text)

RETURNS SETOF RECORD

AS 'MODULE_PATHNAME','plvlex_tokens'

LANGUAGE C IMMUTABLE STRICT;

COMMENT ON FUNCTION plvlex.tokens(text,bool,bool) IS 'Parse SQL string';

## C语言实现代码

Datum

plvlex_tokens(PG_FUNCTION_ARGS)

{

#ifdef _MSC_VER

ereport(ERROR,

(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

errmsg("plvlex.tokens is not available in the built")));

PG_RETURN_VOID();

#else

FuncCallContext *funcctx;

TupleDesc tupdesc;

TupleTableSlot *slot;

AttInMetadata *attinmeta;

tokensFctx *fctx;

if (SRF_IS_FIRSTCALL ())

{

MemoryContext oldcontext;

List *lexems;

text *src = PG_GETARG_TEXT_P(0);

bool skip_spaces = PG_GETARG_BOOL(1);

bool qnames = PG_GETARG_BOOL(2);

/* 此处调用了语法分析器 */

orafce_sql_scanner_init(CSTRING(src));

if (orafce_sql_yyparse(&lexems) != 0)

orafce_sql_yyerror(NULL, "bogus input");

orafce_sql_scanner_finish();

funcctx = SRF_FIRSTCALL_INIT ();

oldcontext = MemoryContextSwitchTo (funcctx->multi_call_memory_ctx);

fctx = (tokensFctx*) palloc (sizeof (tokensFctx));

funcctx->user_fctx = (void *)fctx;

fctx->nodes = filterList(lexems, skip_spaces, qnames);

fctx->nnodes = list_length(fctx->nodes);

fctx->cnode = 0;

fctx->values = (char **) palloc (6 * sizeof (char *));

fctx->values [0] = (char*) palloc (16 * sizeof (char));

fctx->values [1] = (char*) palloc (1024 * sizeof (char));

fctx->values [2] = (char*) palloc (16 * sizeof (char));

fctx->values [3] = (char*) palloc (16 * sizeof (char));

fctx->values [4] = (char*) palloc (255 * sizeof (char));

fctx->values [5] = (char*) palloc (255 * sizeof (char));

tupdesc = CreateTemplateTupleDesc (6 , false);

TupleDescInitEntry (tupdesc, 1, "start_pos", INT4OID, -1, 0);

TupleDescInitEntry (tupdesc, 2, "token", TEXTOID, -1, 0);

TupleDescInitEntry (tupdesc, 3, "keycode", INT4OID, -1, 0);

TupleDescInitEntry (tupdesc, 4, "class", TEXTOID, -1, 0);

TupleDescInitEntry (tupdesc, 5, "separator", TEXTOID, -1, 0);

TupleDescInitEntry (tupdesc, 6, "mod", TEXTOID, -1, 0);

slot = TupleDescGetSlot (tupdesc);

funcctx -> slot = slot;

attinmeta = TupleDescGetAttInMetadata (tupdesc);

funcctx -> attinmeta = attinmeta;

MemoryContextSwitchTo (oldcontext);

}

funcctx = SRF_PERCALL_SETUP ();

fctx = (tokensFctx*) funcctx->user_fctx;

while (fctx->cnode < fctx->nnodes)

{

char **values;

Datum result;

HeapTuple tuple;

char *back_vals[6];

orafce_lexnode *nd = (orafce_lexnode*) list_nth(fctx->nodes, fctx->cnode++);

values = fctx->values;

back_vals[2] = values[2];

back_vals[4] = values[4];

back_vals[5] = values[5];

snprintf(values[0], 16, "%d", nd->lloc);

snprintf(values[1], 10000, "%s", SF(nd->str));

snprintf(values[2], 16, "%d", nd->keycode);

snprintf(values[3], 16, "%s", nd->classname);

snprintf(values[4], 255, "%s", SF(nd->sep));

snprintf(values[5], 48, "%s", SF(nd->modificator));

if (nd->keycode == -1)

values[2] = NULL;

if (!nd->sep)

values[4] = NULL;

if (!nd->modificator)

values[5] = NULL;

tuple = BuildTupleFromCStrings (funcctx -> attinmeta,

fctx -> values);

result = TupleGetDatum (funcctx -> slot, tuple);

values[2] = back_vals[2];

values[4] = back_vals[4];

values[5] = back_vals[5];

SRF_RETURN_NEXT (funcctx, result);

}

SRF_RETURN_DONE (funcctx);

#endif

}

orafce的函数plvlex.tokens的用法:

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

pos | token | code | class | separator | mod

-----+--------+------+---------+-----------+------

0 | select | 597 | KEYWORD | |

7 | * | 42 | OTHERS | | self

9 | from | 417 | KEYWORD | |

14 | a.b.c | | IDENT | |

20 | join | 464 | KEYWORD | |

25 | d | | IDENT | |

27 | on | 521 | KEYWORD | |

30 | x | | IDENT | |

31 | = | 61 | OTHERS | | self

32 | y | | IDENT | |

(10 rows)

对plvlex.tokens的官方说明:

Package PLVlex

This package isn’t compatible with original PLVlex.

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.

总结

orafce的实现都是基于函数、视图来实现的。所以如果要做语法兼容,orafce的做法是无法实现的。因为postgres的语法分析在调用视图和函数之前。必须要在语法分析之前切入hook才能使用extension的实现做语法兼容性。未来postgres也许会提供相应的hook切入点,orafce实现更加完美的oracle兼容性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/566605.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

labview linux 内核 不匹配,Linux CentOS7(或Ubuntu)中安装NI-VISA后一打开范例Simple Serial.vi就闪退,LabVIEW就崩溃。...

Linux CentOS7(或Ubuntu)中安装NI-VISA后一打开范例Simple Serial.vi就闪退&#xff0c;LabVIEW就崩溃。我安装了LabVIEW pro 2017 for Linux(另外也试了2016版的都是一样的效果)&#xff0c;VISA也试了4.1.0、4.4.0、5.1.1、15.0.0、15.5.0、16.0.0、17.0.0版本都试过了&#…

kali linux子远程桌面,适用于kali linux的远程桌面开启方法(从windows xp 远程登录到kali linux )...

为了解决Windows远程桌面访问Ubuntu 12.04 之一 中提到的VNC远程桌面的缺点(见http://www.linuxidc.com/Linux/2012-07/64801.htm)&#xff0c;我们采用第二种方法XRDP&#xff0c;该方法支持多用户登录并远程桌面。1、首先参考Windows远程桌面访问Ubuntu 12.04 之安装VNC中提到…

linux装redis环境变量,linux 怎样安装redis

人到中年有点甜获取Redis1、通过官网http://redis.io/获取稳定版源码包下载地址&#xff1b;2、通过wget http://download.redis.io/releases/redis-3.0.2.tar.gz下载 源码包&#xff1b;2编译安装Redis1、解压源码安装包&#xff0c;通过tar -xvf redis-3.0.2.tar.gz解压源码&…

word2016能识别linux换行符,word文章中的换行符如何批量替换为回车符

word文件中有换行符很正常&#xff0c;但是想要将换行符全部替换为回车符&#xff0c;该怎么替换?以下是学习啦小编为您带来的关于word文章中的换行符批量替换为回车符&#xff0c;希望对您有所帮助。word文章中的换行符批量替换为回车符1、在打开的word中&#xff0c;依次点击…

linux禁用防火墙配置,CentOS Linux防火墙配置及关闭

最近在CentOS Linux下安装配置 Oracle 数据库的时候&#xff0c;总显示因为网络端口而导致的EM安装失败&#xff0c;遂打算先关闭一下防火墙。偶然看到防火墙的配置操作说明&#xff0c;感觉不错。执行”setup”命令启动文字模式配置实用程序,在”选择一种工具”中选择”防火墙…

C语言CASE语句嵌套,C语言中switch case语句的嵌套

给一个含有嵌套的switch case的一段完整代码&#xff1a;#include int main(){int n1;int m2;switch(n){case 1:m;case 2:n;case 3:switch(n){case 1:n;case 2:m;n;break;}case 4:m;break;default:break;}printf("%d %d",m,n);return 0;}代码看起来很简单&#xff0c…

linux dd 进度条,Progress 进度条 – DDProgressHUD

DDProgressHUDProgress 进度条&#xff0c;UIActivityIndicatorView 小菊花&#xff0c;弹窗&#xff0c;状态显示&#xff0c;高度自定义DDProgressHUD的介绍提供了四种类型的展示&#xff1a;显示无限旋转的加载图(比如小菊花&#xff0c;可以自定义)&#xff0c;显示文字信息…

Android动态图标包制作教程,安卓手机ico图标制作美化图文教程

如何让手机更加与众不同?今天我们就来学习如何利用出色的ico图标制作软件——Axialis IconWorkshop制作出美化手机屏幕的个性图标!如今&#xff0c;每个人都有属于自己的手机&#xff0c;每天使用手机聊QQ、刷微博、玩游戏&#xff0c;可以说手机已经是很多人生活中不可缺少的…

android progressbar 水平动画,Android ProgressBar 自定义样式(三),动画模式

果&#xff1a;和之前的一样&#xff0c;在布局文件中&#xff1a;android:id"id/progressBar3"android:layout_width"wrap_content"android:layout_height"wrap_content"android:indeterminate"false"android:indeterminateDrawable&…

android gridview行分割线,Android使用GridView实现表格分割线效果

使用gridview实现表格分割线效果&#xff0c;网格布局表格布局也是可以实现的。效果如下&#xff1a;1.主函数代码&#xff1a;package com.example.qd.douyinwu;import android.app.activity;import android.content.context;import android.os.bundle;import android.support…

android hook 实例,代码实例分析android中inline hook

以下内容通过1、实现目标注入程序&#xff0c;2、实现主程序&#xff0c;3、实现注入函数&#xff0c;4、thumb指令集实现等4个方面详细分析了android中inline hook的用法&#xff0c;以下是全部内容&#xff1a;最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍&#xf…

dax 筛选 包含某个字_筛选状态(ALL与REMOVEFILTERS)

这一章比较绕&#xff0c;但是帮助我们理清切片器的筛选状态以及主要函数对于公式筛选上下文的改变。1.切片器的筛选状态切片器的全选与全不选的状态的区别&#xff0c;我们可以看下图&#xff1a;全不选全选多个点击筛选逐个点击至全部结论初始状态&#xff0c;没有选择任何元…

山东鲁能轨道智能巡检机器人_温湿度传感器在轨道巡检机器人中的应用

▲地下综合管廊智慧管廊建设&#xff0c;是智慧城市在地下的一个缩影&#xff0c;有助于缓解“大城市病”&#xff0c;实现精细化和动态管理。与此同时&#xff0c;各种传感器技术也将被运用到地下综合管廊运维的每一环&#xff0c;这其中&#xff0c;地下管廊巡检机器人便是其…

android显示网络图片控件,Android控件之ImageView(二)

前言在上一篇文章中&#xff0c;我们讲解了如何加载本地图片&#xff0c;那么在实际项目中 ImageView 大多数使用场景是加载网络图片&#xff0c;网络图片其实就是存储在服务器上的文件&#xff0c;我们需要从服务器获取到文件的二进制输入流 Inpustream &#xff0c;然后将其转…

坯子库曲面推拉教程_一招曲面流动,搞定99%异形建模

曲面流动可以建什么模型&#xff1f;这样的▼这样的▼还有这样的▼那究竟如何使用曲面流动呢?本文告诉你!曲面流动是什么&#xff1f;曲面流动功能相当于Rhino(犀牛)中的“沿曲面流动”命令&#xff0c;可以使来源几何体群组或组件&#xff0c;根据基准平面为参照&#xff0c;…

android o 结构光流程,惊艳亮相!一分钟看懂OPPO Find X 3D结构光技术是什么鬼,太牛了...

法国时间6月19日&#xff0c;OPPO在巴黎卢浮宫正式举办未来旗舰Find X发布会。此次亮相的Find X新机&#xff0c;既有充满艺术感的3D玻璃机身设计&#xff0c;又有3D结构光、曲面全景屏、双轨潜望结构等多项黑科技。众多黑科技中&#xff0c;以3D结构光O-face最受数目。据悉&am…

jframe运行和预览大小不一样_同一款车型,为什么配的轮胎大小还会不一样?【内含福利】...

小编又来给大家送福利啦~阅读完文章之后 戳文章底部阅读原文 岁末巨献 国货好胎&#xff01;免费体验价值1999元国产轮胎&#xff01;相信有不少朋友&#xff0c;买车的时候一定会有类似的经历。选车、试驾的时候&#xff0c;看到试驾车配置相当漂亮&#xff0c;尤其搭配的轮圈…

java设计按月每天签到_活动攻略|新同学新签到,欢乐福利全都要!

12月03日【每日一题答案】— 枫叶书签答对问题即有机会获得金币、道具、积分&#xff0c;还有宠物好奇星噢~12月来了&#xff0c;和12月一起来的是我们的新同学——花轮&#xff01;谁不喜欢浪漫体贴的小少爷呢&#xff01;喵星星感觉自己爱消除【最受欢迎男性角色】的地位正岌…

bs cs架构区别_软件架构设计分层模型和构图思考

今天谈下架构设计中的分层思维和分层模型以及基于分层思维下的架构构图逻辑。架构思维概述对于架构思维本身仍然是类似系统思维&#xff0c;结构化思维&#xff0c;编程思维等诸多思维模式的一个合集。由于架构的核心作用是在业务现实世界和抽象的IT实现之间建立起一道桥梁&…

pin码计算器网页版_AP微积分Excel简便计算+网页工具指南

今年的AP考试既然是开卷&#xff0c;允许大家使用各种资源。今天一个学生提了一个不(zhe)错(mo)的(wo)想(de)法(shi)。于是给大家写了一个Excel的公式表格照例老规矩&#xff1a;点个”在看“再走呗先说明一下使用指南&#xff1a;文末有下载表格包含&#xff1a;(目前的功能&a…