Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite5bbf19

Browse files
committed
Extend pg_get_indexdef() to know about index predicates. Also, tweak
it to suppress index opclass output for opclasses that are the defaultfor their datatype; only non-default opclasses are shown explicitly.This is expected to improve portability of the CREATE INDEX commandacross future versions of Postgres --- we've changed index opclassestoo often in the past to think we won't do so again.
1 parent0648d78 commite5bbf19

File tree

1 file changed

+84
-104
lines changed

1 file changed

+84
-104
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 84 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*back to source text
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.82 2001/08/12 21:35:19 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.83 2001/10/01 20:15:26 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -41,7 +41,9 @@
4141
#include<fcntl.h>
4242

4343
#include"catalog/heap.h"
44+
#include"catalog/index.h"
4445
#include"catalog/pg_index.h"
46+
#include"catalog/pg_opclass.h"
4547
#include"catalog/pg_operator.h"
4648
#include"catalog/pg_shadow.h"
4749
#include"executor/spi.h"
@@ -94,10 +96,6 @@ static void *plan_getrule = NULL;
9496
staticchar*query_getrule="SELECT * FROM pg_rewrite WHERE rulename = $1";
9597
staticvoid*plan_getview=NULL;
9698
staticchar*query_getview="SELECT * FROM pg_rewrite WHERE rulename = $1";
97-
staticvoid*plan_getam=NULL;
98-
staticchar*query_getam="SELECT * FROM pg_am WHERE oid = $1";
99-
staticvoid*plan_getopclass=NULL;
100-
staticchar*query_getopclass="SELECT * FROM pg_opclass WHERE oid = $1";
10199

102100

103101
/* ----------
@@ -138,6 +136,8 @@ static void get_sublink_expr(Node *node, deparse_context *context);
138136
staticvoidget_from_clause(Query*query,deparse_context*context);
139137
staticvoidget_from_clause_item(Node*jtnode,Query*query,
140138
deparse_context*context);
139+
staticvoidget_opclass_name(Oidopclass,boolonly_nondefault,
140+
StringInfobuf);
141141
staticbooltleIsArrayAssign(TargetEntry*tle);
142142
staticchar*quote_identifier(char*ident);
143143
staticchar*get_relation_name(Oidrelid);
@@ -341,48 +341,16 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
341341
HeapTupleht_idx;
342342
HeapTupleht_idxrel;
343343
HeapTupleht_indrel;
344-
HeapTuplespi_tup;
345-
TupleDescspi_ttc;
346-
intspi_fno;
347344
Form_pg_indexidxrec;
348345
Form_pg_classidxrelrec;
349346
Form_pg_classindrelrec;
350-
Datumspi_args[1];
351-
charspi_nulls[2];
352-
intspirc;
347+
Form_pg_amamrec;
353348
intlen;
354349
intkeyno;
355350
StringInfoDatabuf;
356351
StringInfoDatakeybuf;
357352
char*sep;
358353

359-
/*
360-
* Connect to SPI manager
361-
*/
362-
if (SPI_connect()!=SPI_OK_CONNECT)
363-
elog(ERROR,"get_indexdef: cannot connect to SPI manager");
364-
365-
/*
366-
* On the first call prepare the plans to lookup pg_am and pg_opclass.
367-
*/
368-
if (plan_getam==NULL)
369-
{
370-
Oidargtypes[1];
371-
void*plan;
372-
373-
argtypes[0]=OIDOID;
374-
plan=SPI_prepare(query_getam,1,argtypes);
375-
if (plan==NULL)
376-
elog(ERROR,"SPI_prepare() failed for \"%s\"",query_getam);
377-
plan_getam=SPI_saveplan(plan);
378-
379-
argtypes[0]=OIDOID;
380-
plan=SPI_prepare(query_getopclass,1,argtypes);
381-
if (plan==NULL)
382-
elog(ERROR,"SPI_prepare() failed for \"%s\"",query_getopclass);
383-
plan_getopclass=SPI_saveplan(plan);
384-
}
385-
386354
/*
387355
* Fetch the pg_index tuple by the Oid of the index
388356
*/
@@ -414,35 +382,27 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
414382
indrelrec= (Form_pg_class)GETSTRUCT(ht_indrel);
415383

416384
/*
417-
* Get the am name for the index relation
385+
* Fetch the pg_am tuple of the index' access method
386+
*
387+
* There is no syscache for this, so use index.c subroutine.
418388
*/
419-
spi_args[0]=ObjectIdGetDatum(idxrelrec->relam);
420-
spi_nulls[0]=' ';
421-
spi_nulls[1]='\0';
422-
spirc=SPI_execp(plan_getam,spi_args,spi_nulls,1);
423-
if (spirc!=SPI_OK_SELECT)
424-
elog(ERROR,"failed to get pg_am tuple for index %s",
425-
NameStr(idxrelrec->relname));
426-
if (SPI_processed!=1)
427-
elog(ERROR,"failed to get pg_am tuple for index %s",
428-
NameStr(idxrelrec->relname));
429-
spi_tup=SPI_tuptable->vals[0];
430-
spi_ttc=SPI_tuptable->tupdesc;
431-
spi_fno=SPI_fnumber(spi_ttc,"amname");
389+
amrec=AccessMethodObjectIdGetForm(idxrelrec->relam,
390+
CurrentMemoryContext);
391+
if (!amrec)
392+
elog(ERROR,"lookup for AM %u failed",idxrelrec->relam);
432393

433394
/*
434395
* Start the index definition
435396
*/
436397
initStringInfo(&buf);
437398
appendStringInfo(&buf,"CREATE %sINDEX %s ON %s USING %s (",
438399
idxrec->indisunique ?"UNIQUE " :"",
439-
quote_identifier(pstrdup(NameStr(idxrelrec->relname))),
440-
quote_identifier(pstrdup(NameStr(indrelrec->relname))),
441-
quote_identifier(SPI_getvalue(spi_tup,spi_ttc,
442-
spi_fno)));
400+
quote_identifier(NameStr(idxrelrec->relname)),
401+
quote_identifier(NameStr(indrelrec->relname)),
402+
quote_identifier(NameStr(amrec->amname)));
443403

444404
/*
445-
* Collect the indexed attributes
405+
* Collect the indexed attributes in keybuf
446406
*/
447407
initStringInfo(&keybuf);
448408
sep="";
@@ -465,29 +425,14 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
465425
* If not a functional index, add the operator class name
466426
*/
467427
if (idxrec->indproc==InvalidOid)
468-
{
469-
spi_args[0]=ObjectIdGetDatum(idxrec->indclass[keyno]);
470-
spi_nulls[0]=' ';
471-
spi_nulls[1]='\0';
472-
spirc=SPI_execp(plan_getopclass,spi_args,spi_nulls,1);
473-
if (spirc!=SPI_OK_SELECT)
474-
elog(ERROR,"failed to get pg_opclass tuple %u",idxrec->indclass[keyno]);
475-
if (SPI_processed!=1)
476-
elog(ERROR,"failed to get pg_opclass tuple %u",idxrec->indclass[keyno]);
477-
spi_tup=SPI_tuptable->vals[0];
478-
spi_ttc=SPI_tuptable->tupdesc;
479-
spi_fno=SPI_fnumber(spi_ttc,"opcname");
480-
appendStringInfo(&keybuf," %s",
481-
quote_identifier(SPI_getvalue(spi_tup,spi_ttc,
482-
spi_fno)));
483-
}
428+
get_opclass_name(idxrec->indclass[keyno], true,&keybuf);
484429
}
485430

486-
/*
487-
* For functional index say 'func (attrs) opclass'
488-
*/
489431
if (idxrec->indproc!=InvalidOid)
490432
{
433+
/*
434+
* For functional index say 'func (attrs) opclass'
435+
*/
491436
HeapTupleproctup;
492437
Form_pg_procprocStruct;
493438

@@ -498,58 +443,67 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
498443
elog(ERROR,"cache lookup for proc %u failed",idxrec->indproc);
499444
procStruct= (Form_pg_proc)GETSTRUCT(proctup);
500445

501-
appendStringInfo(&buf,"%s(%s)",
502-
quote_identifier(pstrdup(NameStr(procStruct->proname))),
446+
appendStringInfo(&buf,"%s(%s)",
447+
quote_identifier(NameStr(procStruct->proname)),
503448
keybuf.data);
449+
get_opclass_name(idxrec->indclass[0], true,&buf);
504450

505-
spi_args[0]=ObjectIdGetDatum(idxrec->indclass[0]);
506-
spi_nulls[0]=' ';
507-
spi_nulls[1]='\0';
508-
spirc=SPI_execp(plan_getopclass,spi_args,spi_nulls,1);
509-
if (spirc!=SPI_OK_SELECT)
510-
elog(ERROR,"failed to get pg_opclass tuple %u",idxrec->indclass[0]);
511-
if (SPI_processed!=1)
512-
elog(ERROR,"failed to get pg_opclass tuple %u",idxrec->indclass[0]);
513-
spi_tup=SPI_tuptable->vals[0];
514-
spi_ttc=SPI_tuptable->tupdesc;
515-
spi_fno=SPI_fnumber(spi_ttc,"opcname");
516-
appendStringInfo(&buf,"%s",
517-
quote_identifier(SPI_getvalue(spi_tup,spi_ttc,
518-
spi_fno)));
519451
ReleaseSysCache(proctup);
520452
}
521453
else
522-
454+
{
523455
/*
524-
*For the others say 'attr opclass [, ...]'
456+
*Otherwise say 'attr opclass [, ...]'
525457
*/
526458
appendStringInfo(&buf,"%s",keybuf.data);
459+
}
460+
461+
appendStringInfo(&buf,")");
527462

528463
/*
529-
*Finish
464+
*If it's a partial index, decompile and append the predicate
530465
*/
531-
appendStringInfo(&buf,")");
466+
if (VARSIZE(&idxrec->indpred)>VARHDRSZ)
467+
{
468+
Node*node;
469+
List*context;
470+
char*exprstr;
471+
char*str;
472+
473+
/* Convert TEXT object to C string */
474+
exprstr=DatumGetCString(DirectFunctionCall1(textout,
475+
PointerGetDatum(&idxrec->indpred)));
476+
/* Convert expression to node tree */
477+
node= (Node*)stringToNode(exprstr);
478+
/*
479+
* If top level is a List, assume it is an implicit-AND structure,
480+
* and convert to explicit AND. This is needed for partial index
481+
* predicates.
482+
*/
483+
if (node&&IsA(node,List))
484+
node= (Node*)make_ands_explicit((List*)node);
485+
/* Deparse */
486+
context=deparse_context_for(NameStr(indrelrec->relname),
487+
idxrec->indrelid);
488+
str=deparse_expression(node,context, false);
489+
appendStringInfo(&buf," WHERE %s",str);
490+
}
532491

533492
/*
534-
* Create the resultin upper executor memory, and freeobjects
493+
* Create the resultas a TEXT datum, and freeworking data
535494
*/
536495
len=buf.len+VARHDRSZ;
537-
indexdef=SPI_palloc(len);
496+
indexdef=(text*)palloc(len);
538497
VARATT_SIZEP(indexdef)=len;
539498
memcpy(VARDATA(indexdef),buf.data,buf.len);
540499

541500
pfree(buf.data);
542501
pfree(keybuf.data);
502+
pfree(amrec);
543503
ReleaseSysCache(ht_idx);
544504
ReleaseSysCache(ht_idxrel);
545505
ReleaseSysCache(ht_indrel);
546506

547-
/*
548-
* Disconnect from SPI manager
549-
*/
550-
if (SPI_finish()!=SPI_OK_FINISH)
551-
elog(ERROR,"get_viewdef: SPI_finish() failed");
552-
553507
PG_RETURN_TEXT_P(indexdef);
554508
}
555509

@@ -2546,6 +2500,32 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
25462500
dpns->namespace=sv_namespace;
25472501
}
25482502

2503+
/* ----------
2504+
* get_opclass_name- fetch name of an index operator class
2505+
*
2506+
* The opclass name is appended (after a space) to buf.
2507+
* If "only_nondefault" is true, the opclass name is appended only if
2508+
* it isn't the default for its datatype.
2509+
* ----------
2510+
*/
2511+
staticvoid
2512+
get_opclass_name(Oidopclass,boolonly_nondefault,
2513+
StringInfobuf)
2514+
{
2515+
HeapTupleht_opc;
2516+
Form_pg_opclassopcrec;
2517+
2518+
ht_opc=SearchSysCache(CLAOID,
2519+
ObjectIdGetDatum(opclass),
2520+
0,0,0);
2521+
if (!HeapTupleIsValid(ht_opc))
2522+
elog(ERROR,"cache lookup failed for opclass %u",opclass);
2523+
opcrec= (Form_pg_opclass)GETSTRUCT(ht_opc);
2524+
if (!only_nondefault|| !opcrec->opcdefault)
2525+
appendStringInfo(buf," %s",
2526+
quote_identifier(NameStr(opcrec->opcname)));
2527+
ReleaseSysCache(ht_opc);
2528+
}
25492529

25502530
/* ----------
25512531
* tleIsArrayAssign- check for array assignment

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp