Skip to content

Commit cc486ca

Browse files
authored
Merge pull request IvorySQL#926 from yuanyl630/master
code refactor of oracle-compatibility feature rowid
2 parents 4336398 + 87d294c commit cc486ca

18 files changed

Lines changed: 111 additions & 87 deletions

File tree

contrib/ivorysql_ora/preload_ora_misc.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ insert into dual values('X');
66
GRANT SELECT ON dual TO PUBLIC;
77

88
--
9-
-- ROWID type
9+
-- Oracle-compatible ROWID and UROWID types
10+
-- ROWID: Composite type containing row object ID and row number
11+
-- UROWID: Universal ROWID, compatible with ROWID
1012
--
1113
CREATE TYPE sys.rowid AS(rowoid OID, rowno bigint);
1214
CREATE TYPE sys.urowid AS(rowoid OID, rowno bigint);

contrib/tablefunc/expected/ivy_tablefunc.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ SELECT avg(normal_rand)::int, count(*) FROM normal_rand(-1, 250, 0.2);
1414
ERROR: number of rows cannot be negative
1515
--
1616
-- crosstab()
17+
-- Use 'orarowid' instead of 'rowid' to avoid conflict with system column
1718
--
1819
CREATE TABLE ct(id int, rowclass text, orarowid text, attribute text, val text);
1920
\copy ct from 'data/ct.data'

contrib/tablefunc/sql/ivy_tablefunc.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ SELECT avg(normal_rand)::int, count(*) FROM normal_rand(-1, 250, 0.2);
1010

1111
--
1212
-- crosstab()
13+
-- Use 'orarowid' instead of 'rowid' to avoid conflict with system column
1314
--
1415
CREATE TABLE ct(id int, rowclass text, orarowid text, attribute text, val text);
1516
\copy ct from 'data/ct.data'

src/backend/access/transam/xlog.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5372,8 +5372,6 @@ BootStrapXLOG(uint32 data_checksum_version)
53725372
/* save database compatible level value */
53735373
ControlFile->dbmode = bootstrap_database_mode;
53745374
ControlFile->casemode = identifier_case_switch;
5375-
5376-
53775375

53785376
/* some additional ControlFile fields are set in WriteControlFile() */
53795377
WriteControlFile();
@@ -5571,7 +5569,7 @@ CleanupAfterArchiveRecovery(TimeLineID EndOfLogTLI, XLogRecPtr EndOfLog,
55715569
}
55725570
}
55735571

5574-
/* IvorySQL: BEGIN - case sensitive indentify
5572+
/* IvorySQL: BEGIN - case-sensitive indentifier support
55755573
* Read database compatibility mode from pg_control file
55765574
*
55775575
*/
@@ -5588,7 +5586,7 @@ int GetDatabaseStyleFromControl(char* path)
55885586
else
55895587
configdir = make_absolute_path(getenv("PGDATA"));
55905588

5591-
sprintf(pathname,"%s/%s",configdir,XLOG_CONTROL_FILE);
5589+
snprintf(pathname, sizeof(pathname), "%s/%s", configdir, XLOG_CONTROL_FILE);
55925590

55935591
fd = open(pathname, O_RDONLY | PG_BINARY, 0);
55945592

@@ -5630,7 +5628,7 @@ int GetCaseSwitchModeFromControl(char* path)
56305628
else
56315629
configdir = make_absolute_path(getenv("PGDATA"));
56325630

5633-
sprintf(pathname,"%s/%s",configdir,XLOG_CONTROL_FILE);
5631+
snprintf(pathname, sizeof(pathname), "%s/%s", configdir, XLOG_CONTROL_FILE);
56345632

56355633
fd = open(pathname, O_RDONLY | PG_BINARY, 0);
56365634

@@ -5665,7 +5663,7 @@ void SetCaseGucOption(char* path)
56655663

56665664
dbstyle = GetDatabaseStyleFromControl(path);
56675665

5668-
//the pg mode does not need to set
5666+
/* PG mode leaves identifier_case_switch unchanged. */
56695667
if (DB_ORACLE == dbstyle)
56705668
{
56715669
int casemode;
@@ -5691,6 +5689,7 @@ void SetCaseGucOption(char* path)
56915689
(errmsg("Incorrect case conversion mode value \"%d\"", casemode)));
56925690
}
56935691
}
5692+
/* IvorySQL: END - case-sensitive identifier support */
56945693

56955694
/*
56965695
* Check to see if required parameters are set high enough on this server

src/backend/catalog/heap.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ static const FormData_pg_attribute a6 = {
228228
};
229229

230230
/*
231-
* Compatible Oracle ROWID pseudo column.
231+
* Oracle-compatible ROWID pseudo-column.
232+
* This system column provides a unique identifier for each row,
233+
* compatible with Oracle's ROWID functionality.
232234
*/
233235
static const FormData_pg_attribute a7 = {
234236
.attname = {"rowid"},

src/backend/catalog/namespace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4420,7 +4420,8 @@ preprocessNamespacePath(const char *searchPath, Oid roleid,
44204420
char *curname = (char *) lfirst(l);
44214421
Oid namespaceId;
44224422

4423-
if ((compatible_db == ORA_PARSER && enable_case_switch && identifier_case_switch != NORMAL) ? /* IvorySQL: case sensitive indentify */
4423+
if ((compatible_db == ORA_PARSER && enable_case_switch &&
4424+
identifier_case_switch != NORMAL) ? /* IvorySQL: case-sensitive indentifier support */
44244425
pg_strcasecmp(curname, "$user") == 0 : strcmp(curname, "$user") == 0)
44254426
{
44264427
/* $user --- substitute namespace matching user name, if any */
@@ -5433,4 +5434,3 @@ get_nodefvalargposition(HeapTuple proctup, int pronargs)
54335434
}
54345435
return nodefvalargposition;
54355436
}
5436-

src/backend/parser/parse_utilcmd.c

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
#include "utils/ruleutils.h"
6969
#include "utils/syscache.h"
7070
#include "utils/typcache.h"
71-
#include <math.h>
71+
#include <math.h>
7272
#include "utils/guc.h"
7373
#include "utils/ora_compatible.h"
7474

@@ -280,10 +280,12 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
280280
if (cxt.inhRelations)
281281
{
282282
ListCell *inher;
283+
283284
foreach(inher, cxt.inhRelations)
284285
{
285286
RangeVar *inh = lfirst_node(RangeVar, inher);
286287
Relation prel;
288+
287289
prel = table_openrv(inh, AccessShareLock);
288290
cxt.hasrowid = cxt.hasrowid || prel->rd_rel->relhasrowid;
289291
table_close(prel, NoLock);
@@ -302,7 +304,8 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
302304
{
303305
case T_ColumnDef:
304306
{
305-
ColumnDef *col = (ColumnDef *) element;
307+
ColumnDef *col = (ColumnDef *) element;
308+
306309
if (compatible_db == ORA_PARSER && strcmp(col->colname, "rowid") == 0)
307310
elog(ERROR, "column name \"%s\" conflicts with a system column name", col->colname);
308311
else
@@ -331,13 +334,14 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
331334
*/
332335
foreach(elements, cxt.columns)
333336
{
334-
ColumnDef *element = lfirst(elements);
335-
if(element->identity == ATTRIBUTE_IDENTITY_DEFAULT_ON_NULL ||
336-
element->identity == ATTRIBUTE_ORA_IDENTITY_ALWAYS ||
337-
element->identity == ATTRIBUTE_ORA_IDENTITY_BY_DEFAULT)
337+
ColumnDef *element = lfirst(elements);
338+
339+
if (element->identity == ATTRIBUTE_IDENTITY_DEFAULT_ON_NULL ||
340+
element->identity == ATTRIBUTE_ORA_IDENTITY_ALWAYS ||
341+
element->identity == ATTRIBUTE_ORA_IDENTITY_BY_DEFAULT)
338342
ora_identity_cnt++;
339343
}
340-
if(ora_identity_cnt > 1)
344+
if (ora_identity_cnt > 1)
341345
elog(ERROR, "table can have only one identity column");
342346

343347
if (like_found && cxt.hasrowid)
@@ -348,7 +352,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
348352

349353
if (cxt.hasrowid)
350354
{
351-
Oid snamespaceid;
355+
Oid snamespaceid;
352356
char *snamespace;
353357
char *sname;
354358

@@ -368,47 +372,48 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
368372
false);
369373

370374
/*
371-
* Build a CREATE SEQUENCE command to create the sequence object,
372-
* and add it to the list of things to be done before this CREATE/ALTER TABLE
375+
* Build a CREATE SEQUENCE command to create the sequence object, and
376+
* add it to the list of things to be done before this CREATE/ALTER
377+
* TABLE
373378
*/
374379
seqstmt = makeNode(CreateSeqStmt);
375380
seqstmt->with_rowid = true;
376381
seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
377382
seqstmt->options = lcons(makeDefElem("as",
378-
(Node *) makeTypeNameFromOid(INT8OID, -1),
379-
-1),
380-
seqstmt->options);
383+
(Node *) makeTypeNameFromOid(INT8OID, -1),
384+
-1),
385+
seqstmt->options);
381386
if (rowid_seq_cache > 1)
382387
{
383388
seqstmt->options = lcons(makeDefElem("cache",
384-
(Node *) makeInteger(rowid_seq_cache),
385-
-1),
386-
seqstmt->options);
389+
(Node *) makeInteger(rowid_seq_cache),
390+
-1),
391+
seqstmt->options);
387392
}
388393
else
389394
seqstmt->options = lcons(makeDefElem("nocache",
390-
NULL,
391-
-1),
392-
seqstmt->options);
395+
NULL,
396+
-1),
397+
seqstmt->options);
393398

394399
if (cxt.rel)
395400
seqstmt->ownerId = cxt.rel->rd_rel->relowner;
396401

397402
cxt.blist = lappend(cxt.blist, seqstmt);
398403

399404
/*
400-
* Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence as owned
401-
* by this table.
405+
* Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence
406+
* as owned by this table.
402407
*/
403408
altseqstmt = makeNode(AlterSeqStmt);
404409
altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
405410

406411
relnamelist = list_make3(makeString(snamespace),
407-
makeString(cxt.relation->relname),
408-
makeString(sname));
412+
makeString(cxt.relation->relname),
413+
makeString(sname));
409414

410415
altseqstmt->options = list_make1(makeDefElem("owned_by",
411-
(Node *) relnamelist, -1));
416+
(Node *) relnamelist, -1));
412417
cxt.alist = lappend(cxt.alist, altseqstmt);
413418
}
414419

@@ -971,11 +976,14 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
971976
ctype = typenameType(cxt->pstate, column->typeName, &typmod);
972977
typeOid = ((Form_pg_type) GETSTRUCT(ctype))->oid;
973978

974-
/* Convert compatible identity smallint/int type column to bigint type */
979+
/*
980+
* Convert compatible identity smallint/int type column to
981+
* bigint type
982+
*/
975983
if ((constraint->generated_when == ATTRIBUTE_IDENTITY_DEFAULT_ON_NULL
976-
|| constraint->generated_when == ATTRIBUTE_ORA_IDENTITY_ALWAYS
977-
|| constraint->generated_when == ATTRIBUTE_ORA_IDENTITY_BY_DEFAULT)
978-
&& (typeOid == INT4OID || typeOid == INT2OID))
984+
|| constraint->generated_when == ATTRIBUTE_ORA_IDENTITY_ALWAYS
985+
|| constraint->generated_when == ATTRIBUTE_ORA_IDENTITY_BY_DEFAULT)
986+
&& (typeOid == INT4OID || typeOid == INT2OID))
979987
{
980988
column->typeName = makeTypeName("int8");
981989
typeOid = INT8OID;
@@ -1296,7 +1304,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
12961304
if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
12971305
{
12981306
aclresult = object_aclcheck(TypeRelationId, relation->rd_rel->reltype, GetUserId(),
1299-
ACL_USAGE);
1307+
ACL_USAGE);
13001308
if (aclresult != ACLCHECK_OK)
13011309
aclcheck_error(aclresult, OBJECT_TYPE,
13021310
RelationGetRelationName(relation));
@@ -2690,7 +2698,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
26902698
* mentioned above.
26912699
*/
26922700
Datum attoptions =
2693-
get_attoptions(RelationGetRelid(index_rel), i + 1);
2701+
get_attoptions(RelationGetRelid(index_rel), i + 1);
26942702

26952703
defopclass = GetDefaultOpClass(attform->atttypid,
26962704
index_rel->rd_rel->relam);
@@ -3765,12 +3773,12 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
37653773

37663774
case AT_AddRowidsRecurse:
37673775
{
3768-
Oid snamespaceid;
3769-
char *snamespace;
3770-
char *sname;
3771-
List *relnamelist;
3772-
CreateSeqStmt *seqstmt;
3773-
AlterSeqStmt *altseqstmt;
3776+
Oid snamespaceid;
3777+
char *snamespace;
3778+
char *sname;
3779+
List *relnamelist;
3780+
CreateSeqStmt *seqstmt;
3781+
AlterSeqStmt *altseqstmt;
37743782

37753783
if (cmd->is_rowid)
37763784
{
@@ -3790,45 +3798,46 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
37903798
false);
37913799

37923800
/*
3793-
* Build a CREATE SEQUENCE command to create the sequence object,
3794-
* and add it to the list of things to be done before this CREATE/ALTER TABLE
3801+
* Build a CREATE SEQUENCE command to create the
3802+
* sequence object, and add it to the list of things
3803+
* to be done before this CREATE/ALTER TABLE
37953804
*/
37963805
seqstmt = makeNode(CreateSeqStmt);
37973806
seqstmt->with_rowid = true;
37983807
seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
37993808
seqstmt->options = lcons(makeDefElem("as",
3800-
(Node *) makeTypeNameFromOid(INT8OID, -1),
3801-
-1), seqstmt->options);
3809+
(Node *) makeTypeNameFromOid(INT8OID, -1),
3810+
-1), seqstmt->options);
38023811
if (rowid_seq_cache > 1)
38033812
{
38043813
seqstmt->options = lcons(makeDefElem("cache",
3805-
(Node *) makeInteger(rowid_seq_cache),
3806-
-1), seqstmt->options);
3814+
(Node *) makeInteger(rowid_seq_cache),
3815+
-1), seqstmt->options);
38073816
}
38083817
else
38093818
seqstmt->options = lcons(makeDefElem("nocache",
3810-
NULL,
3811-
-1),
3812-
seqstmt->options);
3819+
NULL,
3820+
-1),
3821+
seqstmt->options);
38133822

38143823
if (cxt.rel)
38153824
seqstmt->ownerId = cxt.rel->rd_rel->relowner;
38163825

38173826
cxt.blist = lappend(cxt.blist, seqstmt);
38183827

38193828
/*
3820-
* Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence as owned
3821-
* by this table.
3829+
* Build an ALTER SEQUENCE ... OWNED BY command to
3830+
* mark the sequence as owned by this table.
38223831
*/
38233832
altseqstmt = makeNode(AlterSeqStmt);
38243833
altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
38253834

38263835
relnamelist = list_make3(makeString(snamespace),
3827-
makeString(cxt.relation->relname),
3828-
makeString(sname));
3836+
makeString(cxt.relation->relname),
3837+
makeString(sname));
38293838

38303839
altseqstmt->options = list_make1(makeDefElem("owned_by",
3831-
(Node *) relnamelist, -1));
3840+
(Node *) relnamelist, -1));
38323841
cxt.alist = lappend(cxt.alist, altseqstmt);
38333842

38343843
newcmds = lappend(newcmds, cmd);
@@ -4670,7 +4679,7 @@ transformPartitionRangeBounds(ParseState *pstate, List *blist,
46704679
* as ColumnRefs.
46714680
*/
46724681
if (IsA(expr, ColumnRef) ||
4673-
IsA(expr, ColumnRefOrFuncCall))
4682+
IsA(expr, ColumnRefOrFuncCall))
46744683
{
46754684
ColumnRef *cref = NULL;
46764685
char *cname = NULL;

src/backend/parser/scansup.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ downcase_identifier(const char *ident, int len, bool warn, bool truncate)
5656
/*
5757
* SQL99 specifies Unicode-aware case normalization, which we don't yet
5858
* have the infrastructure for. Instead we use tolower() to provide a
59-
* locale-aware translation. However, there are some locales where this
60-
* is not right either (eg, Turkish may do strange things with 'i' and
61-
* 'I'). Our current compromise is to use tolower() for characters with
62-
* the high bit set, as long as they aren't part of a multi-byte
63-
* character, and use an ASCII-only downcasing for 7-bit characters.
59+
* locale-aware translation. However, in some locales (for example,
60+
* Turkish with 'i' and 'I') this still is not correct. Our compromise is
61+
* to use tolower() for characters with the high bit set, as long as they
62+
* aren't part of a multi-byte character, and use an ASCII-only approach
63+
* for 7-bit characters.
6464
*/
6565
for (i = 0; i < len; i++)
6666
{

src/backend/tcop/backend_startup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
797797

798798
if (strcmp(nameptr, "database") == 0)
799799
{
800-
/* Oracle compatibility tranfor upper to lower */
800+
/* Oracle compatibility: transform uppercase identifiers to lowercase. */
801801
char *database_name = pstrdup(valptr);
802802

803803
if (ORA_PARSER == compatible_db && database_name != NULL)
@@ -850,7 +850,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
850850
}
851851
else if (strcmp(nameptr, "user") == 0)
852852
{
853-
/* Oracle compatibility tranfor upper to lower */
853+
/* Oracle compatibility: transform uppercase identifiers to lowercase. */
854854
char *user_name = pstrdup(valptr);
855855

856856
if (ORA_PARSER == compatible_db && user_name != NULL)

0 commit comments

Comments
 (0)