diff --git a/CN/modules/ROOT/nav.adoc b/CN/modules/ROOT/nav.adoc index 02d78ad0..7ce1cf9f 100644 --- a/CN/modules/ROOT/nav.adoc +++ b/CN/modules/ROOT/nav.adoc @@ -19,6 +19,8 @@ *** xref:master/6.1.1.adoc[双parser] ** 兼容框架 *** xref:master/6.2.1.adoc[initdb过程] +** 兼容特性 +*** xref:master/6.3.1.adoc[like] * Oracle兼容功能列表 ** xref:master/7.1.adoc[1、框架设计] ** xref:master/7.2.adoc[2、GUC框架] diff --git a/CN/modules/ROOT/pages/master/6.3.1.adoc b/CN/modules/ROOT/pages/master/6.3.1.adoc new file mode 100644 index 00000000..4df8a918 --- /dev/null +++ b/CN/modules/ROOT/pages/master/6.3.1.adoc @@ -0,0 +1,44 @@ + +:sectnums: +:sectnumlevels: 5 + + += **功能概述** + +Oracle和IvorySQL中的 LIKE 语法是相同的,他们的区别在于表达式的类型,Oracle支持对数字、日期、字符串类型的列用 LIKE 关键字配合通配符来实现模糊查询。原生PostgreSQL只支持字符串类型,不支持日期、数字类型,IvorySQL通过扩展数据类型支持和操作符重载,实现了与 Oracle 兼容的 LIKE 操作符功能。 + +== 实现原理 + +PostgreSQL的字符串基本类型是text,所以 LIKE 是以text为基础,其他PostgreSQL类型隐式转换成text,不用创建opeartor就能自动转换;IvorySQL中oracle兼容的字符串类型是varchar2,因此创建一个varchar2的 LIKE 操作符,其他oracle的类型也通过隐式转换成varchar2实现不用创建操作符,也能使用 LIKE 操作符。 + +在之前实现oracle兼容数据类型时,IvorySQL做了integer,float8,float4 等一些数据类型到varchar2的隐式转换,没有直接到text的。因此实现这些兼容类型的 LIKE 操作符兼容,有两种方式。一种需要针对每个类型添加一个 LIKE 操作符,另一种是做一个基本的varchar2的 LIKE 操作符。在第二种实现方式中,IvorySQL针对float8,integer,number等已经做了向varchar2类型的隐式转换,这些数据类型可以和varchar2用同一个操作符,这样在创建操作符的时候只需要创建varchar2类型的 LIKE 操作符就可以。 + +=== 类型转换 + +可以通过以下SQL语句查看已经存在的类型隐式转换 +``` +-- 查询已存在的隐式转换路径(9503为varchar2的OID) +SELECT t1.typname AS source_type, t2.typname AS target_type +FROM pg_cast C +JOIN pg_type t1 ON C.castsource = t1.OID +JOIN pg_type t2 ON C.casttarget = t2.OID +WHERE C.casttarget = 9503; +``` +经过查看可得,需要进行兼容的类型全部都在该表中做了隐式转换,所以可以直接将这些类型转换为text类型然后进行模糊查询。 + +=== 核心函数实现 +```sql +CREATE OR REPLACE FUNCTION sys.varchar2like(varchar2, varchar2) +RETURNS bool AS $$ +SELECT $1::text LIKE $2::text; +$$ LANGUAGE SQL IMMUTABLE STRICT; + +CREATE OPERATOR ~~ ( + PROCEDURE = sys.varchar2like, + LEFTARG = varchar2, + RIGHTARG = varchar2 +); +``` +第一段代码定义了一个名为sys.varchar2like的函数,它接收两个varchar2类型的参数,通过将它们转换为PostgreSQL原生的text类型后执行标准的LIKE模式匹配,最终返回布尔值表示是否匹配。 +第二段代码创建了一个名为~~的操作符,它将使用前面定义的varchar2like函数作为实现,并指定该操作符左右两边的参数都必须是varchar2类型。 +这样就在IvorySQL中建立了一个与Oracle兼容的LIKE操作符,当用户使用~~操作符时,实际上是通过类型转换后调用PostgreSQL原生的LIKE功能来完成模式匹配,从而实现了Oracle的LIKE语义兼容。 \ No newline at end of file diff --git a/EN/modules/ROOT/nav.adoc b/EN/modules/ROOT/nav.adoc index 52136863..5cef59f0 100644 --- a/EN/modules/ROOT/nav.adoc +++ b/EN/modules/ROOT/nav.adoc @@ -19,6 +19,8 @@ *** xref:master/6.1.1.adoc[Dual Parser] ** Compatibility Framework *** xref:master/6.2.1.adoc[initdb Process] +** Compatibility Features +*** xref:master/6.3.1.adoc[like] * List of Oracle compatible features ** xref:master/7.1.adoc[1、Ivorysql frame design] ** xref:master/7.2.adoc[2、GUC Framework] diff --git a/EN/modules/ROOT/pages/master/6.3.1.adoc b/EN/modules/ROOT/pages/master/6.3.1.adoc new file mode 100644 index 00000000..05934ffb --- /dev/null +++ b/EN/modules/ROOT/pages/master/6.3.1.adoc @@ -0,0 +1,54 @@ + +:sectnums: +:sectnumlevels: 5 + + += **Functional Overview** + +The LIKE syntax in Oracle and IvorySQL is identical. Their difference lies in the expression types: Oracle supports using the LIKE keyword with wildcards for fuzzy queries on columns of numeric, date, and string types. Native PostgreSQL only supports string types, not date or numeric types. IvorySQL achieves Oracle-compatible LIKE operator functionality by extending data type support and operator overloading. + +== Implementation Principle + +In PostgreSQL, the fundamental string type is text, so LIKE is text-based. Other PostgreSQL types implicitly convert to text, enabling automatic conversion without creating operators. In IvorySQL, the Oracle-compatible string type is varchar2. Therefore, a LIKE operator for varchar2 is created, and other Oracle types also utilize the LIKE operator by implicitly converting to varchar2 without requiring additional operator creation. + +In the previous implementation of Oracle-compatible data types, IvorySQL established implicit conversions from certain data types (such as integer, float8, float4) to varchar2, but not directly to text. + +To achieve LIKE operator compatibility for these types, there are two approaches: + +1、Add a separate LIKE operator for each individual type. + +2、Implement a base LIKE operator for varchar2. + +In the second approach, since IvorySQL already supports implicit conversions from float8, integer, number, etc., to varchar2, these data types can share the same operator. Thus, only a single LIKE operator for varchar2 needs to be created. + +=== Type Conversion + +You can use the following SQL statement to check existing implicit type conversions. +``` +-- Check existing implicit conversion paths (where 9503 is the OID of varchar2) +SELECT t1.typname AS source_type, t2.typname AS target_type +FROM pg_cast C +JOIN pg_type t1 ON C.castsource = t1.OID +JOIN pg_type t2 ON C.casttarget = t2.OID +WHERE C.casttarget = 9503; +``` +After reviewing, it can be observed that all the types requiring compatibility have implicit conversions defined in this table. Therefore, these types can be directly converted to the text type for fuzzy query operations. + +=== Core Function Implementation +```sql +CREATE OR REPLACE FUNCTION sys.varchar2like(varchar2, varchar2) +RETURNS bool AS $$ +SELECT $1::text LIKE $2::text; +$$ LANGUAGE SQL IMMUTABLE STRICT; + +CREATE OPERATOR ~~ ( + PROCEDURE = sys.varchar2like, + LEFTARG = varchar2, + RIGHTARG = varchar2 +); +``` +The first code segment defines a function named sys.varchar2like, which accepts two parameters of type varchar2. By converting them to PostgreSQL's native text type, it performs standard LIKE pattern matching and ultimately returns a boolean value indicating whether the match is successful. + +The second code segment creates an operator named ~~, which uses the previously defined varchar2like function as its implementation. It specifies that both the left and right operands of this operator must be of type varchar2. + +This establishes an Oracle-compatible LIKE operator in IvorySQL. When users employ the ~~ operator, it essentially invokes PostgreSQL's native LIKE functionality after type conversion, thereby achieving semantic compatibility with Oracle's LIKE behavior. \ No newline at end of file