3
3
* back to source text
4
4
*
5
5
* 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 $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
41
41
#include <fcntl.h>
42
42
43
43
#include "catalog/heap.h"
44
+ #include "catalog/index.h"
44
45
#include "catalog/pg_index.h"
46
+ #include "catalog/pg_opclass.h"
45
47
#include "catalog/pg_operator.h"
46
48
#include "catalog/pg_shadow.h"
47
49
#include "executor/spi.h"
@@ -94,10 +96,6 @@ static void *plan_getrule = NULL;
94
96
static char * query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1" ;
95
97
static void * plan_getview = NULL ;
96
98
static char * query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1" ;
97
- static void * plan_getam = NULL ;
98
- static char * query_getam = "SELECT * FROM pg_am WHERE oid = $1" ;
99
- static void * plan_getopclass = NULL ;
100
- static char * query_getopclass = "SELECT * FROM pg_opclass WHERE oid = $1" ;
101
99
102
100
103
101
/* ----------
@@ -138,6 +136,8 @@ static void get_sublink_expr(Node *node, deparse_context *context);
138
136
static void get_from_clause (Query * query , deparse_context * context );
139
137
static void get_from_clause_item (Node * jtnode , Query * query ,
140
138
deparse_context * context );
139
+ static void get_opclass_name (Oid opclass , bool only_nondefault ,
140
+ StringInfo buf );
141
141
static bool tleIsArrayAssign (TargetEntry * tle );
142
142
static char * quote_identifier (char * ident );
143
143
static char * get_relation_name (Oid relid );
@@ -341,48 +341,16 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
341
341
HeapTuple ht_idx ;
342
342
HeapTuple ht_idxrel ;
343
343
HeapTuple ht_indrel ;
344
- HeapTuple spi_tup ;
345
- TupleDesc spi_ttc ;
346
- int spi_fno ;
347
344
Form_pg_index idxrec ;
348
345
Form_pg_class idxrelrec ;
349
346
Form_pg_class indrelrec ;
350
- Datum spi_args [1 ];
351
- char spi_nulls [2 ];
352
- int spirc ;
347
+ Form_pg_am amrec ;
353
348
int len ;
354
349
int keyno ;
355
350
StringInfoData buf ;
356
351
StringInfoData keybuf ;
357
352
char * sep ;
358
353
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
- Oid argtypes [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
-
386
354
/*
387
355
* Fetch the pg_index tuple by the Oid of the index
388
356
*/
@@ -414,35 +382,27 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
414
382
indrelrec = (Form_pg_class ) GETSTRUCT (ht_indrel );
415
383
416
384
/*
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.
418
388
*/
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 );
432
393
433
394
/*
434
395
* Start the index definition
435
396
*/
436
397
initStringInfo (& buf );
437
398
appendStringInfo (& buf , "CREATE %sINDEX %s ON %s USING %s (" ,
438
399
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 )));
443
403
444
404
/*
445
- * Collect the indexed attributes
405
+ * Collect the indexed attributes in keybuf
446
406
*/
447
407
initStringInfo (& keybuf );
448
408
sep = "" ;
@@ -465,29 +425,14 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
465
425
* If not a functional index, add the operator class name
466
426
*/
467
427
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 );
484
429
}
485
430
486
- /*
487
- * For functional index say 'func (attrs) opclass'
488
- */
489
431
if (idxrec -> indproc != InvalidOid )
490
432
{
433
+ /*
434
+ * For functional index say 'func (attrs) opclass'
435
+ */
491
436
HeapTuple proctup ;
492
437
Form_pg_proc procStruct ;
493
438
@@ -498,58 +443,67 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
498
443
elog (ERROR , "cache lookup for proc %u failed" , idxrec -> indproc );
499
444
procStruct = (Form_pg_proc ) GETSTRUCT (proctup );
500
445
501
- appendStringInfo (& buf , "%s(%s) " ,
502
- quote_identifier (pstrdup ( NameStr (procStruct -> proname ) )),
446
+ appendStringInfo (& buf , "%s(%s)" ,
447
+ quote_identifier (NameStr (procStruct -> proname )),
503
448
keybuf .data );
449
+ get_opclass_name (idxrec -> indclass [0 ], true, & buf );
504
450
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 )));
519
451
ReleaseSysCache (proctup );
520
452
}
521
453
else
522
-
454
+ {
523
455
/*
524
- * For the others say 'attr opclass [, ...]'
456
+ * Otherwise say 'attr opclass [, ...]'
525
457
*/
526
458
appendStringInfo (& buf , "%s" , keybuf .data );
459
+ }
460
+
461
+ appendStringInfo (& buf , ")" );
527
462
528
463
/*
529
- * Finish
464
+ * If it's a partial index, decompile and append the predicate
530
465
*/
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
+ }
532
491
533
492
/*
534
- * Create the result in upper executor memory , and free objects
493
+ * Create the result as a TEXT datum , and free working data
535
494
*/
536
495
len = buf .len + VARHDRSZ ;
537
- indexdef = SPI_palloc (len );
496
+ indexdef = ( text * ) palloc (len );
538
497
VARATT_SIZEP (indexdef ) = len ;
539
498
memcpy (VARDATA (indexdef ), buf .data , buf .len );
540
499
541
500
pfree (buf .data );
542
501
pfree (keybuf .data );
502
+ pfree (amrec );
543
503
ReleaseSysCache (ht_idx );
544
504
ReleaseSysCache (ht_idxrel );
545
505
ReleaseSysCache (ht_indrel );
546
506
547
- /*
548
- * Disconnect from SPI manager
549
- */
550
- if (SPI_finish () != SPI_OK_FINISH )
551
- elog (ERROR , "get_viewdef: SPI_finish() failed" );
552
-
553
507
PG_RETURN_TEXT_P (indexdef );
554
508
}
555
509
@@ -2546,6 +2500,32 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
2546
2500
dpns -> namespace = sv_namespace ;
2547
2501
}
2548
2502
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
+ static void
2512
+ get_opclass_name (Oid opclass , bool only_nondefault ,
2513
+ StringInfo buf )
2514
+ {
2515
+ HeapTuple ht_opc ;
2516
+ Form_pg_opclass opcrec ;
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
+ }
2549
2529
2550
2530
/* ----------
2551
2531
* tleIsArrayAssign - check for array assignment
0 commit comments