mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
OK, folks, here is the pgindent output.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.84 1998/09/01 03:24:02 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.85 1998/09/01 04:30:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -69,7 +69,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
|
||||
while (pl != NIL)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
elog(DEBUG,"parse tree from yacc:\n---\n%s\n---\n", nodeToString(lfirst(pl)));
|
||||
elog(DEBUG, "parse tree from yacc:\n---\n%s\n---\n", nodeToString(lfirst(pl)));
|
||||
#endif
|
||||
|
||||
pstate = make_parsestate(parentParseState);
|
||||
@@ -313,11 +313,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
* better to create proper target list here...
|
||||
*/
|
||||
te = makeTargetEntry(makeResdom(defval[ndef].adnum,
|
||||
att[defval[ndef].adnum - 1]->atttypid,
|
||||
att[defval[ndef].adnum - 1]->atttypmod,
|
||||
pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
|
||||
0, 0, 0),
|
||||
(Node *) stringToNode(defval[ndef].adbin));
|
||||
att[defval[ndef].adnum - 1]->atttypid,
|
||||
att[defval[ndef].adnum - 1]->atttypmod,
|
||||
pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
|
||||
0, 0, 0),
|
||||
(Node *) stringToNode(defval[ndef].adbin));
|
||||
qry->targetList = lappend(qry->targetList, te);
|
||||
}
|
||||
}
|
||||
@@ -325,9 +325,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
/* fix where clause */
|
||||
qry->qual = transformWhereClause(pstate, stmt->whereClause);
|
||||
|
||||
/* The havingQual has a similar meaning as "qual" in the where statement.
|
||||
* So we can easily use the code from the "where clause" with some additional
|
||||
* traversals done in .../optimizer/plan/planner.c */
|
||||
/*
|
||||
* The havingQual has a similar meaning as "qual" in the where
|
||||
* statement. So we can easily use the code from the "where clause"
|
||||
* with some additional traversals done in
|
||||
* .../optimizer/plan/planner.c
|
||||
*/
|
||||
qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
|
||||
|
||||
qry->hasSubLinks = pstate->p_hasSubLinks;
|
||||
@@ -351,20 +354,24 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
if (pstate->p_hasAggs)
|
||||
parseCheckAggregates(pstate, qry);
|
||||
|
||||
/* The INSERT INTO ... SELECT ... could have a UNION
|
||||
* in child, so unionClause may be false
|
||||
/*
|
||||
* The INSERT INTO ... SELECT ... could have a UNION in child, so
|
||||
* unionClause may be false
|
||||
*/
|
||||
qry->unionall = stmt->unionall;
|
||||
qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
|
||||
|
||||
/* If there is a havingQual but there are no aggregates, then there is something wrong
|
||||
* with the query because having must contain aggregates in its expressions!
|
||||
* Otherwise the query could have been formulated using the where clause. */
|
||||
if((qry->hasAggs == false) && (qry->havingQual != NULL))
|
||||
{
|
||||
elog(ERROR,"This is not a valid having query!");
|
||||
return (Query *)NIL;
|
||||
}
|
||||
/*
|
||||
* If there is a havingQual but there are no aggregates, then there is
|
||||
* something wrong with the query because having must contain
|
||||
* aggregates in its expressions! Otherwise the query could have been
|
||||
* formulated using the where clause.
|
||||
*/
|
||||
if ((qry->hasAggs == false) && (qry->havingQual != NULL))
|
||||
{
|
||||
elog(ERROR, "This is not a valid having query!");
|
||||
return (Query *) NIL;
|
||||
}
|
||||
|
||||
return (Query *) qry;
|
||||
}
|
||||
@@ -495,13 +502,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
|
||||
|
||||
if (column->is_sequence)
|
||||
{
|
||||
char *cstring;
|
||||
char *cstring;
|
||||
CreateSeqStmt *sequence;
|
||||
|
||||
constraint = makeNode(Constraint);
|
||||
constraint->contype = CONSTR_DEFAULT;
|
||||
constraint->name = makeTableName(stmt->relname, column->colname, "seq", NULL);
|
||||
cstring = palloc(9+strlen(constraint->name)+2+1);
|
||||
cstring = palloc(9 + strlen(constraint->name) + 2 + 1);
|
||||
strcpy(cstring, "nextval('");
|
||||
strcat(cstring, constraint->name);
|
||||
strcat(cstring, "')");
|
||||
@@ -509,20 +516,16 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
|
||||
constraint->keys = NULL;
|
||||
|
||||
if (column->constraints != NIL)
|
||||
{
|
||||
column->constraints = lappend(column->constraints, constraint);
|
||||
}
|
||||
else
|
||||
{
|
||||
column->constraints = lcons(constraint, NIL);
|
||||
}
|
||||
|
||||
sequence = makeNode(CreateSeqStmt);
|
||||
sequence->seqname = pstrdup(constraint->name);
|
||||
sequence->options = NIL;
|
||||
|
||||
elog(NOTICE, "CREATE TABLE will create implicit sequence %s for SERIAL column %s.%s",
|
||||
sequence->seqname, stmt->relname, column->colname);
|
||||
sequence->seqname, stmt->relname, column->colname);
|
||||
|
||||
ilist = lcons(sequence, NIL);
|
||||
|
||||
@@ -789,14 +792,16 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
|
||||
qry->commandType = CMD_UTILITY;
|
||||
|
||||
/*
|
||||
* 'instead nothing' rules with a qualification need a
|
||||
* query a rangetable so the rewrite handler can add the
|
||||
* negated rule qualification to the original query. We
|
||||
* create a query with the new command type CMD_NOTHING
|
||||
* here that is treated special by the rewrite system.
|
||||
* 'instead nothing' rules with a qualification need a query a
|
||||
* rangetable so the rewrite handler can add the negated rule
|
||||
* qualification to the original query. We create a query with the new
|
||||
* command type CMD_NOTHING here that is treated special by the
|
||||
* rewrite system.
|
||||
*/
|
||||
if (stmt->actions == NIL) {
|
||||
Query *nothing_qry = makeNode(Query);
|
||||
if (stmt->actions == NIL)
|
||||
{
|
||||
Query *nothing_qry = makeNode(Query);
|
||||
|
||||
nothing_qry->commandType = CMD_NOTHING;
|
||||
|
||||
addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
|
||||
@@ -830,7 +835,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
|
||||
pstate->p_is_rule = true; /* for expand all */
|
||||
pstate->p_hasAggs = false;
|
||||
|
||||
action = (Query *)lfirst(actions);
|
||||
action = (Query *) lfirst(actions);
|
||||
if (action->commandType != CMD_NOTHING)
|
||||
lfirst(actions) = transformStmt(pstate, lfirst(actions));
|
||||
actions = lnext(actions);
|
||||
@@ -869,9 +874,12 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
|
||||
qry->qual = transformWhereClause(pstate, stmt->whereClause);
|
||||
|
||||
/* The havingQual has a similar meaning as "qual" in the where statement.
|
||||
* So we can easily use the code from the "where clause" with some additional
|
||||
* traversals done in .../optimizer/plan/planner.c */
|
||||
/*
|
||||
* The havingQual has a similar meaning as "qual" in the where
|
||||
* statement. So we can easily use the code from the "where clause"
|
||||
* with some additional traversals done in
|
||||
* .../optimizer/plan/planner.c
|
||||
*/
|
||||
qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
|
||||
|
||||
qry->hasSubLinks = pstate->p_hasSubLinks;
|
||||
@@ -891,20 +899,24 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
if (pstate->p_hasAggs)
|
||||
parseCheckAggregates(pstate, qry);
|
||||
|
||||
/* The INSERT INTO ... SELECT ... could have a UNION
|
||||
* in child, so unionClause may be false
|
||||
/*
|
||||
* The INSERT INTO ... SELECT ... could have a UNION in child, so
|
||||
* unionClause may be false
|
||||
*/
|
||||
qry->unionall = stmt->unionall;
|
||||
qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
|
||||
|
||||
/* If there is a havingQual but there are no aggregates, then there is something wrong
|
||||
* with the query because having must contain aggregates in its expressions!
|
||||
* Otherwise the query could have been formulated using the where clause. */
|
||||
if((qry->hasAggs == false) && (qry->havingQual != NULL))
|
||||
{
|
||||
elog(ERROR,"This is not a valid having query!");
|
||||
return (Query *)NIL;
|
||||
}
|
||||
/*
|
||||
* If there is a havingQual but there are no aggregates, then there is
|
||||
* something wrong with the query because having must contain
|
||||
* aggregates in its expressions! Otherwise the query could have been
|
||||
* formulated using the where clause.
|
||||
*/
|
||||
if ((qry->hasAggs == false) && (qry->havingQual != NULL))
|
||||
{
|
||||
elog(ERROR, "This is not a valid having query!");
|
||||
return (Query *) NIL;
|
||||
}
|
||||
|
||||
return (Query *) qry;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.43 1998/09/01 03:24:10 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.44 1998/09/01 04:30:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -66,12 +66,9 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"createdb", CREATEDB},
|
||||
{"createuser", CREATEUSER},
|
||||
{"cross", CROSS},
|
||||
{"current", CURRENT}, /*
|
||||
* 6.4 to 6.5 is migration time!
|
||||
* CURRENT will be removed in 6.5!
|
||||
* Use OLD keyword in rules.
|
||||
* Jan
|
||||
*/
|
||||
{"current", CURRENT}, /* 6.4 to 6.5 is migration time! CURRENT
|
||||
* will be removed in 6.5! Use OLD keyword
|
||||
* in rules. Jan */
|
||||
{"current_date", CURRENT_DATE},
|
||||
{"current_time", CURRENT_TIME},
|
||||
{"current_timestamp", CURRENT_TIMESTAMP},
|
||||
|
||||
@@ -1,236 +1,237 @@
|
||||
typedef union
|
||||
{
|
||||
double dval;
|
||||
int ival;
|
||||
char chr;
|
||||
char *str;
|
||||
bool boolean;
|
||||
bool* pboolean; /* for pg_shadow privileges */
|
||||
List *list;
|
||||
Node *node;
|
||||
Value *value;
|
||||
double dval;
|
||||
int ival;
|
||||
char chr;
|
||||
char *str;
|
||||
bool boolean;
|
||||
bool *pboolean; /* for pg_shadow privileges */
|
||||
List *list;
|
||||
Node *node;
|
||||
Value *value;
|
||||
|
||||
Attr *attr;
|
||||
Attr *attr;
|
||||
|
||||
TypeName *typnam;
|
||||
DefElem *defelt;
|
||||
ParamString *param;
|
||||
SortGroupBy *sortgroupby;
|
||||
JoinUsing *joinusing;
|
||||
IndexElem *ielem;
|
||||
RangeVar *range;
|
||||
RelExpr *relexp;
|
||||
A_Indices *aind;
|
||||
ResTarget *target;
|
||||
ParamNo *paramno;
|
||||
TypeName *typnam;
|
||||
DefElem *defelt;
|
||||
ParamString *param;
|
||||
SortGroupBy *sortgroupby;
|
||||
JoinUsing *joinusing;
|
||||
IndexElem *ielem;
|
||||
RangeVar *range;
|
||||
RelExpr *relexp;
|
||||
A_Indices *aind;
|
||||
ResTarget *target;
|
||||
ParamNo *paramno;
|
||||
|
||||
VersionStmt *vstmt;
|
||||
DefineStmt *dstmt;
|
||||
RuleStmt *rstmt;
|
||||
InsertStmt *astmt;
|
||||
VersionStmt *vstmt;
|
||||
DefineStmt *dstmt;
|
||||
RuleStmt *rstmt;
|
||||
InsertStmt *astmt;
|
||||
} YYSTYPE;
|
||||
#define ACTION 258
|
||||
#define ADD 259
|
||||
#define ALL 260
|
||||
#define ALTER 261
|
||||
#define AND 262
|
||||
#define ANY 263
|
||||
#define AS 264
|
||||
#define ASC 265
|
||||
#define BEGIN_TRANS 266
|
||||
#define BETWEEN 267
|
||||
#define BOTH 268
|
||||
#define BY 269
|
||||
#define CASCADE 270
|
||||
#define CAST 271
|
||||
#define CHAR 272
|
||||
#define CHARACTER 273
|
||||
#define CHECK 274
|
||||
#define CLOSE 275
|
||||
#define COLLATE 276
|
||||
#define COLUMN 277
|
||||
#define COMMIT 278
|
||||
#define CONSTRAINT 279
|
||||
#define CREATE 280
|
||||
#define CROSS 281
|
||||
#define CURRENT 282
|
||||
#define CURRENT_DATE 283
|
||||
#define CURRENT_TIME 284
|
||||
#define CURRENT_TIMESTAMP 285
|
||||
#define CURRENT_USER 286
|
||||
#define CURSOR 287
|
||||
#define DAY_P 288
|
||||
#define DECIMAL 289
|
||||
#define DECLARE 290
|
||||
#define DEFAULT 291
|
||||
#define DELETE 292
|
||||
#define DESC 293
|
||||
#define DISTINCT 294
|
||||
#define DOUBLE 295
|
||||
#define DROP 296
|
||||
#define END_TRANS 297
|
||||
#define EXECUTE 298
|
||||
#define EXISTS 299
|
||||
#define EXTRACT 300
|
||||
#define FETCH 301
|
||||
#define FLOAT 302
|
||||
#define FOR 303
|
||||
#define FOREIGN 304
|
||||
#define FROM 305
|
||||
#define FULL 306
|
||||
#define GRANT 307
|
||||
#define GROUP 308
|
||||
#define HAVING 309
|
||||
#define HOUR_P 310
|
||||
#define IN 311
|
||||
#define INNER_P 312
|
||||
#define INSERT 313
|
||||
#define INTERVAL 314
|
||||
#define INTO 315
|
||||
#define IS 316
|
||||
#define JOIN 317
|
||||
#define KEY 318
|
||||
#define LANGUAGE 319
|
||||
#define LEADING 320
|
||||
#define LEFT 321
|
||||
#define LIKE 322
|
||||
#define LOCAL 323
|
||||
#define MATCH 324
|
||||
#define MINUTE_P 325
|
||||
#define MONTH_P 326
|
||||
#define NAMES 327
|
||||
#define NATIONAL 328
|
||||
#define NATURAL 329
|
||||
#define NCHAR 330
|
||||
#define NO 331
|
||||
#define NOT 332
|
||||
#define NOTIFY 333
|
||||
#define NULL_P 334
|
||||
#define NUMERIC 335
|
||||
#define ON 336
|
||||
#define OPTION 337
|
||||
#define OR 338
|
||||
#define ORDER 339
|
||||
#define OUTER_P 340
|
||||
#define PARTIAL 341
|
||||
#define POSITION 342
|
||||
#define PRECISION 343
|
||||
#define PRIMARY 344
|
||||
#define PRIVILEGES 345
|
||||
#define PROCEDURE 346
|
||||
#define PUBLIC 347
|
||||
#define REFERENCES 348
|
||||
#define REVOKE 349
|
||||
#define RIGHT 350
|
||||
#define ROLLBACK 351
|
||||
#define SECOND_P 352
|
||||
#define SELECT 353
|
||||
#define SET 354
|
||||
#define SUBSTRING 355
|
||||
#define TABLE 356
|
||||
#define TIME 357
|
||||
#define TIMESTAMP 358
|
||||
#define TIMEZONE_HOUR 359
|
||||
#define TIMEZONE_MINUTE 360
|
||||
#define TO 361
|
||||
#define TRAILING 362
|
||||
#define TRANSACTION 363
|
||||
#define TRIM 364
|
||||
#define UNION 365
|
||||
#define UNIQUE 366
|
||||
#define UPDATE 367
|
||||
#define USER 368
|
||||
#define USING 369
|
||||
#define VALUES 370
|
||||
#define VARCHAR 371
|
||||
#define VARYING 372
|
||||
#define VIEW 373
|
||||
#define WHERE 374
|
||||
#define WITH 375
|
||||
#define WORK 376
|
||||
#define YEAR_P 377
|
||||
#define ZONE 378
|
||||
#define FALSE_P 379
|
||||
#define TRIGGER 380
|
||||
#define TRUE_P 381
|
||||
#define TYPE_P 382
|
||||
#define ABORT_TRANS 383
|
||||
#define AFTER 384
|
||||
#define AGGREGATE 385
|
||||
#define ANALYZE 386
|
||||
#define BACKWARD 387
|
||||
#define BEFORE 388
|
||||
#define BINARY 389
|
||||
#define CACHE 390
|
||||
#define CLUSTER 391
|
||||
#define COPY 392
|
||||
#define CYCLE 393
|
||||
#define DATABASE 394
|
||||
#define DELIMITERS 395
|
||||
#define DO 396
|
||||
#define EACH 397
|
||||
#define EXPLAIN 398
|
||||
#define EXTEND 399
|
||||
#define FORWARD 400
|
||||
#define FUNCTION 401
|
||||
#define HANDLER 402
|
||||
#define INCREMENT 403
|
||||
#define INDEX 404
|
||||
#define INHERITS 405
|
||||
#define INSTEAD 406
|
||||
#define ISNULL 407
|
||||
#define LANCOMPILER 408
|
||||
#define LISTEN 409
|
||||
#define LOAD 410
|
||||
#define LOCK_P 411
|
||||
#define LOCATION 412
|
||||
#define MAXVALUE 413
|
||||
#define MINVALUE 414
|
||||
#define MOVE 415
|
||||
#define NEW 416
|
||||
#define NONE 417
|
||||
#define NOTHING 418
|
||||
#define NOTNULL 419
|
||||
#define OIDS 420
|
||||
#define OPERATOR 421
|
||||
#define PROCEDURAL 422
|
||||
#define RECIPE 423
|
||||
#define RENAME 424
|
||||
#define RESET 425
|
||||
#define RETURNS 426
|
||||
#define ROW 427
|
||||
#define RULE 428
|
||||
#define SEQUENCE 429
|
||||
#define SERIAL 430
|
||||
#define SETOF 431
|
||||
#define SHOW 432
|
||||
#define START 433
|
||||
#define STATEMENT 434
|
||||
#define STDIN 435
|
||||
#define STDOUT 436
|
||||
#define TRUSTED 437
|
||||
#define VACUUM 438
|
||||
#define VERBOSE 439
|
||||
#define VERSION 440
|
||||
#define ENCODING 441
|
||||
#define UNLISTEN 442
|
||||
#define ARCHIVE 443
|
||||
#define PASSWORD 444
|
||||
#define CREATEDB 445
|
||||
#define NOCREATEDB 446
|
||||
#define CREATEUSER 447
|
||||
#define NOCREATEUSER 448
|
||||
#define VALID 449
|
||||
#define UNTIL 450
|
||||
#define IDENT 451
|
||||
#define SCONST 452
|
||||
#define Op 453
|
||||
#define ICONST 454
|
||||
#define PARAM 455
|
||||
#define FCONST 456
|
||||
#define OP 457
|
||||
#define UMINUS 458
|
||||
#define TYPECAST 459
|
||||
|
||||
#define ACTION 258
|
||||
#define ADD 259
|
||||
#define ALL 260
|
||||
#define ALTER 261
|
||||
#define AND 262
|
||||
#define ANY 263
|
||||
#define AS 264
|
||||
#define ASC 265
|
||||
#define BEGIN_TRANS 266
|
||||
#define BETWEEN 267
|
||||
#define BOTH 268
|
||||
#define BY 269
|
||||
#define CASCADE 270
|
||||
#define CAST 271
|
||||
#define CHAR 272
|
||||
#define CHARACTER 273
|
||||
#define CHECK 274
|
||||
#define CLOSE 275
|
||||
#define COLLATE 276
|
||||
#define COLUMN 277
|
||||
#define COMMIT 278
|
||||
#define CONSTRAINT 279
|
||||
#define CREATE 280
|
||||
#define CROSS 281
|
||||
#define CURRENT 282
|
||||
#define CURRENT_DATE 283
|
||||
#define CURRENT_TIME 284
|
||||
#define CURRENT_TIMESTAMP 285
|
||||
#define CURRENT_USER 286
|
||||
#define CURSOR 287
|
||||
#define DAY_P 288
|
||||
#define DECIMAL 289
|
||||
#define DECLARE 290
|
||||
#define DEFAULT 291
|
||||
#define DELETE 292
|
||||
#define DESC 293
|
||||
#define DISTINCT 294
|
||||
#define DOUBLE 295
|
||||
#define DROP 296
|
||||
#define END_TRANS 297
|
||||
#define EXECUTE 298
|
||||
#define EXISTS 299
|
||||
#define EXTRACT 300
|
||||
#define FETCH 301
|
||||
#define FLOAT 302
|
||||
#define FOR 303
|
||||
#define FOREIGN 304
|
||||
#define FROM 305
|
||||
#define FULL 306
|
||||
#define GRANT 307
|
||||
#define GROUP 308
|
||||
#define HAVING 309
|
||||
#define HOUR_P 310
|
||||
#define IN 311
|
||||
#define INNER_P 312
|
||||
#define INSERT 313
|
||||
#define INTERVAL 314
|
||||
#define INTO 315
|
||||
#define IS 316
|
||||
#define JOIN 317
|
||||
#define KEY 318
|
||||
#define LANGUAGE 319
|
||||
#define LEADING 320
|
||||
#define LEFT 321
|
||||
#define LIKE 322
|
||||
#define LOCAL 323
|
||||
#define MATCH 324
|
||||
#define MINUTE_P 325
|
||||
#define MONTH_P 326
|
||||
#define NAMES 327
|
||||
#define NATIONAL 328
|
||||
#define NATURAL 329
|
||||
#define NCHAR 330
|
||||
#define NO 331
|
||||
#define NOT 332
|
||||
#define NOTIFY 333
|
||||
#define NULL_P 334
|
||||
#define NUMERIC 335
|
||||
#define ON 336
|
||||
#define OPTION 337
|
||||
#define OR 338
|
||||
#define ORDER 339
|
||||
#define OUTER_P 340
|
||||
#define PARTIAL 341
|
||||
#define POSITION 342
|
||||
#define PRECISION 343
|
||||
#define PRIMARY 344
|
||||
#define PRIVILEGES 345
|
||||
#define PROCEDURE 346
|
||||
#define PUBLIC 347
|
||||
#define REFERENCES 348
|
||||
#define REVOKE 349
|
||||
#define RIGHT 350
|
||||
#define ROLLBACK 351
|
||||
#define SECOND_P 352
|
||||
#define SELECT 353
|
||||
#define SET 354
|
||||
#define SUBSTRING 355
|
||||
#define TABLE 356
|
||||
#define TIME 357
|
||||
#define TIMESTAMP 358
|
||||
#define TIMEZONE_HOUR 359
|
||||
#define TIMEZONE_MINUTE 360
|
||||
#define TO 361
|
||||
#define TRAILING 362
|
||||
#define TRANSACTION 363
|
||||
#define TRIM 364
|
||||
#define UNION 365
|
||||
#define UNIQUE 366
|
||||
#define UPDATE 367
|
||||
#define USER 368
|
||||
#define USING 369
|
||||
#define VALUES 370
|
||||
#define VARCHAR 371
|
||||
#define VARYING 372
|
||||
#define VIEW 373
|
||||
#define WHERE 374
|
||||
#define WITH 375
|
||||
#define WORK 376
|
||||
#define YEAR_P 377
|
||||
#define ZONE 378
|
||||
#define FALSE_P 379
|
||||
#define TRIGGER 380
|
||||
#define TRUE_P 381
|
||||
#define TYPE_P 382
|
||||
#define ABORT_TRANS 383
|
||||
#define AFTER 384
|
||||
#define AGGREGATE 385
|
||||
#define ANALYZE 386
|
||||
#define BACKWARD 387
|
||||
#define BEFORE 388
|
||||
#define BINARY 389
|
||||
#define CACHE 390
|
||||
#define CLUSTER 391
|
||||
#define COPY 392
|
||||
#define CYCLE 393
|
||||
#define DATABASE 394
|
||||
#define DELIMITERS 395
|
||||
#define DO 396
|
||||
#define EACH 397
|
||||
#define EXPLAIN 398
|
||||
#define EXTEND 399
|
||||
#define FORWARD 400
|
||||
#define FUNCTION 401
|
||||
#define HANDLER 402
|
||||
#define INCREMENT 403
|
||||
#define INDEX 404
|
||||
#define INHERITS 405
|
||||
#define INSTEAD 406
|
||||
#define ISNULL 407
|
||||
#define LANCOMPILER 408
|
||||
#define LISTEN 409
|
||||
#define LOAD 410
|
||||
#define LOCK_P 411
|
||||
#define LOCATION 412
|
||||
#define MAXVALUE 413
|
||||
#define MINVALUE 414
|
||||
#define MOVE 415
|
||||
#define NEW 416
|
||||
#define NONE 417
|
||||
#define NOTHING 418
|
||||
#define NOTNULL 419
|
||||
#define OIDS 420
|
||||
#define OPERATOR 421
|
||||
#define PROCEDURAL 422
|
||||
#define RECIPE 423
|
||||
#define RENAME 424
|
||||
#define RESET 425
|
||||
#define RETURNS 426
|
||||
#define ROW 427
|
||||
#define RULE 428
|
||||
#define SEQUENCE 429
|
||||
#define SERIAL 430
|
||||
#define SETOF 431
|
||||
#define SHOW 432
|
||||
#define START 433
|
||||
#define STATEMENT 434
|
||||
#define STDIN 435
|
||||
#define STDOUT 436
|
||||
#define TRUSTED 437
|
||||
#define VACUUM 438
|
||||
#define VERBOSE 439
|
||||
#define VERSION 440
|
||||
#define ENCODING 441
|
||||
#define UNLISTEN 442
|
||||
#define ARCHIVE 443
|
||||
#define PASSWORD 444
|
||||
#define CREATEDB 445
|
||||
#define NOCREATEDB 446
|
||||
#define CREATEUSER 447
|
||||
#define NOCREATEUSER 448
|
||||
#define VALID 449
|
||||
#define UNTIL 450
|
||||
#define IDENT 451
|
||||
#define SCONST 452
|
||||
#define Op 453
|
||||
#define ICONST 454
|
||||
#define PARAM 455
|
||||
#define FCONST 456
|
||||
#define OP 457
|
||||
#define UMINUS 458
|
||||
#define TYPECAST 459
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.12 1998/08/19 02:02:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.13 1998/09/01 04:30:26 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -332,7 +332,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
|
||||
aggreg->target = lfirst(target);
|
||||
if (usenulls)
|
||||
aggreg->usenulls = true;
|
||||
|
||||
|
||||
pstate->p_hasAggs = true;
|
||||
|
||||
return aggreg;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.24 1998/08/25 03:17:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.25 1998/09/01 04:30:27 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -35,7 +35,7 @@
|
||||
static char *clauseText[] = {"ORDER", "GROUP"};
|
||||
|
||||
static TargetEntry *
|
||||
findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause);
|
||||
findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause);
|
||||
|
||||
static void parseFromClause(ParseState *pstate, List *frmList);
|
||||
|
||||
@@ -71,7 +71,7 @@ makeRangeTable(ParseState *pstate, char *relname, List *frmList)
|
||||
/*
|
||||
* transformWhereClause -
|
||||
* transforms the qualification and make sure it is of type Boolean
|
||||
*
|
||||
*
|
||||
*/
|
||||
Node *
|
||||
transformWhereClause(ParseState *pstate, Node *a_expr)
|
||||
@@ -138,44 +138,44 @@ parseFromClause(ParseState *pstate, List *frmList)
|
||||
* returns the Resdom in the target list matching the specified varname
|
||||
* and range. If none exist one is created.
|
||||
*
|
||||
* Rewritten for ver 6.4 to handle expressions in the GROUP/ORDER BY clauses.
|
||||
* - daveh@insightdist.com 1998-07-31
|
||||
* Rewritten for ver 6.4 to handle expressions in the GROUP/ORDER BY clauses.
|
||||
* - daveh@insightdist.com 1998-07-31
|
||||
*
|
||||
*/
|
||||
static TargetEntry *
|
||||
findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
{
|
||||
List *l;
|
||||
int rtable_pos = 0,
|
||||
target_pos = 0,
|
||||
targetlist_pos = 0;
|
||||
List *l;
|
||||
int rtable_pos = 0,
|
||||
target_pos = 0,
|
||||
targetlist_pos = 0;
|
||||
TargetEntry *target_result = NULL;
|
||||
Value *val = NULL;
|
||||
char *relname = NULL;
|
||||
char *name = NULL;
|
||||
Node *expr = NULL;
|
||||
Value *val = NULL;
|
||||
char *relname = NULL;
|
||||
char *name = NULL;
|
||||
Node *expr = NULL;
|
||||
int relCnt = 0;
|
||||
|
||||
/* Pull out some values before looping thru target list */
|
||||
switch(nodeTag(node))
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Attr:
|
||||
relname = ((Attr*)node)->relname;
|
||||
val = (Value *)lfirst(((Attr*)node)->attrs);
|
||||
case T_Attr:
|
||||
relname = ((Attr *) node)->relname;
|
||||
val = (Value *) lfirst(((Attr *) node)->attrs);
|
||||
name = strVal(val);
|
||||
rtable_pos = refnameRangeTablePosn(pstate, relname, NULL);
|
||||
relCnt = length(pstate->p_rtable);
|
||||
break;
|
||||
|
||||
case T_Ident:
|
||||
name = ((Ident*)node)->name;
|
||||
name = ((Ident *) node)->name;
|
||||
relCnt = length(pstate->p_rtable);
|
||||
break;
|
||||
|
||||
case T_A_Const:
|
||||
val = &((A_Const*)node)->val;
|
||||
|
||||
if (nodeTag(val) != T_Integer)
|
||||
val = &((A_Const *) node)->val;
|
||||
|
||||
if (nodeTag(val) != T_Integer)
|
||||
elog(ERROR, "Illegal Constant in %s BY", clauseText[clause]);
|
||||
target_pos = intVal(val);
|
||||
break;
|
||||
@@ -190,7 +190,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through target entries and try to match to node
|
||||
* Loop through target entries and try to match to node
|
||||
*/
|
||||
foreach(l, tlist)
|
||||
{
|
||||
@@ -202,93 +202,107 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
|
||||
|
||||
++targetlist_pos;
|
||||
|
||||
switch(nodeTag(node))
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Attr:
|
||||
if (strcmp(resname, name) == 0 && rtable_pos == test_rtable_pos)
|
||||
{
|
||||
/* Check for only 1 table & ORDER BY -ambiguity does not matter here */
|
||||
if (clause == ORDER_CLAUSE && relCnt == 1)
|
||||
case T_Attr:
|
||||
if (strcmp(resname, name) == 0 && rtable_pos == test_rtable_pos)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check for only 1 table & ORDER BY -ambiguity does
|
||||
* not matter here
|
||||
*/
|
||||
if (clause == ORDER_CLAUSE && relCnt == 1)
|
||||
return target;
|
||||
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "%s BY '%s' is ambiguous", clauseText[clause], name);
|
||||
else
|
||||
target_result = target;
|
||||
/* Stay in loop to check for ambiguity */
|
||||
}
|
||||
break;
|
||||
|
||||
case T_Ident:
|
||||
if (strcmp(resname, name) == 0)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check for only 1 table & ORDER BY -ambiguity does
|
||||
* not matter here
|
||||
*/
|
||||
if (clause == ORDER_CLAUSE && relCnt == 1)
|
||||
return target;
|
||||
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "%s BY '%s' is ambiguous", clauseText[clause], name);
|
||||
else
|
||||
target_result = target;
|
||||
/* Stay in loop to check for ambiguity */
|
||||
}
|
||||
break;
|
||||
|
||||
case T_A_Const:
|
||||
if (target_pos == targetlist_pos)
|
||||
{
|
||||
/* Can't be ambigious and we got what we came for */
|
||||
return target;
|
||||
}
|
||||
break;
|
||||
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "%s BY '%s' is ambiguous", clauseText[clause], name);
|
||||
else
|
||||
target_result = target;
|
||||
/* Stay in loop to check for ambiguity */
|
||||
}
|
||||
break;
|
||||
case T_FuncCall:
|
||||
case T_A_Expr:
|
||||
if (equal(expr, target->expr))
|
||||
{
|
||||
|
||||
case T_Ident:
|
||||
if (strcmp(resname, name) == 0)
|
||||
{
|
||||
/* Check for only 1 table & ORDER BY -ambiguity does not matter here */
|
||||
if (clause == ORDER_CLAUSE && relCnt == 1)
|
||||
return target;
|
||||
/*
|
||||
* Check for only 1 table & ORDER BY -ambiguity does
|
||||
* not matter here
|
||||
*/
|
||||
if (clause == ORDER_CLAUSE)
|
||||
return target;
|
||||
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "%s BY '%s' is ambiguous", clauseText[clause], name);
|
||||
else
|
||||
target_result = target;
|
||||
/* Stay in loop to check for ambiguity */
|
||||
}
|
||||
break;
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "GROUP BY has ambiguous expression");
|
||||
else
|
||||
target_result = target;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_A_Const:
|
||||
if (target_pos == targetlist_pos)
|
||||
{
|
||||
/* Can't be ambigious and we got what we came for */
|
||||
return target;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_FuncCall:
|
||||
case T_A_Expr:
|
||||
if (equal(expr, target->expr))
|
||||
{
|
||||
/* Check for only 1 table & ORDER BY -ambiguity does not matter here */
|
||||
if (clause == ORDER_CLAUSE)
|
||||
return target;
|
||||
|
||||
if (target_result != NULL)
|
||||
elog(ERROR, "GROUP BY has ambiguous expression");
|
||||
else
|
||||
target_result = target;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "Illegal %s BY node = %d", clauseText[clause], nodeTag(node));
|
||||
default:
|
||||
elog(ERROR, "Illegal %s BY node = %d", clauseText[clause], nodeTag(node));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no matches, construct a new target entry which is appended to the end
|
||||
* of the target list. This target is set to be resjunk = TRUE so that
|
||||
* it will not be projected into the final tuple.
|
||||
*/
|
||||
/*
|
||||
* If no matches, construct a new target entry which is appended to
|
||||
* the end of the target list. This target is set to be resjunk =
|
||||
* TRUE so that it will not be projected into the final tuple.
|
||||
*/
|
||||
if (target_result == NULL)
|
||||
{
|
||||
switch(nodeTag(node))
|
||||
{
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Attr:
|
||||
case T_Attr:
|
||||
target_result = MakeTargetEntryIdent(pstate, node,
|
||||
&((Attr*)node)->relname, NULL,
|
||||
((Attr*)node)->relname, TRUE);
|
||||
&((Attr *) node)->relname, NULL,
|
||||
((Attr *) node)->relname, TRUE);
|
||||
lappend(tlist, target_result);
|
||||
break;
|
||||
|
||||
case T_Ident:
|
||||
target_result = MakeTargetEntryIdent(pstate, node,
|
||||
&((Ident*)node)->name, NULL,
|
||||
((Ident*)node)->name, TRUE);
|
||||
&((Ident *) node)->name, NULL,
|
||||
((Ident *) node)->name, TRUE);
|
||||
lappend(tlist, target_result);
|
||||
break;
|
||||
|
||||
case T_A_Const:
|
||||
/*
|
||||
* If we got this far, then must have been an out-of-range column number
|
||||
*/
|
||||
|
||||
/*
|
||||
* If we got this far, then must have been an out-of-range
|
||||
* column number
|
||||
*/
|
||||
elog(ERROR, "%s BY position %d is not in target list", clauseText[clause], target_pos);
|
||||
break;
|
||||
|
||||
@@ -376,7 +390,7 @@ transformSortClause(ParseState *pstate,
|
||||
List *s = NIL;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformSortClause: entering\n");
|
||||
printf("transformSortClause: entering\n");
|
||||
#endif
|
||||
|
||||
while (orderlist != NIL)
|
||||
@@ -389,13 +403,16 @@ printf("transformSortClause: entering\n");
|
||||
restarget = findTargetlistEntry(pstate, sortby->node, targetlist, ORDER_CLAUSE);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformSortClause: find sorting operator for type %d\n",
|
||||
restarget->resdom->restype);
|
||||
printf("transformSortClause: find sorting operator for type %d\n",
|
||||
restarget->resdom->restype);
|
||||
#endif
|
||||
|
||||
sortcl->resdom = resdom = restarget->resdom;
|
||||
|
||||
/* if we have InvalidOid, then this is a NULL field and don't need to sort */
|
||||
/*
|
||||
* if we have InvalidOid, then this is a NULL field and don't need
|
||||
* to sort
|
||||
*/
|
||||
if (resdom->restype == InvalidOid)
|
||||
resdom->restype = INT4OID;
|
||||
|
||||
@@ -447,10 +464,10 @@ printf("transformSortClause: find sorting operator for type %d\n",
|
||||
SortClause *sortcl = lfirst(s);
|
||||
|
||||
/*
|
||||
* We use equal() here because we are called for UNION
|
||||
* from the optimizer, and at that point, the sort clause
|
||||
* resdom pointers don't match the target list resdom
|
||||
* pointers
|
||||
* We use equal() here because we are called for UNION
|
||||
* from the optimizer, and at that point, the sort
|
||||
* clause resdom pointers don't match the target list
|
||||
* resdom pointers
|
||||
*/
|
||||
if (equal(sortcl->resdom, tlelt->resdom))
|
||||
break;
|
||||
@@ -462,8 +479,8 @@ printf("transformSortClause: find sorting operator for type %d\n",
|
||||
SortClause *sortcl = makeNode(SortClause);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformSortClause: (2) find sorting operator for type %d\n",
|
||||
tlelt->resdom->restype);
|
||||
printf("transformSortClause: (2) find sorting operator for type %d\n",
|
||||
tlelt->resdom->restype);
|
||||
#endif
|
||||
|
||||
if (tlelt->resdom->restype == InvalidOid)
|
||||
@@ -504,8 +521,8 @@ printf("transformSortClause: (2) find sorting operator for type %d\n",
|
||||
SortClause *sortcl = makeNode(SortClause);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformSortClause: try sorting type %d\n",
|
||||
tlelt->resdom->restype);
|
||||
printf("transformSortClause: try sorting type %d\n",
|
||||
tlelt->resdom->restype);
|
||||
#endif
|
||||
|
||||
sortcl->resdom = tlelt->resdom;
|
||||
@@ -523,20 +540,20 @@ printf("transformSortClause: try sorting type %d\n",
|
||||
* Transform a UNION clause.
|
||||
* Note that the union clause is actually a fully-formed select structure.
|
||||
* So, it is evaluated as a select, then the resulting target fields
|
||||
* are matched up to ensure correct types in the results.
|
||||
* are matched up to ensure correct types in the results.
|
||||
* The select clause parsing is done recursively, so the unions are evaluated
|
||||
* right-to-left. One might want to look at all columns from all clauses before
|
||||
* trying to coerce, but unless we keep track of the call depth we won't know
|
||||
* when to do this because of the recursion.
|
||||
* right-to-left. One might want to look at all columns from all clauses before
|
||||
* trying to coerce, but unless we keep track of the call depth we won't know
|
||||
* when to do this because of the recursion.
|
||||
* Let's just try matching in pairs for now (right to left) and see if it works.
|
||||
* - thomas 1998-05-22
|
||||
*/
|
||||
List *
|
||||
transformUnionClause(List *unionClause, List *targetlist)
|
||||
{
|
||||
List *union_list = NIL;
|
||||
List *union_list = NIL;
|
||||
QueryTreeList *qlist;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (unionClause)
|
||||
{
|
||||
@@ -547,19 +564,20 @@ transformUnionClause(List *unionClause, List *targetlist)
|
||||
{
|
||||
List *prev_target = targetlist;
|
||||
List *next_target;
|
||||
|
||||
|
||||
if (length(targetlist) != length(qlist->qtrees[i]->targetList))
|
||||
elog(ERROR,"Each UNION clause must have the same number of columns");
|
||||
|
||||
elog(ERROR, "Each UNION clause must have the same number of columns");
|
||||
|
||||
foreach(next_target, qlist->qtrees[i]->targetList)
|
||||
{
|
||||
Oid itype;
|
||||
Oid otype;
|
||||
otype = ((TargetEntry *)lfirst(prev_target))->resdom->restype;
|
||||
itype = ((TargetEntry *)lfirst(next_target))->resdom->restype;
|
||||
Oid itype;
|
||||
Oid otype;
|
||||
|
||||
otype = ((TargetEntry *) lfirst(prev_target))->resdom->restype;
|
||||
itype = ((TargetEntry *) lfirst(next_target))->resdom->restype;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformUnionClause: types are %d -> %d\n", itype, otype);
|
||||
printf("transformUnionClause: types are %d -> %d\n", itype, otype);
|
||||
#endif
|
||||
|
||||
/* one or both is a NULL column? then don't convert... */
|
||||
@@ -567,14 +585,12 @@ printf("transformUnionClause: types are %d -> %d\n", itype, otype);
|
||||
{
|
||||
/* propagate a known type forward, if available */
|
||||
if (itype != InvalidOid)
|
||||
{
|
||||
((TargetEntry *)lfirst(prev_target))->resdom->restype = itype;
|
||||
}
|
||||
((TargetEntry *) lfirst(prev_target))->resdom->restype = itype;
|
||||
#if FALSE
|
||||
else
|
||||
{
|
||||
((TargetEntry *)lfirst(prev_target))->resdom->restype = UNKNOWNOID;
|
||||
((TargetEntry *)lfirst(next_target))->resdom->restype = UNKNOWNOID;
|
||||
((TargetEntry *) lfirst(prev_target))->resdom->restype = UNKNOWNOID;
|
||||
((TargetEntry *) lfirst(next_target))->resdom->restype = UNKNOWNOID;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -584,26 +600,26 @@ printf("transformUnionClause: types are %d -> %d\n", itype, otype);
|
||||
/* they don't match in type? then convert... */
|
||||
else if (itype != otype)
|
||||
{
|
||||
Node *expr;
|
||||
Node *expr;
|
||||
|
||||
expr = ((TargetEntry *)lfirst(next_target))->expr;
|
||||
expr = ((TargetEntry *) lfirst(next_target))->expr;
|
||||
expr = CoerceTargetExpr(NULL, expr, itype, otype);
|
||||
if (expr == NULL)
|
||||
{
|
||||
elog(ERROR,"Unable to transform %s to %s"
|
||||
elog(ERROR, "Unable to transform %s to %s"
|
||||
"\n\tEach UNION clause must have compatible target types",
|
||||
typeidTypeName(itype),
|
||||
typeidTypeName(otype));
|
||||
}
|
||||
((TargetEntry *)lfirst(next_target))->expr = expr;
|
||||
((TargetEntry *)lfirst(next_target))->resdom->restype = otype;
|
||||
((TargetEntry *) lfirst(next_target))->expr = expr;
|
||||
((TargetEntry *) lfirst(next_target))->resdom->restype = otype;
|
||||
}
|
||||
|
||||
/* both are UNKNOWN? then evaluate as text... */
|
||||
else if (itype == UNKNOWNOID)
|
||||
{
|
||||
((TargetEntry *)lfirst(next_target))->resdom->restype = TEXTOID;
|
||||
((TargetEntry *)lfirst(prev_target))->resdom->restype = TEXTOID;
|
||||
((TargetEntry *) lfirst(next_target))->resdom->restype = TEXTOID;
|
||||
((TargetEntry *) lfirst(prev_target))->resdom->restype = TEXTOID;
|
||||
}
|
||||
prev_target = lnext(prev_target);
|
||||
}
|
||||
@@ -613,4 +629,4 @@ printf("transformUnionClause: types are %d -> %d\n", itype, otype);
|
||||
}
|
||||
else
|
||||
return NIL;
|
||||
} /* transformUnionClause() */
|
||||
} /* transformUnionClause() */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.5 1998/09/01 03:24:11 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.6 1998/09/01 04:30:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -25,8 +25,8 @@
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
Oid DemoteType(Oid inType);
|
||||
Oid PromoteTypeToNext(Oid inType);
|
||||
Oid DemoteType(Oid inType);
|
||||
Oid PromoteTypeToNext(Oid inType);
|
||||
|
||||
|
||||
/* coerce_type()
|
||||
@@ -35,45 +35,57 @@ Oid PromoteTypeToNext(Oid inType);
|
||||
Node *
|
||||
coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId)
|
||||
{
|
||||
Node *result = NULL;
|
||||
Oid infunc;
|
||||
Datum val;
|
||||
Node *result = NULL;
|
||||
Oid infunc;
|
||||
Datum val;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: argument types are %d -> %d\n",
|
||||
inputTypeId, targetTypeId);
|
||||
printf("coerce_type: argument types are %d -> %d\n",
|
||||
inputTypeId, targetTypeId);
|
||||
#endif
|
||||
|
||||
if (targetTypeId == InvalidOid)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: apparent NULL target argument; suppress type conversion\n");
|
||||
printf("coerce_type: apparent NULL target argument; suppress type conversion\n");
|
||||
#endif
|
||||
result = node;
|
||||
}
|
||||
else if (inputTypeId != targetTypeId)
|
||||
{
|
||||
/* one of the known-good transparent conversions? then drop through... */
|
||||
|
||||
/*
|
||||
* one of the known-good transparent conversions? then drop
|
||||
* through...
|
||||
*/
|
||||
if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: argument type %s is known to be convertible to type %s\n",
|
||||
typeidTypeName(inputTypeId), typeidTypeName(targetTypeId));
|
||||
printf("coerce_type: argument type %s is known to be convertible to type %s\n",
|
||||
typeidTypeName(inputTypeId), typeidTypeName(targetTypeId));
|
||||
#endif
|
||||
result = node;
|
||||
}
|
||||
|
||||
/* if not unknown input type, try for explicit conversion using functions... */
|
||||
/*
|
||||
* if not unknown input type, try for explicit conversion using
|
||||
* functions...
|
||||
*/
|
||||
else if (inputTypeId != UNKNOWNOID)
|
||||
{
|
||||
/* We already know there is a function which will do this, so let's use it */
|
||||
FuncCall *n = makeNode(FuncCall);
|
||||
|
||||
/*
|
||||
* We already know there is a function which will do this, so
|
||||
* let's use it
|
||||
*/
|
||||
FuncCall *n = makeNode(FuncCall);
|
||||
|
||||
n->funcname = typeidTypeName(targetTypeId);
|
||||
n->args = lcons(node, NIL);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: construct function %s(%s)\n",
|
||||
typeidTypeName(targetTypeId), typeidTypeName(inputTypeId));
|
||||
printf("coerce_type: construct function %s(%s)\n",
|
||||
typeidTypeName(targetTypeId), typeidTypeName(inputTypeId));
|
||||
#endif
|
||||
|
||||
result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
|
||||
@@ -81,14 +93,14 @@ printf("coerce_type: construct function %s(%s)\n",
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: node is UNKNOWN type\n");
|
||||
printf("coerce_type: node is UNKNOWN type\n");
|
||||
#endif
|
||||
if (nodeTag(node) == T_Const)
|
||||
{
|
||||
Const *con = (Const *) node;
|
||||
if (nodeTag(node) == T_Const)
|
||||
{
|
||||
Const *con = (Const *) node;
|
||||
|
||||
val = (Datum) textout((struct varlena *)
|
||||
con->constvalue);
|
||||
con->constvalue);
|
||||
infunc = typeidInfunc(targetTypeId);
|
||||
con = makeNode(Const);
|
||||
con->consttype = targetTypeId;
|
||||
@@ -97,7 +109,7 @@ printf("coerce_type: node is UNKNOWN type\n");
|
||||
/* use "-1" for varchar() type */
|
||||
con->constvalue = (Datum) fmgr(infunc,
|
||||
val,
|
||||
typeidTypElem(targetTypeId),
|
||||
typeidTypElem(targetTypeId),
|
||||
-1);
|
||||
con->constisnull = false;
|
||||
con->constbyval = true;
|
||||
@@ -107,7 +119,7 @@ printf("coerce_type: node is UNKNOWN type\n");
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: should never get here!\n");
|
||||
printf("coerce_type: should never get here!\n");
|
||||
#endif
|
||||
result = node;
|
||||
}
|
||||
@@ -116,14 +128,14 @@ printf("coerce_type: should never get here!\n");
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("coerce_type: argument type IDs %d match\n", inputTypeId);
|
||||
printf("coerce_type: argument type IDs %d match\n", inputTypeId);
|
||||
#endif
|
||||
|
||||
result = node;
|
||||
}
|
||||
|
||||
return result;
|
||||
} /* coerce_type() */
|
||||
} /* coerce_type() */
|
||||
|
||||
|
||||
/* can_coerce_type()
|
||||
@@ -131,12 +143,12 @@ printf("coerce_type: argument type IDs %d match\n", inputTypeId);
|
||||
*
|
||||
* There are a few types which are known apriori to be convertible.
|
||||
* We will check for those cases first, and then look for possible
|
||||
* conversion functions.
|
||||
* conversion functions.
|
||||
*
|
||||
* Notes:
|
||||
* This uses the same mechanism as the CAST() SQL construct in gram.y.
|
||||
* We should also check the function return type on candidate conversion
|
||||
* routines just to be safe but we do not do that yet...
|
||||
* routines just to be safe but we do not do that yet...
|
||||
* We need to have a zero-filled OID array here, otherwise the cache lookup fails.
|
||||
* - thomas 1998-03-31
|
||||
*/
|
||||
@@ -152,17 +164,21 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: argument #%d types are %d -> %d\n",
|
||||
i, input_typeids[i], func_typeids[i]);
|
||||
printf("can_coerce_type: argument #%d types are %d -> %d\n",
|
||||
i, input_typeids[i], func_typeids[i]);
|
||||
#endif
|
||||
if (input_typeids[i] != func_typeids[i])
|
||||
{
|
||||
/* one of the known-good transparent conversions? then drop through... */
|
||||
|
||||
/*
|
||||
* one of the known-good transparent conversions? then drop
|
||||
* through...
|
||||
*/
|
||||
if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: argument #%d type %s is known to be convertible to type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]), typeidTypeName(func_typeids[i]));
|
||||
printf("can_coerce_type: argument #%d type %s is known to be convertible to type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]), typeidTypeName(func_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -170,7 +186,7 @@ printf("can_coerce_type: argument #%d type %s is known to be convertible to type
|
||||
else if (func_typeids[i] == InvalidOid)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: output OID func_typeids[%d] is zero\n", i);
|
||||
printf("can_coerce_type: output OID func_typeids[%d] is zero\n", i);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -179,37 +195,46 @@ printf("can_coerce_type: output OID func_typeids[%d] is zero\n", i);
|
||||
else if (input_typeids[i] == InvalidOid)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: input OID input_typeids[%d] is zero\n", i);
|
||||
printf("can_coerce_type: input OID input_typeids[%d] is zero\n", i);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if not unknown input type, try for explicit conversion using functions... */
|
||||
/*
|
||||
* if not unknown input type, try for explicit conversion
|
||||
* using functions...
|
||||
*/
|
||||
else if (input_typeids[i] != UNKNOWNOID)
|
||||
{
|
||||
MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
|
||||
oid_array[0] = input_typeids[i];
|
||||
|
||||
/* look for a single-argument function named with the target type name */
|
||||
/*
|
||||
* look for a single-argument function named with the
|
||||
* target type name
|
||||
*/
|
||||
ftup = SearchSysCacheTuple(PRONAME,
|
||||
PointerGetDatum(typeidTypeName(func_typeids[i])),
|
||||
PointerGetDatum(typeidTypeName(func_typeids[i])),
|
||||
Int32GetDatum(1),
|
||||
PointerGetDatum(oid_array),
|
||||
0);
|
||||
|
||||
/* should also check the function return type just to be safe... */
|
||||
/*
|
||||
* should also check the function return type just to be
|
||||
* safe...
|
||||
*/
|
||||
if (HeapTupleIsValid(ftup))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: found function %s(%s) to convert argument #%d\n",
|
||||
typeidTypeName(func_typeids[i]), typeidTypeName(input_typeids[i]), i);
|
||||
printf("can_coerce_type: found function %s(%s) to convert argument #%d\n",
|
||||
typeidTypeName(func_typeids[i]), typeidTypeName(input_typeids[i]), i);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: did not find function %s(%s) to convert argument #%d\n",
|
||||
typeidTypeName(func_typeids[i]), typeidTypeName(input_typeids[i]), i);
|
||||
printf("can_coerce_type: did not find function %s(%s) to convert argument #%d\n",
|
||||
typeidTypeName(func_typeids[i]), typeidTypeName(input_typeids[i]), i);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -217,8 +242,8 @@ printf("can_coerce_type: did not find function %s(%s) to convert argument #%d\n"
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: argument #%d type is %d (UNKNOWN)\n",
|
||||
i, input_typeids[i]);
|
||||
printf("can_coerce_type: argument #%d type is %d (UNKNOWN)\n",
|
||||
i, input_typeids[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -226,28 +251,28 @@ printf("can_coerce_type: argument #%d type is %d (UNKNOWN)\n",
|
||||
if (typeTypeFlag(tp) == 'c')
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: typeTypeFlag for %s is 'c'\n",
|
||||
typeidTypeName(input_typeids[i]));
|
||||
printf("can_coerce_type: typeTypeFlag for %s is 'c'\n",
|
||||
typeidTypeName(input_typeids[i]));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: conversion from %s to %s is possible\n",
|
||||
typeidTypeName(input_typeids[i]), typeidTypeName(func_typeids[i]));
|
||||
printf("can_coerce_type: conversion from %s to %s is possible\n",
|
||||
typeidTypeName(input_typeids[i]), typeidTypeName(func_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("can_coerce_type: argument #%d type IDs %d match\n",
|
||||
i, input_typeids[i]);
|
||||
printf("can_coerce_type: argument #%d type IDs %d match\n",
|
||||
i, input_typeids[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* can_coerce_type() */
|
||||
} /* can_coerce_type() */
|
||||
|
||||
|
||||
/* TypeCategory()
|
||||
@@ -256,7 +281,7 @@ printf("can_coerce_type: argument #%d type IDs %d match\n",
|
||||
CATEGORY
|
||||
TypeCategory(Oid inType)
|
||||
{
|
||||
CATEGORY result;
|
||||
CATEGORY result;
|
||||
|
||||
switch (inType)
|
||||
{
|
||||
@@ -307,7 +332,7 @@ TypeCategory(Oid inType)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} /* TypeCategory() */
|
||||
} /* TypeCategory() */
|
||||
|
||||
|
||||
/* IsPreferredType()
|
||||
@@ -317,7 +342,7 @@ bool
|
||||
IsPreferredType(CATEGORY category, Oid type)
|
||||
{
|
||||
return type == PreferredType(category, type);
|
||||
} /* IsPreferredType() */
|
||||
} /* IsPreferredType() */
|
||||
|
||||
|
||||
/* PreferredType()
|
||||
@@ -326,7 +351,7 @@ IsPreferredType(CATEGORY category, Oid type)
|
||||
Oid
|
||||
PreferredType(CATEGORY category, Oid type)
|
||||
{
|
||||
Oid result;
|
||||
Oid result;
|
||||
|
||||
switch (category)
|
||||
{
|
||||
@@ -363,17 +388,17 @@ PreferredType(CATEGORY category, Oid type)
|
||||
break;
|
||||
}
|
||||
#ifdef PARSEDEBUG
|
||||
printf("PreferredType- (%d) preferred type is %s\n", category, typeidTypeName(result));
|
||||
printf("PreferredType- (%d) preferred type is %s\n", category, typeidTypeName(result));
|
||||
#endif
|
||||
return result;
|
||||
} /* PreferredType() */
|
||||
} /* PreferredType() */
|
||||
|
||||
|
||||
#if FALSE
|
||||
Oid
|
||||
PromoteTypeToNext(Oid inType)
|
||||
{
|
||||
Oid result;
|
||||
Oid result;
|
||||
|
||||
switch (inType)
|
||||
{
|
||||
@@ -418,13 +443,13 @@ PromoteTypeToNext(Oid inType)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} /* PromoteTypeToNext() */
|
||||
} /* PromoteTypeToNext() */
|
||||
|
||||
|
||||
Oid
|
||||
DemoteType(Oid inType)
|
||||
{
|
||||
Oid result;
|
||||
Oid result;
|
||||
|
||||
switch (inType)
|
||||
{
|
||||
@@ -438,13 +463,13 @@ DemoteType(Oid inType)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} /* DemoteType() */
|
||||
} /* DemoteType() */
|
||||
|
||||
|
||||
Oid
|
||||
PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
|
||||
{
|
||||
Oid result;
|
||||
Oid result;
|
||||
|
||||
if (inType1 == inType2)
|
||||
{
|
||||
@@ -471,34 +496,35 @@ PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
|
||||
switch (*arg1)
|
||||
{
|
||||
case (CHAROID):
|
||||
switch (*arg2)
|
||||
{
|
||||
case (BPCHAROID):
|
||||
case (VARCHAROID):
|
||||
case (TEXTOID):
|
||||
switch (*arg2)
|
||||
{
|
||||
case (BPCHAROID):
|
||||
case (VARCHAROID):
|
||||
case (TEXTOID):
|
||||
|
||||
case (INT2OID):
|
||||
case (INT4OID):
|
||||
case (FLOAT4OID):
|
||||
case (FLOAT8OID):
|
||||
case (CASHOID):
|
||||
case (INT2OID):
|
||||
case (INT4OID):
|
||||
case (FLOAT4OID):
|
||||
case (FLOAT8OID):
|
||||
case (CASHOID):
|
||||
|
||||
case (POINTOID):
|
||||
case (LSEGOID):
|
||||
case (LINEOID):
|
||||
case (BOXOID):
|
||||
case (PATHOID):
|
||||
case (CIRCLEOID):
|
||||
case (POLYGONOID):
|
||||
case (POINTOID):
|
||||
case (LSEGOID):
|
||||
case (LINEOID):
|
||||
case (BOXOID):
|
||||
case (PATHOID):
|
||||
case (CIRCLEOID):
|
||||
case (POLYGONOID):
|
||||
|
||||
case (InvalidOid):
|
||||
case (UNKNOWNOID):
|
||||
case (BOOLOID):
|
||||
default:
|
||||
*arg1 = InvalidOid;
|
||||
*arg2 = InvalidOid;
|
||||
result = InvalidOid;
|
||||
}
|
||||
case (InvalidOid):
|
||||
case (UNKNOWNOID):
|
||||
case (BOOLOID):
|
||||
default:
|
||||
*arg1 = InvalidOid;
|
||||
*arg2 = InvalidOid;
|
||||
result = InvalidOid;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isBuiltIn1 && !isBuiltIn2)
|
||||
{
|
||||
@@ -536,31 +562,33 @@ PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
|
||||
case (CHAROID):
|
||||
switch (*arg2)
|
||||
{
|
||||
case (BPCHAROID):
|
||||
case (VARCHAROID):
|
||||
case (TEXTOID):
|
||||
case (BPCHAROID):
|
||||
case (VARCHAROID):
|
||||
case (TEXTOID):
|
||||
|
||||
case (INT2OID):
|
||||
case (INT4OID):
|
||||
case (FLOAT4OID):
|
||||
case (FLOAT8OID):
|
||||
case (CASHOID):
|
||||
case (INT2OID):
|
||||
case (INT4OID):
|
||||
case (FLOAT4OID):
|
||||
case (FLOAT8OID):
|
||||
case (CASHOID):
|
||||
|
||||
case (POINTOID):
|
||||
case (LSEGOID):
|
||||
case (LINEOID):
|
||||
case (BOXOID):
|
||||
case (PATHOID):
|
||||
case (CIRCLEOID):
|
||||
case (POLYGONOID):
|
||||
case (POINTOID):
|
||||
case (LSEGOID):
|
||||
case (LINEOID):
|
||||
case (BOXOID):
|
||||
case (PATHOID):
|
||||
case (CIRCLEOID):
|
||||
case (POLYGONOID):
|
||||
|
||||
case (InvalidOid):
|
||||
case (UNKNOWNOID):
|
||||
case (BOOLOID):
|
||||
default:
|
||||
*arg1 = InvalidOid;
|
||||
*arg2 = InvalidOid;
|
||||
result = InvalidOid;
|
||||
case (InvalidOid):
|
||||
case (UNKNOWNOID):
|
||||
case (BOOLOID):
|
||||
default:
|
||||
*arg1 = InvalidOid;
|
||||
*arg2 = InvalidOid;
|
||||
result = InvalidOid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.33 1998/09/01 03:24:12 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.34 1998/09/01 04:30:30 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -264,11 +264,11 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
if (length(left_expr) !=
|
||||
length(right_expr))
|
||||
elog(ERROR, "parser: Subselect has too many or too few fields.");
|
||||
|
||||
if (length(left_expr) > 1 &&
|
||||
strcmp (op, "=") != 0 && strcmp (op, "<>") != 0)
|
||||
|
||||
if (length(left_expr) > 1 &&
|
||||
strcmp(op, "=") != 0 && strcmp(op, "<>") != 0)
|
||||
elog(ERROR, "parser: '%s' is not relational operator", op);
|
||||
|
||||
|
||||
sublink->oper = NIL;
|
||||
foreach(elist, left_expr)
|
||||
{
|
||||
@@ -301,10 +301,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
||||
}
|
||||
|
||||
/* Some nodes do _not_ come from the original parse tree,
|
||||
* but result from parser transformation in this phase.
|
||||
* but result from parser transformation in this phase.
|
||||
* At least one construct (BETWEEN/AND) puts the same nodes
|
||||
* into two branches of the parse tree; hence, some nodes
|
||||
* are transformed twice.
|
||||
* into two branches of the parse tree; hence, some nodes
|
||||
* are transformed twice.
|
||||
* The three cases below come from transforming function calls.
|
||||
* Let's try just passing them through...
|
||||
* - thomas 1998-03-14
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.27 1998/09/01 03:24:13 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.28 1998/09/01 04:30:31 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,8 +45,7 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static Node *
|
||||
ParseComplexProjection(ParseState *pstate,
|
||||
static Node *ParseComplexProjection(ParseState *pstate,
|
||||
char *funcname,
|
||||
Node *first_arg,
|
||||
bool *attisset);
|
||||
@@ -64,14 +63,12 @@ func_get_detail(char *funcname,
|
||||
Oid **true_typeids);
|
||||
static Oid funcid_get_rettype(Oid funcid);
|
||||
static Oid **gen_cross_product(InhPaths *arginh, int nargs);
|
||||
static void
|
||||
make_arguments(ParseState *pstate,
|
||||
static void make_arguments(ParseState *pstate,
|
||||
int nargs,
|
||||
List *fargs,
|
||||
Oid *input_typeids,
|
||||
Oid *function_typeids);
|
||||
static int
|
||||
match_argtypes(int nargs,
|
||||
static int match_argtypes(int nargs,
|
||||
Oid *input_typeids,
|
||||
CandidateList function_typeids,
|
||||
CandidateList *candidates);
|
||||
@@ -270,23 +267,24 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
fargs, precedence);
|
||||
|
||||
/*
|
||||
* See if this is a single argument function with the function name
|
||||
* also a type name and the input argument and type name binary compatible...
|
||||
* See if this is a single argument function with the function
|
||||
* name also a type name and the input argument and type name
|
||||
* binary compatible...
|
||||
*/
|
||||
if ((HeapTupleIsValid(tp = SearchSysCacheTuple(TYPNAME,
|
||||
PointerGetDatum(funcname),
|
||||
PointerGetDatum(funcname),
|
||||
0, 0, 0)))
|
||||
&& IS_BINARY_COMPATIBLE(typeTypeId(tp), basetype))
|
||||
return((Node *)lfirst(fargs));
|
||||
&& IS_BINARY_COMPATIBLE(typeTypeId(tp), basetype))
|
||||
return ((Node *) lfirst(fargs));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we dropped through to here it's really a function (or a set,
|
||||
* which is implemented as a function).
|
||||
* Extract arg type info and transform relation name arguments
|
||||
* into varnodes of the appropriate form.
|
||||
* which is implemented as a function). Extract arg type info and
|
||||
* transform relation name arguments into varnodes of the appropriate
|
||||
* form.
|
||||
*/
|
||||
MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
|
||||
|
||||
@@ -372,7 +370,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
}
|
||||
else
|
||||
{
|
||||
bool exists;
|
||||
bool exists;
|
||||
|
||||
exists = func_get_detail(funcname, nargs, oid_array, &funcid,
|
||||
&rettype, &retset, &true_oid_array);
|
||||
@@ -446,8 +444,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
seqrel = textout(seqname);
|
||||
|
||||
if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
|
||||
(((funcid == F_NEXTVAL) || (funcid == F_SETVAL)) ?
|
||||
ACL_WR : ACL_RD)))
|
||||
(((funcid == F_NEXTVAL) || (funcid == F_SETVAL)) ?
|
||||
ACL_WR : ACL_RD)))
|
||||
!= ACLCHECK_OK)
|
||||
elog(ERROR, "%s.%s: %s",
|
||||
seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
|
||||
@@ -544,7 +542,7 @@ func_get_candidates(char *funcname, int nargs)
|
||||
{
|
||||
ItemPointer iptr;
|
||||
Buffer buffer;
|
||||
|
||||
|
||||
iptr = &indexRes->heap_iptr;
|
||||
tuple = heap_fetch(heapRelation, SnapshotNow, iptr, &buffer);
|
||||
pfree(indexRes);
|
||||
@@ -614,7 +612,7 @@ match_argtypes(int nargs,
|
||||
}
|
||||
|
||||
return ncandidates;
|
||||
} /* match_argtypes() */
|
||||
} /* match_argtypes() */
|
||||
|
||||
|
||||
/* func_select_candidate()
|
||||
@@ -633,24 +631,24 @@ func_select_candidate(int nargs,
|
||||
Oid *input_typeids,
|
||||
CandidateList candidates)
|
||||
{
|
||||
CandidateList current_candidate;
|
||||
CandidateList last_candidate;
|
||||
Oid *current_typeids;
|
||||
int i;
|
||||
CandidateList current_candidate;
|
||||
CandidateList last_candidate;
|
||||
Oid *current_typeids;
|
||||
int i;
|
||||
|
||||
int ncandidates;
|
||||
int nbestMatch,
|
||||
nmatch,
|
||||
nident;
|
||||
int ncandidates;
|
||||
int nbestMatch,
|
||||
nmatch,
|
||||
nident;
|
||||
|
||||
CATEGORY slot_category,
|
||||
current_category;
|
||||
Oid slot_type,
|
||||
current_type;
|
||||
CATEGORY slot_category,
|
||||
current_category;
|
||||
Oid slot_type,
|
||||
current_type;
|
||||
|
||||
/*
|
||||
* Run through all candidates and keep those with the most matches
|
||||
* on explicit types. Keep all candidates if none match.
|
||||
* on explicit types. Keep all candidates if none match.
|
||||
*/
|
||||
ncandidates = 0;
|
||||
nbestMatch = 0;
|
||||
@@ -665,7 +663,7 @@ func_select_candidate(int nargs,
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if ((input_typeids[i] != UNKNOWNOID)
|
||||
&& (current_typeids[i] == input_typeids[i]))
|
||||
&& (current_typeids[i] == input_typeids[i]))
|
||||
nmatch++;
|
||||
else if (IS_BINARY_COMPATIBLE(current_typeids[i], input_typeids[i]))
|
||||
nident++;
|
||||
@@ -675,7 +673,7 @@ func_select_candidate(int nargs,
|
||||
return current_candidate->args;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- candidate has %d matches\n", nmatch);
|
||||
printf("func_select_candidate- candidate has %d matches\n", nmatch);
|
||||
#endif
|
||||
if ((nmatch > nbestMatch) || (last_candidate == NULL))
|
||||
{
|
||||
@@ -684,7 +682,7 @@ printf("func_select_candidate- candidate has %d matches\n", nmatch);
|
||||
last_candidate = current_candidate;
|
||||
ncandidates = 1;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- choose candidate as best match\n");
|
||||
printf("func_select_candidate- choose candidate as best match\n");
|
||||
#endif
|
||||
}
|
||||
else if (nmatch == nbestMatch)
|
||||
@@ -693,14 +691,14 @@ printf("func_select_candidate- choose candidate as best match\n");
|
||||
last_candidate = current_candidate;
|
||||
ncandidates++;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- choose candidate as possible match\n");
|
||||
printf("func_select_candidate- choose candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
last_candidate->next = NULL;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- reject candidate as possible match\n");
|
||||
printf("func_select_candidate- reject candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -730,15 +728,15 @@ printf("func_select_candidate- reject candidate as possible match\n");
|
||||
slot_category = current_category;
|
||||
slot_type = current_type;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- assign column #%d first candidate slot type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
printf("func_select_candidate- assign column #%d first candidate slot type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
#endif
|
||||
}
|
||||
else if ((current_category != slot_category)
|
||||
&& IS_BUILTIN_TYPE(current_type))
|
||||
&& IS_BUILTIN_TYPE(current_type))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- multiple possible types for column #%d; unable to choose candidate\n", i);
|
||||
printf("func_select_candidate- multiple possible types for column #%d; unable to choose candidate\n", i);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
@@ -749,15 +747,15 @@ printf("func_select_candidate- multiple possible types for column #%d; unable to
|
||||
slot_type = current_type;
|
||||
candidates = current_candidate;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- column #%d found preferred candidate type %s\n",
|
||||
i, typeidTypeName(slot_type));
|
||||
printf("func_select_candidate- column #%d found preferred candidate type %s\n",
|
||||
i, typeidTypeName(slot_type));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- column #%d found possible candidate type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
printf("func_select_candidate- column #%d found possible candidate type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -767,16 +765,16 @@ printf("func_select_candidate- column #%d found possible candidate type %s\n",
|
||||
{
|
||||
input_typeids[i] = slot_type;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- assign column #%d slot type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
printf("func_select_candidate- assign column #%d slot type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("func_select_candidate- column #%d input type is %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
printf("func_select_candidate- column #%d input type is %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -792,36 +790,36 @@ printf("func_select_candidate- column #%d input type is %s\n",
|
||||
return candidates->args;
|
||||
|
||||
return NULL;
|
||||
} /* func_select_candidate() */
|
||||
} /* func_select_candidate() */
|
||||
|
||||
|
||||
/* func_get_detail()
|
||||
* Find the named function in the system catalogs.
|
||||
*
|
||||
* Attempt to find the named function in the system catalogs with
|
||||
* arguments exactly as specified, so that the normal case
|
||||
* (exact match) is as quick as possible.
|
||||
* arguments exactly as specified, so that the normal case
|
||||
* (exact match) is as quick as possible.
|
||||
*
|
||||
* If an exact match isn't found:
|
||||
* 1) get a vector of all possible input arg type arrays constructed
|
||||
* from the superclasses of the original input arg types
|
||||
* 2) get a list of all possible argument type arrays to the function
|
||||
* with given name and number of arguments
|
||||
* 3) for each input arg type array from vector #1:
|
||||
* a) find how many of the function arg type arrays from list #2
|
||||
* it can be coerced to
|
||||
* b) if the answer is one, we have our function
|
||||
* c) if the answer is more than one, attempt to resolve the conflict
|
||||
* d) if the answer is zero, try the next array from vector #1
|
||||
* 1) get a vector of all possible input arg type arrays constructed
|
||||
* from the superclasses of the original input arg types
|
||||
* 2) get a list of all possible argument type arrays to the function
|
||||
* with given name and number of arguments
|
||||
* 3) for each input arg type array from vector #1:
|
||||
* a) find how many of the function arg type arrays from list #2
|
||||
* it can be coerced to
|
||||
* b) if the answer is one, we have our function
|
||||
* c) if the answer is more than one, attempt to resolve the conflict
|
||||
* d) if the answer is zero, try the next array from vector #1
|
||||
*/
|
||||
static bool
|
||||
func_get_detail(char *funcname,
|
||||
int nargs,
|
||||
Oid *oid_array,
|
||||
Oid *funcid, /* return value */
|
||||
Oid *rettype, /* return value */
|
||||
bool *retset, /* return value */
|
||||
Oid **true_typeids) /* return value */
|
||||
Oid *funcid, /* return value */
|
||||
Oid *rettype, /* return value */
|
||||
bool *retset, /* return value */
|
||||
Oid **true_typeids) /* return value */
|
||||
{
|
||||
Oid **input_typeid_vector;
|
||||
Oid *current_input_typeids;
|
||||
@@ -864,33 +862,36 @@ func_get_detail(char *funcname,
|
||||
ftup = SearchSysCacheTuple(PRONAME,
|
||||
PointerGetDatum(funcname),
|
||||
Int32GetDatum(nargs),
|
||||
PointerGetDatum(*true_typeids),
|
||||
PointerGetDatum(*true_typeids),
|
||||
0);
|
||||
Assert(HeapTupleIsValid(ftup));
|
||||
}
|
||||
|
||||
/* multiple candidates? then better decide or throw an error... */
|
||||
/*
|
||||
* multiple candidates? then better decide or throw an
|
||||
* error...
|
||||
*/
|
||||
else if (ncandidates > 1)
|
||||
{
|
||||
*true_typeids = func_select_candidate(nargs,
|
||||
current_input_typeids,
|
||||
current_function_typeids);
|
||||
current_input_typeids,
|
||||
current_function_typeids);
|
||||
|
||||
/* couldn't decide, so quit */
|
||||
if (*true_typeids == NULL)
|
||||
{
|
||||
func_error(NULL, funcname, nargs, oid_array,
|
||||
"There is more than one function that satisfies the given argument types"
|
||||
"\n\tYou will have to retype your query using explicit typecasts");
|
||||
"There is more than one function that satisfies the given argument types"
|
||||
"\n\tYou will have to retype your query using explicit typecasts");
|
||||
}
|
||||
|
||||
/* found something, so use the first one... */
|
||||
else
|
||||
{
|
||||
ftup = SearchSysCacheTuple(PRONAME,
|
||||
PointerGetDatum(funcname),
|
||||
PointerGetDatum(funcname),
|
||||
Int32GetDatum(nargs),
|
||||
PointerGetDatum(*true_typeids),
|
||||
PointerGetDatum(*true_typeids),
|
||||
0);
|
||||
Assert(HeapTupleIsValid(ftup));
|
||||
}
|
||||
@@ -1155,16 +1156,16 @@ gen_cross_product(InhPaths *arginh, int nargs)
|
||||
|
||||
/* make_arguments()
|
||||
* Given the number and types of arguments to a function, and the
|
||||
* actual arguments and argument types, do the necessary typecasting.
|
||||
* actual arguments and argument types, do the necessary typecasting.
|
||||
*
|
||||
* There are two ways an input typeid can differ from a function typeid:
|
||||
* 1) the input type inherits the function type, so no typecasting required
|
||||
* 2) the input type can be typecast into the function type
|
||||
* 1) the input type inherits the function type, so no typecasting required
|
||||
* 2) the input type can be typecast into the function type
|
||||
* Right now, we only typecast unknowns, and that is all we check for.
|
||||
*
|
||||
* func_get_detail() now can find coersions for function arguments which
|
||||
* will make this function executable. So, we need to recover these
|
||||
* results here too.
|
||||
* will make this function executable. So, we need to recover these
|
||||
* results here too.
|
||||
* - thomas 1998-03-25
|
||||
*/
|
||||
static void
|
||||
@@ -1181,7 +1182,11 @@ make_arguments(ParseState *pstate,
|
||||
i < nargs;
|
||||
i++, current_fargs = lnext(current_fargs))
|
||||
{
|
||||
/* unspecified type for string constant? then use heuristics for conversion... */
|
||||
|
||||
/*
|
||||
* unspecified type for string constant? then use heuristics for
|
||||
* conversion...
|
||||
*/
|
||||
if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
|
||||
{
|
||||
lfirst(current_fargs) =
|
||||
@@ -1222,7 +1227,7 @@ setup_tlist(char *attname, Oid relid)
|
||||
attno = get_attnum(relid, attname);
|
||||
if (attno < 0)
|
||||
elog(ERROR, "Cannot reference attribute '%s'"
|
||||
" of tuple params/return values for functions", attname);
|
||||
" of tuple params/return values for functions", attname);
|
||||
|
||||
typeid = get_atttype(relid, attno);
|
||||
type_mod = get_atttypmod(relid, attno);
|
||||
@@ -1454,11 +1459,11 @@ func_error(char *caller, char *funcname, int nargs, Oid *argtypes, char *msg)
|
||||
if (caller == NULL)
|
||||
{
|
||||
elog(ERROR, "Function '%s(%s)' does not exist%s%s",
|
||||
funcname, p, ((msg != NULL)? "\n\t": ""), ((msg != NULL)? msg: ""));
|
||||
funcname, p, ((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "%s: function '%s(%s)' does not exist%s%s",
|
||||
caller, funcname, p, ((msg != NULL)? "\n\t": ""), ((msg != NULL)? msg: ""));
|
||||
caller, funcname, p, ((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.20 1998/09/01 03:24:15 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.21 1998/09/01 04:30:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -31,8 +31,7 @@
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
static void disallow_setop(char *op, Type optype, Node *operand);
|
||||
static Node *
|
||||
make_operand(char *opname,
|
||||
static Node *make_operand(char *opname,
|
||||
Node *tree,
|
||||
Oid orig_typeId,
|
||||
Oid true_typeId);
|
||||
@@ -69,8 +68,8 @@ make_operand(char *opname,
|
||||
Type true_type;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_operand: constructing operand for '%s' %s->%s\n",
|
||||
opname, typeidTypeName(orig_typeId), typeidTypeName(true_typeId));
|
||||
printf("make_operand: constructing operand for '%s' %s->%s\n",
|
||||
opname, typeidTypeName(orig_typeId), typeidTypeName(true_typeId));
|
||||
#endif
|
||||
if (tree != NULL)
|
||||
{
|
||||
@@ -82,8 +81,8 @@ printf("make_operand: constructing operand for '%s' %s->%s\n",
|
||||
if (true_typeId != orig_typeId)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_operand: try to convert node from %s to %s\n",
|
||||
typeidTypeName(orig_typeId), typeidTypeName(true_typeId));
|
||||
printf("make_operand: try to convert node from %s to %s\n",
|
||||
typeidTypeName(orig_typeId), typeidTypeName(true_typeId));
|
||||
#endif
|
||||
result = coerce_type(NULL, tree, orig_typeId, true_typeId);
|
||||
}
|
||||
@@ -104,7 +103,7 @@ printf("make_operand: try to convert node from %s to %s\n",
|
||||
}
|
||||
|
||||
return result;
|
||||
} /* make_operand() */
|
||||
} /* make_operand() */
|
||||
|
||||
|
||||
static void
|
||||
@@ -157,11 +156,11 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
||||
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
||||
tup = left_oper(opname, rtypeId);
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_op: returned from left_oper() with structure at %p\n", (void *)tup);
|
||||
printf("make_op: returned from left_oper() with structure at %p\n", (void *) tup);
|
||||
#endif
|
||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_op: calling make_operand()\n");
|
||||
printf("make_op: calling make_operand()\n");
|
||||
#endif
|
||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
||||
left = NULL;
|
||||
@@ -192,9 +191,9 @@ printf("make_op: calling make_operand()\n");
|
||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
||||
}
|
||||
|
||||
newop = makeOper(oprid(tup), /* opno */
|
||||
InvalidOid, /* opid */
|
||||
opform->oprresult, /* operator result type */
|
||||
newop = makeOper(oprid(tup),/* opno */
|
||||
InvalidOid,/* opid */
|
||||
opform->oprresult, /* operator result type */
|
||||
0,
|
||||
NULL);
|
||||
|
||||
@@ -211,7 +210,7 @@ printf("make_op: calling make_operand()\n");
|
||||
result->args = lcons(left, lcons(right, NIL));
|
||||
|
||||
return result;
|
||||
} /* make_op() */
|
||||
} /* make_op() */
|
||||
|
||||
|
||||
Var *
|
||||
@@ -284,7 +283,7 @@ make_array_ref(Node *expr,
|
||||
|
||||
/* get the type tuple for the element type */
|
||||
type_tuple = SearchSysCacheTuple(TYPOID,
|
||||
ObjectIdGetDatum(type_struct_array->typelem),
|
||||
ObjectIdGetDatum(type_struct_array->typelem),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(type_tuple))
|
||||
elog(ERROR, "make_array_ref: Cache lookup failed for type %d\n",
|
||||
@@ -365,7 +364,7 @@ make_array_set(Expr *target_expr,
|
||||
type_struct_array->typname);
|
||||
/* get the type tuple for the element type */
|
||||
type_tuple = SearchSysCacheTuple(TYPOID,
|
||||
ObjectIdGetDatum(type_struct_array->typelem),
|
||||
ObjectIdGetDatum(type_struct_array->typelem),
|
||||
0, 0, 0);
|
||||
|
||||
if (!HeapTupleIsValid(type_tuple))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.16 1998/09/01 03:24:16 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.17 1998/09/01 04:30:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -29,19 +29,17 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
Oid *
|
||||
oper_select_candidate(int nargs, Oid *input_typeids, CandidateList candidates);
|
||||
static int
|
||||
binary_oper_get_candidates(char *opname,
|
||||
oper_select_candidate(int nargs, Oid *input_typeids, CandidateList candidates);
|
||||
static int binary_oper_get_candidates(char *opname,
|
||||
Oid leftTypeId,
|
||||
Oid rightTypeId,
|
||||
CandidateList *candidates);
|
||||
static int
|
||||
unary_oper_get_candidates(char *op,
|
||||
static int unary_oper_get_candidates(char *op,
|
||||
Oid typeId,
|
||||
CandidateList *candidates,
|
||||
char rightleft);
|
||||
static void
|
||||
op_error(char *op, Oid arg1, Oid arg2);
|
||||
op_error(char *op, Oid arg1, Oid arg2);
|
||||
|
||||
Oid
|
||||
any_ordering_op(int restype)
|
||||
@@ -53,8 +51,8 @@ any_ordering_op(int restype)
|
||||
if (!HeapTupleIsValid(order_op))
|
||||
{
|
||||
elog(ERROR, "Unable to find an ordering operator '%s' for type %s."
|
||||
"\n\tUse an explicit ordering operator or modify the query.",
|
||||
"<", typeidTypeName(restype));
|
||||
"\n\tUse an explicit ordering operator or modify the query.",
|
||||
"<", typeidTypeName(restype));
|
||||
}
|
||||
order_opid = oprid(order_op);
|
||||
|
||||
@@ -107,7 +105,7 @@ binary_oper_get_candidates(char *opname,
|
||||
pg_operator_desc = heap_openr(OperatorRelationName);
|
||||
pg_operator_scan = heap_beginscan(pg_operator_desc,
|
||||
0,
|
||||
SnapshotSelf, /* ??? */
|
||||
SnapshotSelf, /* ??? */
|
||||
nkeys,
|
||||
opKey);
|
||||
|
||||
@@ -128,7 +126,7 @@ binary_oper_get_candidates(char *opname,
|
||||
heap_close(pg_operator_desc);
|
||||
|
||||
return ncandidates;
|
||||
} /* binary_oper_get_candidates() */
|
||||
} /* binary_oper_get_candidates() */
|
||||
|
||||
|
||||
/* oper_select_candidate()
|
||||
@@ -179,24 +177,24 @@ oper_select_candidate(int nargs,
|
||||
Oid *input_typeids,
|
||||
CandidateList candidates)
|
||||
{
|
||||
CandidateList current_candidate;
|
||||
CandidateList last_candidate;
|
||||
Oid *current_typeids;
|
||||
int unknownOids;
|
||||
int i;
|
||||
CandidateList current_candidate;
|
||||
CandidateList last_candidate;
|
||||
Oid *current_typeids;
|
||||
int unknownOids;
|
||||
int i;
|
||||
|
||||
int ncandidates;
|
||||
int nbestMatch,
|
||||
nmatch;
|
||||
int ncandidates;
|
||||
int nbestMatch,
|
||||
nmatch;
|
||||
|
||||
CATEGORY slot_category,
|
||||
current_category;
|
||||
Oid slot_type,
|
||||
current_type;
|
||||
CATEGORY slot_category,
|
||||
current_category;
|
||||
Oid slot_type,
|
||||
current_type;
|
||||
|
||||
/*
|
||||
* Run through all candidates and keep those with the most matches
|
||||
* on explicit types. Keep all candidates if none match.
|
||||
* on explicit types. Keep all candidates if none match.
|
||||
*/
|
||||
ncandidates = 0;
|
||||
nbestMatch = 0;
|
||||
@@ -210,12 +208,12 @@ oper_select_candidate(int nargs,
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if ((input_typeids[i] != UNKNOWNOID)
|
||||
&& (current_typeids[i] == input_typeids[i]))
|
||||
&& (current_typeids[i] == input_typeids[i]))
|
||||
nmatch++;
|
||||
}
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
#endif
|
||||
if ((nmatch > nbestMatch) || (last_candidate == NULL))
|
||||
{
|
||||
@@ -224,7 +222,7 @@ printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
last_candidate = current_candidate;
|
||||
ncandidates = 1;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- choose candidate as best match\n");
|
||||
printf("oper_select_candidate- choose candidate as best match\n");
|
||||
#endif
|
||||
}
|
||||
else if (nmatch == nbestMatch)
|
||||
@@ -233,14 +231,14 @@ printf("oper_select_candidate- choose candidate as best match\n");
|
||||
last_candidate = current_candidate;
|
||||
ncandidates++;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- choose candidate as possible match\n");
|
||||
printf("oper_select_candidate- choose candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
last_candidate->next = NULL;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -250,7 +248,7 @@ printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])
|
||||
|| !can_coerce_type(1, &input_typeids[1], &candidates->args[1]))
|
||||
ncandidates = 0;
|
||||
return (ncandidates == 1)? candidates->args: NULL;
|
||||
return (ncandidates == 1) ? candidates->args : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -275,13 +273,13 @@ printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
if (current_typeids[i] == input_typeids[i])
|
||||
nmatch++;
|
||||
else if (IsPreferredType(current_category, current_typeids[i])
|
||||
&& can_coerce_type(1, &input_typeids[i], ¤t_typeids[i]))
|
||||
&& can_coerce_type(1, &input_typeids[i], ¤t_typeids[i]))
|
||||
nmatch++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
#endif
|
||||
if ((nmatch > nbestMatch) || (last_candidate == NULL))
|
||||
{
|
||||
@@ -290,7 +288,7 @@ printf("oper_select_candidate- candidate has %d matches\n", nmatch);
|
||||
last_candidate = current_candidate;
|
||||
ncandidates = 1;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- choose candidate as best match\n");
|
||||
printf("oper_select_candidate- choose candidate as best match\n");
|
||||
#endif
|
||||
}
|
||||
else if (nmatch == nbestMatch)
|
||||
@@ -299,14 +297,14 @@ printf("oper_select_candidate- choose candidate as best match\n");
|
||||
last_candidate = current_candidate;
|
||||
ncandidates++;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- choose candidate as possible match\n");
|
||||
printf("oper_select_candidate- choose candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
last_candidate->next = NULL;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -318,10 +316,10 @@ printf("oper_select_candidate- reject candidate as possible match\n");
|
||||
{
|
||||
ncandidates = 0;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- unable to coerce preferred candidate\n");
|
||||
printf("oper_select_candidate- unable to coerce preferred candidate\n");
|
||||
#endif
|
||||
}
|
||||
return (ncandidates == 1)? candidates->args: NULL;
|
||||
return (ncandidates == 1) ? candidates->args : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -333,7 +331,7 @@ printf("oper_select_candidate- unable to coerce preferred candidate\n");
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if ((input_typeids[i] != UNKNOWNOID)
|
||||
&& (input_typeids[i] != InvalidOid))
|
||||
&& (input_typeids[i] != InvalidOid))
|
||||
current_type = input_typeids[i];
|
||||
else
|
||||
unknownOids = TRUE;
|
||||
@@ -350,7 +348,7 @@ printf("oper_select_candidate- unable to coerce preferred candidate\n");
|
||||
{
|
||||
current_typeids = current_candidate->args;
|
||||
if ((current_type == current_typeids[i])
|
||||
|| IS_BINARY_COMPATIBLE(current_type, current_typeids[i]))
|
||||
|| IS_BINARY_COMPATIBLE(current_type, current_typeids[i]))
|
||||
nmatch++;
|
||||
}
|
||||
if (nmatch == nargs)
|
||||
@@ -376,14 +374,14 @@ printf("oper_select_candidate- unable to coerce preferred candidate\n");
|
||||
slot_category = current_category;
|
||||
slot_type = current_type;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- assign column #%d first candidate slot type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
printf("oper_select_candidate- assign column #%d first candidate slot type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
#endif
|
||||
}
|
||||
else if (current_category != slot_category)
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- multiple possible types for column #%d; unable to choose candidate\n", i);
|
||||
printf("oper_select_candidate- multiple possible types for column #%d; unable to choose candidate\n", i);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
@@ -394,15 +392,15 @@ printf("oper_select_candidate- multiple possible types for column #%d; unable to
|
||||
slot_type = current_type;
|
||||
candidates = current_candidate;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- column #%d found preferred candidate type %s\n",
|
||||
i, typeidTypeName(slot_type));
|
||||
printf("oper_select_candidate- column #%d found preferred candidate type %s\n",
|
||||
i, typeidTypeName(slot_type));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- column #%d found possible candidate type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
printf("oper_select_candidate- column #%d found possible candidate type %s\n",
|
||||
i, typeidTypeName(current_type));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -412,16 +410,16 @@ printf("oper_select_candidate- column #%d found possible candidate type %s\n",
|
||||
{
|
||||
input_typeids[i] = slot_type;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- assign column #%d slot type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
printf("oper_select_candidate- assign column #%d slot type %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("oper_select_candidate- column #%d input type is %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
printf("oper_select_candidate- column #%d input type is %s\n",
|
||||
i, typeidTypeName(input_typeids[i]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -432,12 +430,12 @@ printf("oper_select_candidate- column #%d input type is %s\n",
|
||||
current_candidate = current_candidate->next)
|
||||
{
|
||||
if (can_coerce_type(1, &input_typeids[0], ¤t_candidate->args[0])
|
||||
&& can_coerce_type(1, &input_typeids[1], ¤t_candidate->args[1]))
|
||||
&& can_coerce_type(1, &input_typeids[1], ¤t_candidate->args[1]))
|
||||
ncandidates++;
|
||||
}
|
||||
|
||||
return (ncandidates == 1)? candidates->args: NULL;
|
||||
} /* oper_select_candidate() */
|
||||
return (ncandidates == 1) ? candidates->args : NULL;
|
||||
} /* oper_select_candidate() */
|
||||
|
||||
|
||||
/* oper_exact()
|
||||
@@ -452,8 +450,10 @@ oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarn
|
||||
Node *tree;
|
||||
|
||||
/* Unspecified type for one of the arguments? then use the other */
|
||||
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid)) arg1 = arg2;
|
||||
else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid)) arg2 = arg1;
|
||||
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
|
||||
arg1 = arg2;
|
||||
else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
|
||||
arg2 = arg1;
|
||||
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
@@ -461,7 +461,10 @@ oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarn
|
||||
ObjectIdGetDatum(arg2),
|
||||
CharGetDatum('b'));
|
||||
|
||||
/* Did not find anything? then try flipping arguments on a commutative operator... */
|
||||
/*
|
||||
* Did not find anything? then try flipping arguments on a commutative
|
||||
* operator...
|
||||
*/
|
||||
if (!HeapTupleIsValid(tup) && (arg1 != arg2))
|
||||
{
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
@@ -475,13 +478,13 @@ oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarn
|
||||
Form_pg_operator opform;
|
||||
|
||||
#if PARSEDEBUG
|
||||
printf("oper_exact: found possible commutative operator candidate\n");
|
||||
printf("oper_exact: found possible commutative operator candidate\n");
|
||||
#endif
|
||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||
if (opform->oprcom == tup->t_oid)
|
||||
{
|
||||
#if PARSEDEBUG
|
||||
printf("oper_exact: commutative operator found\n");
|
||||
printf("oper_exact: commutative operator found\n");
|
||||
#endif
|
||||
if ((ltree != NULL) && (rtree != NULL))
|
||||
{
|
||||
@@ -499,7 +502,7 @@ printf("oper_exact: commutative operator found\n");
|
||||
}
|
||||
|
||||
return tup;
|
||||
} /* oper_exact() */
|
||||
} /* oper_exact() */
|
||||
|
||||
|
||||
/* oper_inexact()
|
||||
@@ -510,11 +513,11 @@ printf("oper_exact: commutative operator found\n");
|
||||
Operator
|
||||
oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings)
|
||||
{
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOids;
|
||||
Oid inputOids[2];
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOids;
|
||||
Oid inputOids[2];
|
||||
|
||||
/* Unspecified type for one of the arguments? then use the other */
|
||||
if (arg2 == InvalidOid)
|
||||
@@ -543,7 +546,7 @@ oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWa
|
||||
Assert(HeapTupleIsValid(tup));
|
||||
|
||||
#if PARSEDEBUG
|
||||
printf("oper_inexact: found single candidate\n");
|
||||
printf("oper_inexact: found single candidate\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -557,7 +560,7 @@ printf("oper_inexact: found single candidate\n");
|
||||
if (targetOids != NULL)
|
||||
{
|
||||
#if PARSEDEBUG
|
||||
printf("oper_inexact: found candidate\n");
|
||||
printf("oper_inexact: found candidate\n");
|
||||
#endif
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
@@ -574,14 +577,14 @@ printf("oper_inexact: found candidate\n");
|
||||
if (!noWarnings)
|
||||
{
|
||||
elog(ERROR, "There is more than one possible operator '%s' for types '%s' and '%s'"
|
||||
"\n\tYou will have to retype this query using an explicit cast",
|
||||
op, typeTypeName(typeidType(arg1)), typeTypeName(typeidType(arg2)));
|
||||
"\n\tYou will have to retype this query using an explicit cast",
|
||||
op, typeTypeName(typeidType(arg1)), typeTypeName(typeidType(arg2)));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (Operator) tup;
|
||||
} /* oper_inexact() */
|
||||
} /* oper_inexact() */
|
||||
|
||||
|
||||
/* oper()
|
||||
@@ -592,7 +595,7 @@ printf("oper_inexact: found candidate\n");
|
||||
Operator
|
||||
oper(char *opname, Oid ltypeId, Oid rtypeId, bool noWarnings)
|
||||
{
|
||||
HeapTuple tup;
|
||||
HeapTuple tup;
|
||||
|
||||
/* check for exact match on this operator... */
|
||||
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, NULL, NULL, TRUE)))
|
||||
@@ -609,7 +612,7 @@ oper(char *opname, Oid ltypeId, Oid rtypeId, bool noWarnings)
|
||||
}
|
||||
|
||||
return (Operator) tup;
|
||||
} /* oper() */
|
||||
} /* oper() */
|
||||
|
||||
|
||||
/* unary_oper_get_candidates()
|
||||
@@ -642,12 +645,12 @@ unary_oper_get_candidates(char *op,
|
||||
opKey[1].sk_argument = CharGetDatum(rightleft);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("unary_oper_get_candidates: start scan for '%s'\n", op);
|
||||
printf("unary_oper_get_candidates: start scan for '%s'\n", op);
|
||||
#endif
|
||||
pg_operator_desc = heap_openr(OperatorRelationName);
|
||||
pg_operator_scan = heap_beginscan(pg_operator_desc,
|
||||
0,
|
||||
SnapshotSelf, /* ??? */
|
||||
SnapshotSelf, /* ??? */
|
||||
2,
|
||||
opKey);
|
||||
|
||||
@@ -664,8 +667,8 @@ printf("unary_oper_get_candidates: start scan for '%s'\n", op);
|
||||
current_candidate->next = *candidates;
|
||||
*candidates = current_candidate;
|
||||
#ifdef PARSEDEBUG
|
||||
printf("unary_oper_get_candidates: found candidate '%s' for type %s\n",
|
||||
op, typeidTypeName(current_candidate->args[0]));
|
||||
printf("unary_oper_get_candidates: found candidate '%s' for type %s\n",
|
||||
op, typeidTypeName(current_candidate->args[0]));
|
||||
#endif
|
||||
ncandidates++;
|
||||
}
|
||||
@@ -674,10 +677,10 @@ printf("unary_oper_get_candidates: found candidate '%s' for type %s\n",
|
||||
heap_close(pg_operator_desc);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("unary_oper_get_candidates: found %d candidates\n", ncandidates);
|
||||
printf("unary_oper_get_candidates: found %d candidates\n", ncandidates);
|
||||
#endif
|
||||
return ncandidates;
|
||||
} /* unary_oper_get_candidates() */
|
||||
} /* unary_oper_get_candidates() */
|
||||
|
||||
|
||||
/* Given unary right-side operator (operator on right), return oper struct */
|
||||
@@ -685,10 +688,10 @@ printf("unary_oper_get_candidates: found %d candidates\n", ncandidates);
|
||||
Operator
|
||||
right_oper(char *op, Oid arg)
|
||||
{
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOid;
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOid;
|
||||
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
@@ -708,7 +711,7 @@ right_oper(char *op, Oid arg)
|
||||
{
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
ObjectIdGetDatum(candidates->args[0]),
|
||||
ObjectIdGetDatum(candidates->args[0]),
|
||||
ObjectIdGetDatum(InvalidOid),
|
||||
CharGetDatum('r'));
|
||||
Assert(HeapTupleIsValid(tup));
|
||||
@@ -737,7 +740,7 @@ right_oper(char *op, Oid arg)
|
||||
}
|
||||
}
|
||||
return (Operator) tup;
|
||||
} /* right_oper() */
|
||||
} /* right_oper() */
|
||||
|
||||
|
||||
/* Given unary left-side operator (operator on left), return oper struct */
|
||||
@@ -745,10 +748,10 @@ right_oper(char *op, Oid arg)
|
||||
Operator
|
||||
left_oper(char *op, Oid arg)
|
||||
{
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOid;
|
||||
HeapTuple tup;
|
||||
CandidateList candidates;
|
||||
int ncandidates;
|
||||
Oid *targetOid;
|
||||
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
@@ -769,12 +772,12 @@ left_oper(char *op, Oid arg)
|
||||
tup = SearchSysCacheTuple(OPRNAME,
|
||||
PointerGetDatum(op),
|
||||
ObjectIdGetDatum(InvalidOid),
|
||||
ObjectIdGetDatum(candidates->args[0]),
|
||||
ObjectIdGetDatum(candidates->args[0]),
|
||||
CharGetDatum('l'));
|
||||
Assert(HeapTupleIsValid(tup));
|
||||
#ifdef PARSEDEBUG
|
||||
printf("left_oper: searched cache for single left oper candidate '%s %s'\n",
|
||||
op, typeidTypeName((Oid) candidates->args[0]));
|
||||
printf("left_oper: searched cache for single left oper candidate '%s %s'\n",
|
||||
op, typeidTypeName((Oid) candidates->args[0]));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -793,13 +796,13 @@ printf("left_oper: searched cache for single left oper candidate '%s %s'\n",
|
||||
return NULL;
|
||||
}
|
||||
#ifdef PARSEDEBUG
|
||||
printf("left_oper: searched cache for best left oper candidate '%s %s'\n",
|
||||
op, typeidTypeName(*targetOid));
|
||||
printf("left_oper: searched cache for best left oper candidate '%s %s'\n",
|
||||
op, typeidTypeName(*targetOid));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return (Operator) tup;
|
||||
} /* left_oper() */
|
||||
} /* left_oper() */
|
||||
|
||||
|
||||
/* op_error()
|
||||
@@ -830,6 +833,6 @@ op_error(char *op, Oid arg1, Oid arg2)
|
||||
|
||||
elog(ERROR, "There is no operator '%s' for types '%s' and '%s'"
|
||||
"\n\tYou will either have to retype this query using an explicit cast,"
|
||||
"\n\tor you will have to define the operator using CREATE OPERATOR",
|
||||
"\n\tor you will have to define the operator using CREATE OPERATOR",
|
||||
op, typeTypeName(tp1), typeTypeName(tp2));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.15 1998/09/01 03:24:17 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.16 1998/09/01 04:30:36 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -25,8 +25,7 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
static void
|
||||
checkTargetTypes(ParseState *pstate, char *target_colname,
|
||||
static void checkTargetTypes(ParseState *pstate, char *target_colname,
|
||||
char *refname, char *colname);
|
||||
|
||||
struct
|
||||
@@ -191,10 +190,13 @@ addRangeTableEntry(ParseState *pstate,
|
||||
if (pstate != NULL)
|
||||
{
|
||||
if (refnameRangeTablePosn(pstate, refname, &sublevels_up) != 0 &&
|
||||
(!inFromCl || sublevels_up == 0)) {
|
||||
if (!strcmp(refname, "*CURRENT*") || !strcmp(refname, "*NEW*")) {
|
||||
int rt_index = refnameRangeTablePosn(pstate, refname, &sublevels_up);
|
||||
return (RangeTblEntry *)nth(rt_index - 1, pstate->p_rtable);
|
||||
(!inFromCl || sublevels_up == 0))
|
||||
{
|
||||
if (!strcmp(refname, "*CURRENT*") || !strcmp(refname, "*NEW*"))
|
||||
{
|
||||
int rt_index = refnameRangeTablePosn(pstate, refname, &sublevels_up);
|
||||
|
||||
return (RangeTblEntry *) nth(rt_index - 1, pstate->p_rtable);
|
||||
}
|
||||
elog(ERROR, "Table name %s specified more than once", refname);
|
||||
}
|
||||
@@ -438,12 +440,12 @@ checkTargetTypes(ParseState *pstate, char *target_colname,
|
||||
|
||||
#if FALSE
|
||||
if ((attrtype_id != attrtype_target)
|
||||
|| (get_atttypmod(rte->relid, resdomno_id) !=
|
||||
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target)))
|
||||
|| (get_atttypmod(rte->relid, resdomno_id) !=
|
||||
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target)))
|
||||
{
|
||||
if (can_coerce_type(1, &attrtype_id, &attrtype_target))
|
||||
{
|
||||
Node *expr = coerce_type(pstate, expr, attrtype_id, attrtype_target);
|
||||
Node *expr = coerce_type(pstate, expr, attrtype_id, attrtype_target);
|
||||
|
||||
elog(ERROR, "Type %s(%d) can be coerced to match target column %s(%d)",
|
||||
colname, get_atttypmod(rte->relid, resdomno_id),
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.26 1998/09/01 03:24:19 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.27 1998/09/01 04:30:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -32,9 +32,8 @@
|
||||
|
||||
static List *ExpandAllTables(ParseState *pstate);
|
||||
static char *FigureColname(Node *expr, Node *resval);
|
||||
|
||||
Node *
|
||||
SizeTargetExpr(ParseState *pstate,
|
||||
|
||||
Node *SizeTargetExpr(ParseState *pstate,
|
||||
Node *expr,
|
||||
Oid attrtype,
|
||||
int32 attrtypmod);
|
||||
@@ -42,11 +41,11 @@ SizeTargetExpr(ParseState *pstate,
|
||||
|
||||
/* MakeTargetEntryIdent()
|
||||
* Transforms an Ident Node to a Target Entry
|
||||
* Created this function to allow the ORDER/GROUP BY clause to be able
|
||||
* to construct a TargetEntry from an Ident.
|
||||
* Created this function to allow the ORDER/GROUP BY clause to be able
|
||||
* to construct a TargetEntry from an Ident.
|
||||
*
|
||||
* resjunk = TRUE will hide the target entry in the final result tuple.
|
||||
* daveh@insightdist.com 5/20/98
|
||||
* daveh@insightdist.com 5/20/98
|
||||
*
|
||||
* Added more conversion logic to match up types from source to target.
|
||||
* - thomas 1998-06-02
|
||||
@@ -63,15 +62,15 @@ MakeTargetEntryIdent(ParseState *pstate,
|
||||
char *colname,
|
||||
int16 resjunk)
|
||||
{
|
||||
Node *expr = NULL;
|
||||
Oid attrtype_target;
|
||||
Node *expr = NULL;
|
||||
Oid attrtype_target;
|
||||
TargetEntry *tent = makeNode(TargetEntry);
|
||||
|
||||
if (pstate->p_is_insert)
|
||||
{
|
||||
if (pstate->p_insert_columns != NIL)
|
||||
{
|
||||
Ident *id = lfirst(pstate->p_insert_columns);
|
||||
Ident *id = lfirst(pstate->p_insert_columns);
|
||||
|
||||
*resname = id->name;
|
||||
pstate->p_insert_columns = lnext(pstate->p_insert_columns);
|
||||
@@ -82,8 +81,8 @@ MakeTargetEntryIdent(ParseState *pstate,
|
||||
|
||||
if (pstate->p_is_insert || pstate->p_is_update)
|
||||
{
|
||||
Oid attrtype_id;
|
||||
int resdomno_id,
|
||||
Oid attrtype_id;
|
||||
int resdomno_id,
|
||||
resdomno_target;
|
||||
RangeTblEntry *rte;
|
||||
char *target_colname;
|
||||
@@ -92,7 +91,10 @@ MakeTargetEntryIdent(ParseState *pstate,
|
||||
|
||||
target_colname = *resname;
|
||||
|
||||
/* this looks strange to me, returning an empty TargetEntry bjm 1998/08/24 */
|
||||
/*
|
||||
* this looks strange to me, returning an empty TargetEntry bjm
|
||||
* 1998/08/24
|
||||
*/
|
||||
if (target_colname == NULL || colname == NULL)
|
||||
return tent;
|
||||
|
||||
@@ -115,11 +117,11 @@ MakeTargetEntryIdent(ParseState *pstate,
|
||||
attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("MakeTargetEntryIdent- transform type %d to %d\n",
|
||||
attrtype_id, attrtype_target);
|
||||
printf("MakeTargetEntryIdent- transform type %d to %d\n",
|
||||
attrtype_id, attrtype_target);
|
||||
#endif
|
||||
if ((attrtype_id != attrtype_target)
|
||||
|| ((attrtypmod_target >= 0) && (attrtypmod_target != attrtypmod)))
|
||||
|| ((attrtypmod_target >= 0) && (attrtypmod_target != attrtypmod)))
|
||||
{
|
||||
if (can_coerce_type(1, &attrtype_id, &attrtype_target))
|
||||
{
|
||||
@@ -136,26 +138,25 @@ printf("MakeTargetEntryIdent- transform type %d to %d\n",
|
||||
target_colname);
|
||||
#else
|
||||
elog(ERROR, "Type or size of %s(%d) does not match target column %s(%d)",
|
||||
colname, attrtypmod, target_colname, attrtypmod_target);
|
||||
colname, attrtypmod, target_colname, attrtypmod_target);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* here we want to look for column names only, not
|
||||
* relation names (even though they can be stored in
|
||||
* Ident nodes, too)
|
||||
* here we want to look for column names only, not relation names
|
||||
* (even though they can be stored in Ident nodes, too)
|
||||
*/
|
||||
if (expr == NULL)
|
||||
{
|
||||
char *name;
|
||||
int32 type_mod;
|
||||
char *name;
|
||||
int32 type_mod;
|
||||
|
||||
name = ((*resname != NULL)? *resname: colname);
|
||||
name = ((*resname != NULL) ? *resname : colname);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("MakeTargetEntryIdent- call transformIdent()\n");
|
||||
printf("MakeTargetEntryIdent- call transformIdent()\n");
|
||||
#endif
|
||||
#if FALSE
|
||||
expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
|
||||
@@ -170,7 +171,7 @@ printf("MakeTargetEntryIdent- call transformIdent()\n");
|
||||
type_mod = -1;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
|
||||
printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
|
||||
#endif
|
||||
|
||||
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
|
||||
@@ -184,7 +185,7 @@ printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
|
||||
}
|
||||
|
||||
return tent;
|
||||
} /* MakeTargetEntryIdent() */
|
||||
} /* MakeTargetEntryIdent() */
|
||||
|
||||
|
||||
/* MakeTargetEntryExpr()
|
||||
@@ -192,19 +193,19 @@ printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
|
||||
* arrayRef is a list of transformed A_Indices.
|
||||
*
|
||||
* For type mismatches between expressions and targets, use the same
|
||||
* techniques as for function and operator type coersion.
|
||||
* techniques as for function and operator type coersion.
|
||||
* - thomas 1998-05-08
|
||||
*
|
||||
* Added resjunk flag and made extern so that it can be use by GROUP/
|
||||
* ORDER BY a function or expersion not in the target_list
|
||||
* - daveh@insightdist.com 1998-07-31
|
||||
* - daveh@insightdist.com 1998-07-31
|
||||
*/
|
||||
TargetEntry *
|
||||
MakeTargetEntryExpr(ParseState *pstate,
|
||||
char *colname,
|
||||
Node *expr,
|
||||
List *arrayRef,
|
||||
int16 resjunk)
|
||||
char *colname,
|
||||
Node *expr,
|
||||
List *arrayRef,
|
||||
int16 resjunk)
|
||||
{
|
||||
Oid type_id,
|
||||
attrtype;
|
||||
@@ -227,6 +228,7 @@ MakeTargetEntryExpr(ParseState *pstate,
|
||||
/* Process target columns that will be receiving results */
|
||||
if (pstate->p_is_insert || pstate->p_is_update)
|
||||
{
|
||||
|
||||
/*
|
||||
* insert or update query -- insert, update work only on one
|
||||
* relation, so multiple occurence of same resdomno is bogus
|
||||
@@ -240,13 +242,16 @@ MakeTargetEntryExpr(ParseState *pstate,
|
||||
attrtype = GetArrayElementType(attrtype);
|
||||
attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod;
|
||||
|
||||
/* Check for InvalidOid since that seems to indicate a NULL constant... */
|
||||
/*
|
||||
* Check for InvalidOid since that seems to indicate a NULL
|
||||
* constant...
|
||||
*/
|
||||
if (type_id != InvalidOid)
|
||||
{
|
||||
/* Mismatch on types? then try to coerce to target... */
|
||||
if (attrtype != type_id)
|
||||
{
|
||||
Oid typelem;
|
||||
Oid typelem;
|
||||
|
||||
if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
|
||||
typelem = typeidTypElem(attrtype);
|
||||
@@ -258,18 +263,19 @@ MakeTargetEntryExpr(ParseState *pstate,
|
||||
if (!HeapTupleIsValid(expr))
|
||||
elog(ERROR, "parser: attribute '%s' is of type '%s'"
|
||||
" but expression is of type '%s'"
|
||||
"\n\tYou will need to rewrite or cast the expression",
|
||||
"\n\tYou will need to rewrite or cast the expression",
|
||||
colname,
|
||||
typeidTypeName(attrtype),
|
||||
typeidTypeName(type_id));
|
||||
}
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
|
||||
printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
|
||||
#endif
|
||||
|
||||
/* Apparently going to a fixed-length string?
|
||||
* Then explicitly size for storage...
|
||||
/*
|
||||
* Apparently going to a fixed-length string? Then explicitly
|
||||
* size for storage...
|
||||
*/
|
||||
if (attrtypmod > 0)
|
||||
expr = SizeTargetExpr(pstate, expr, attrtype, attrtypmod);
|
||||
@@ -286,8 +292,8 @@ printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
|
||||
att->relname = pstrdup(RelationGetRelationName(rd)->data);
|
||||
att->attrs = lcons(makeString(colname), NIL);
|
||||
target_expr = (Expr *) ParseNestedFuncOrColumn(pstate, att,
|
||||
&pstate->p_last_resno,
|
||||
EXPR_COLUMN_FIRST);
|
||||
&pstate->p_last_resno,
|
||||
EXPR_COLUMN_FIRST);
|
||||
while (ar != NIL)
|
||||
{
|
||||
A_Indices *ind = lfirst(ar);
|
||||
@@ -329,7 +335,7 @@ printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
|
||||
resjunk);
|
||||
|
||||
return makeTargetEntry(resnode, expr);
|
||||
} /* MakeTargetEntryExpr() */
|
||||
} /* MakeTargetEntryExpr() */
|
||||
|
||||
/*
|
||||
* MakeTargetlistComplex()
|
||||
@@ -337,12 +343,12 @@ printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
|
||||
*/
|
||||
static TargetEntry *
|
||||
MakeTargetEntryComplex(ParseState *pstate,
|
||||
ResTarget *res)
|
||||
ResTarget *res)
|
||||
{
|
||||
Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
|
||||
Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformTargetList: decode T_Expr\n");
|
||||
printf("transformTargetList: decode T_Expr\n");
|
||||
#endif
|
||||
|
||||
handleTargetColname(pstate, &res->name, NULL, NULL);
|
||||
@@ -366,7 +372,7 @@ printf("transformTargetList: decode T_Expr\n");
|
||||
elog(ERROR, "yyparse: string constant expected");
|
||||
|
||||
val = (char *) textout((struct varlena *)
|
||||
((Const *) expr)->constvalue);
|
||||
((Const *) expr)->constvalue);
|
||||
str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
|
||||
foreach(elt, res->indirection)
|
||||
{
|
||||
@@ -406,8 +412,8 @@ printf("transformTargetList: decode T_Expr\n");
|
||||
constval->type = T_String;
|
||||
constval->val.str = save_str;
|
||||
return MakeTargetEntryExpr(pstate, res->name,
|
||||
(Node *) make_const(constval),
|
||||
NULL, FALSE);
|
||||
(Node *) make_const(constval),
|
||||
NULL, FALSE);
|
||||
pfree(save_str);
|
||||
}
|
||||
else
|
||||
@@ -417,10 +423,10 @@ printf("transformTargetList: decode T_Expr\n");
|
||||
/* this is not an array assignment */
|
||||
if (colname == NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* if you're wondering why this is here, look
|
||||
* at the yacc grammar for why a name can be
|
||||
* missing. -ay
|
||||
* if you're wondering why this is here, look at the yacc
|
||||
* grammar for why a name can be missing. -ay
|
||||
*/
|
||||
colname = FigureColname(expr, res->val);
|
||||
}
|
||||
@@ -439,7 +445,7 @@ printf("transformTargetList: decode T_Expr\n");
|
||||
}
|
||||
res->name = colname;
|
||||
return MakeTargetEntryExpr(pstate, res->name, expr,
|
||||
res->indirection, FALSE);
|
||||
res->indirection, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +455,7 @@ printf("transformTargetList: decode T_Expr\n");
|
||||
*/
|
||||
static TargetEntry *
|
||||
MakeTargetEntryAttr(ParseState *pstate,
|
||||
ResTarget *res)
|
||||
ResTarget *res)
|
||||
{
|
||||
Oid type_id;
|
||||
int32 type_mod;
|
||||
@@ -460,16 +466,16 @@ MakeTargetEntryAttr(ParseState *pstate,
|
||||
Resdom *resnode;
|
||||
int resdomno;
|
||||
List *attrs = att->attrs;
|
||||
TargetEntry *tent;
|
||||
TargetEntry *tent;
|
||||
Oid relid;
|
||||
|
||||
attrname = strVal(lfirst(att->attrs));
|
||||
|
||||
/*
|
||||
* Target item is fully specified: ie.
|
||||
* relation.attribute
|
||||
* Target item is fully specified: ie. relation.attribute
|
||||
*/
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformTargetList: decode T_Attr\n");
|
||||
printf("transformTargetList: decode T_Attr\n");
|
||||
#endif
|
||||
result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);
|
||||
handleTargetColname(pstate, &res->name, att->relname, attrname);
|
||||
@@ -498,7 +504,8 @@ printf("transformTargetList: decode T_Attr\n");
|
||||
resname = (res->name) ? res->name : strVal(lfirst(attrs));
|
||||
if (pstate->p_is_insert || pstate->p_is_update)
|
||||
{
|
||||
Relation rd;
|
||||
Relation rd;
|
||||
|
||||
/*
|
||||
* insert or update query -- insert, update work only on one
|
||||
* relation, so multiple occurence of same resdomno is bogus
|
||||
@@ -508,7 +515,7 @@ printf("transformTargetList: decode T_Attr\n");
|
||||
resdomno = attnameAttNum(rd, res->name);
|
||||
}
|
||||
else
|
||||
resdomno = pstate->p_last_resno++;
|
||||
resdomno = pstate->p_last_resno++;
|
||||
resnode = makeResdom((AttrNumber) resdomno,
|
||||
(Oid) type_id,
|
||||
type_mod,
|
||||
@@ -522,7 +529,7 @@ printf("transformTargetList: decode T_Attr\n");
|
||||
return tent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* transformTargetList()
|
||||
* Turns a list of ResTarget's into a list of TargetEntry's.
|
||||
*/
|
||||
@@ -534,8 +541,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
|
||||
while (targetlist != NIL)
|
||||
{
|
||||
ResTarget *res = (ResTarget *) lfirst(targetlist);
|
||||
TargetEntry *tent = NULL;
|
||||
ResTarget *res = (ResTarget *) lfirst(targetlist);
|
||||
TargetEntry *tent = NULL;
|
||||
|
||||
switch (nodeTag(res->val))
|
||||
{
|
||||
@@ -544,10 +551,10 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
char *identname;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("transformTargetList: decode T_Ident\n");
|
||||
printf("transformTargetList: decode T_Ident\n");
|
||||
#endif
|
||||
identname = ((Ident *) res->val)->name;
|
||||
tent = MakeTargetEntryIdent(pstate, (Node *)res->val, &res->name, NULL, identname, FALSE);
|
||||
tent = MakeTargetEntryIdent(pstate, (Node *) res->val, &res->name, NULL, identname, FALSE);
|
||||
break;
|
||||
}
|
||||
case T_ParamNo:
|
||||
@@ -560,9 +567,10 @@ printf("transformTargetList: decode T_Ident\n");
|
||||
}
|
||||
case T_Attr:
|
||||
{
|
||||
bool expand_star = false;
|
||||
bool expand_star = false;
|
||||
char *attrname;
|
||||
Attr *att = (Attr *) res->val;
|
||||
|
||||
/*
|
||||
* Target item is a single '*', expand all tables (eg.
|
||||
* SELECT * FROM emp)
|
||||
@@ -577,22 +585,23 @@ printf("transformTargetList: decode T_Ident\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Target item is relation.*, expand the table (eg.
|
||||
* SELECT emp.*, dname FROM emp, dept)
|
||||
* Target item is relation.*, expand the table
|
||||
* (eg. SELECT emp.*, dname FROM emp, dept)
|
||||
*/
|
||||
attrname = strVal(lfirst(att->attrs));
|
||||
if (att->attrs != NIL && !strcmp(attrname, "*"))
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* tail_p_target is the target list we're building
|
||||
* in the while loop. Make sure we fix it after
|
||||
* appending more nodes.
|
||||
* tail_p_target is the target list we're
|
||||
* building in the while loop. Make sure we
|
||||
* fix it after appending more nodes.
|
||||
*/
|
||||
if (tail_p_target == NIL)
|
||||
p_target = tail_p_target = expandAll(pstate, att->relname,
|
||||
att->relname, &pstate->p_last_resno);
|
||||
att->relname, &pstate->p_last_resno);
|
||||
else
|
||||
lnext(tail_p_target) =
|
||||
expandAll(pstate, att->relname, att->relname,
|
||||
@@ -605,6 +614,7 @@ printf("transformTargetList: decode T_Ident\n");
|
||||
while (lnext(tail_p_target) != NIL)
|
||||
/* make sure we point to the last target entry */
|
||||
tail_p_target = lnext(tail_p_target);
|
||||
|
||||
/*
|
||||
* skip rest of while loop
|
||||
*/
|
||||
@@ -634,7 +644,7 @@ printf("transformTargetList: decode T_Ident\n");
|
||||
}
|
||||
|
||||
return p_target;
|
||||
} /* transformTargetList() */
|
||||
} /* transformTargetList() */
|
||||
|
||||
|
||||
Node *
|
||||
@@ -646,20 +656,25 @@ CoerceTargetExpr(ParseState *pstate,
|
||||
if (can_coerce_type(1, &type_id, &attrtype))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("CoerceTargetExpr: coerce type from %s to %s\n",
|
||||
typeidTypeName(type_id), typeidTypeName(attrtype));
|
||||
printf("CoerceTargetExpr: coerce type from %s to %s\n",
|
||||
typeidTypeName(type_id), typeidTypeName(attrtype));
|
||||
#endif
|
||||
expr = coerce_type(pstate, expr, type_id, attrtype);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_STRING_HACKS
|
||||
/* string hacks to get transparent conversions w/o explicit conversions */
|
||||
|
||||
/*
|
||||
* string hacks to get transparent conversions w/o explicit
|
||||
* conversions
|
||||
*/
|
||||
else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))
|
||||
{
|
||||
Oid text_id = TEXTOID;
|
||||
Oid text_id = TEXTOID;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("CoerceTargetExpr: try coercing from %s to %s via text\n",
|
||||
typeidTypeName(type_id), typeidTypeName(attrtype));
|
||||
printf("CoerceTargetExpr: try coercing from %s to %s via text\n",
|
||||
typeidTypeName(type_id), typeidTypeName(attrtype));
|
||||
#endif
|
||||
if (type_id == TEXTOID)
|
||||
{
|
||||
@@ -675,7 +690,7 @@ printf("CoerceTargetExpr: try coercing from %s to %s via text\n",
|
||||
expr = NULL;
|
||||
|
||||
return expr;
|
||||
} /* CoerceTargetExpr() */
|
||||
} /* CoerceTargetExpr() */
|
||||
|
||||
|
||||
/* SizeTargetExpr()
|
||||
@@ -694,19 +709,20 @@ SizeTargetExpr(ParseState *pstate,
|
||||
Oid oid_array[8];
|
||||
|
||||
FuncCall *func;
|
||||
A_Const *cons;
|
||||
A_Const *cons;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("SizeTargetExpr: ensure target fits storage\n");
|
||||
printf("SizeTargetExpr: ensure target fits storage\n");
|
||||
#endif
|
||||
funcname = typeidTypeName(attrtype);
|
||||
oid_array[0] = attrtype;
|
||||
oid_array[1] = INT4OID;
|
||||
for (i = 2; i < 8; i++) oid_array[i] = InvalidOid;
|
||||
for (i = 2; i < 8; i++)
|
||||
oid_array[i] = InvalidOid;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("SizeTargetExpr: look for conversion function %s(%s,%s)\n",
|
||||
funcname, typeidTypeName(attrtype), typeidTypeName(INT4OID));
|
||||
printf("SizeTargetExpr: look for conversion function %s(%s,%s)\n",
|
||||
funcname, typeidTypeName(attrtype), typeidTypeName(INT4OID));
|
||||
#endif
|
||||
|
||||
/* attempt to find with arguments exactly as specified... */
|
||||
@@ -719,7 +735,7 @@ printf("SizeTargetExpr: look for conversion function %s(%s,%s)\n",
|
||||
if (HeapTupleIsValid(ftup))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf("SizeTargetExpr: found conversion function for sizing\n");
|
||||
printf("SizeTargetExpr: found conversion function for sizing\n");
|
||||
#endif
|
||||
func = makeNode(FuncCall);
|
||||
func->funcname = funcname;
|
||||
@@ -727,19 +743,17 @@ printf("SizeTargetExpr: found conversion function for sizing\n");
|
||||
cons = makeNode(A_Const);
|
||||
cons->val.type = T_Integer;
|
||||
cons->val.val.ival = attrtypmod;
|
||||
func->args = lappend( lcons(expr,NIL), cons);
|
||||
func->args = lappend(lcons(expr, NIL), cons);
|
||||
|
||||
expr = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);
|
||||
}
|
||||
#ifdef PARSEDEBUG
|
||||
else
|
||||
{
|
||||
printf("SizeTargetExpr: no conversion function for sizing\n");
|
||||
}
|
||||
printf("SizeTargetExpr: no conversion function for sizing\n");
|
||||
#endif
|
||||
|
||||
return expr;
|
||||
} /* SizeTargetExpr() */
|
||||
} /* SizeTargetExpr() */
|
||||
|
||||
|
||||
/*
|
||||
@@ -790,7 +804,7 @@ makeTargetNames(ParseState *pstate, List *cols)
|
||||
attnameAttNum(pstate->p_target_relation, name);
|
||||
foreach(nxt, lnext(tl))
|
||||
if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
|
||||
elog(ERROR, "Attribute '%s' should be specified only once", name);
|
||||
elog(ERROR, "Attribute '%s' should be specified only once", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.15 1998/09/01 03:24:20 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.16 1998/09/01 04:30:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -148,7 +148,7 @@ stringTypeString(Type tp, char *string, int32 atttypmod)
|
||||
Oid typelem;
|
||||
|
||||
op = ((Form_pg_type) GETSTRUCT(tp))->typinput;
|
||||
typelem = ((Form_pg_type) GETSTRUCT(tp))->typelem; /* XXX - used for
|
||||
typelem = ((Form_pg_type) GETSTRUCT(tp))->typelem; /* XXX - used for
|
||||
* array_in */
|
||||
return (char *) fmgr(op, string, typelem, atttypmod);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.35 1998/09/01 03:24:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.36 1998/09/01 04:30:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -43,7 +43,7 @@ parser(char *str, Oid *typev, int nargs)
|
||||
#if defined(FLEX_SCANNER)
|
||||
extern void DeleteBuffer(void);
|
||||
|
||||
#endif /* FLEX_SCANNER */
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
init_io();
|
||||
|
||||
@@ -54,7 +54,7 @@ parser(char *str, Oid *typev, int nargs)
|
||||
|
||||
#if defined(FLEX_SCANNER)
|
||||
DeleteBuffer();
|
||||
#endif /* FLEX_SCANNER */
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
clearerr(stdin);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user