<commit_before>/*-------------------------------------------------------------------------
 *
 * comment.c
 *
 * PostgreSQL object comments utility code.
 *
 * Copyright (c) 1999, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "utils/builtins.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_database.h"
#include "catalog/pg_description.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
#include "utils/syscache.h"

#include "../backend/parser/parse.h"

/*------------------------------------------------------------------
 * Static Function Prototypes --
 *
 * The following protoypes are declared static so as not to conflict
 * with any other routines outside this module. These routines are
 * called by the public function CommentObject() routine to create
 * the appropriate comment for the specific object type.
 *------------------------------------------------------------------
 */

static void CommentRelation(int objtype, char *relation, char *comment);
static void CommentAttribute(char *relation, char *attrib, char *comment);
static void CommentDatabase(char *database, char *comment);
static void CommentRewrite(char *rule, char *comment);
static void CommentType(char *type, char *comment);
static void CommentAggregate(char *aggregate, char *aggtype, char *comment);
static void CommentProc(char *function, List *arguments, char *comment);
static void CommentOperator(char *opname, List *arguments, char *comment);
static void CommentTrigger(char *trigger, char *relation, char *comments);

/*------------------------------------------------------------------
 * CommentObject --
 *
 * This routine is used to add the associated comment into
 * pg_description for the object specified by the paramters handed
 * to this routine. If the routine cannot determine an Oid to
 * associated with the parameters handed to this routine, an
 * error is thrown. Otherwise the comment is added to pg_description
 * by calling the CreateComments() routine. If the comments were
 * empty, CreateComments() will drop any comments associated with
 * the object.
 *------------------------------------------------------------------
*/

void CommentObject(int objtype, char *objname, char *objproperty,
		   List *objlist, char *comment) {

  switch (objtype) {
  case (INDEX):
  case (SEQUENCE):
  case (TABLE):
  case (VIEW):
    CommentRelation(objtype, objname, comment);
    break;
  case (COLUMN):
    CommentAttribute(objname, objproperty, comment);
    break;
  case (DATABASE):
    CommentDatabase(objname, comment);
    break;
  case (RULE):
    CommentRewrite(objname, comment);
    break;
  case (TYPE_P):
    CommentType(objname, comment);
    break;
  case (AGGREGATE):
    CommentAggregate(objname, objproperty, comment);
    break;
  case (FUNCTION):
    CommentProc(objname, objlist, comment);
    break;
  case (OPERATOR):
    CommentOperator(objname, objlist, comment);
    break;
  case (TRIGGER):
    CommentTrigger(objname, objproperty, comment);
    break;
  default:
    elog(ERROR, "An attempt was made to comment on a unknown type: %i",
	 objtype);
  }


}

/*------------------------------------------------------------------
 * CreateComments --
 *
 * This routine is handed the oid and the command associated
 * with that id and will insert, update, or delete (if the
 * comment is an empty string or a NULL pointer) the associated
 * comment from the system cataloge, pg_description.
 *
 *------------------------------------------------------------------
 */

void CreateComments(Oid oid, char *comment) {

  Relation description;
  TupleDesc tupDesc;
  HeapScanDesc scan;
  ScanKeyData entry;
  HeapTuple desctuple = NULL, searchtuple;
  Datum values[Natts_pg_description];
  char nulls[Natts_pg_description];
  char replaces[Natts_pg_description];
  bool modified = false;
  int i;

  /*** Open pg_description, form a new tuple, if necessary ***/

  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
  tupDesc = description->rd_att;
  if ((comment != NULL) && (strlen(comment) > 0)) {
    for (i = 0; i < Natts_pg_description; i++) {
      nulls[i] = ' ';
      replaces[i] = 'r';
      values[i] = (Datum) NULL;
    }
    i = 0;
    values[i++] = ObjectIdGetDatum(oid);
    values[i++] = (Datum) fmgr(F_TEXTIN, comment);
  }

  /*** Now, open pg_description and attempt to find the old tuple ***/

  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
			 ObjectIdGetDatum(oid));
  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
  searchtuple = heap_getnext(scan, 0);

  /*** If a previous tuple exists, either delete or prep replacement ***/

  if (HeapTupleIsValid(searchtuple)) {

    /*** If the comment is blank, call heap_delete, else heap_update ***/

    if ((comment == NULL) || (strlen(comment) == 0)) {
      heap_delete(description, &searchtuple->t_self, NULL);
    } else {
      desctuple = heap_modifytuple(searchtuple, description, values,
				   nulls, replaces);
      heap_update(description, &searchtuple->t_self, desctuple, NULL);
      modified = TRUE;
    }

  } else {
    desctuple = heap_formtuple(tupDesc, values, nulls);
    heap_insert(description, desctuple);
    modified = TRUE;
  }

  /*** Complete the scan, update indices, if necessary ***/
<commit_msg>Bruce,<commit_after>/*-------------------------------------------------------------------------
 *
 * comment.c
 *
 * PostgreSQL object comments utility code.
 *
 * Copyright (c) 1999, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "utils/builtins.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_database.h"
#include "catalog/pg_description.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
#include "utils/syscache.h"

#include "../backend/parser/parse.h"

/*------------------------------------------------------------------
 * Static Function Prototypes --
 *
 * The following protoypes are declared static so as not to conflict
 * with any other routines outside this module. These routines are
 * called by the public function CommentObject() routine to create
 * the appropriate comment for the specific object type.
 *------------------------------------------------------------------
 */

static void CommentRelation(int objtype, char *relation, char *comment);
static void CommentAttribute(char *relation, char *attrib, char *comment);
static void CommentDatabase(char *database, char *comment);
static void CommentRewrite(char *rule, char *comment);
static void CommentType(char *type, char *comment);
static void CommentAggregate(char *aggregate, char *aggtype, char *comment);
static void CommentProc(char *function, List *arguments, char *comment);
static void CommentOperator(char *opname, List *arguments, char *comment);
static void CommentTrigger(char *trigger, char *relation, char *comments);

/*------------------------------------------------------------------
 * CommentObject --
 *
 * This routine is used to add the associated comment into
 * pg_description for the object specified by the paramters handed
 * to this routine. If the routine cannot determine an Oid to
 * associated with the parameters handed to this routine, an
 * error is thrown. Otherwise the comment is added to pg_description
 * by calling the CreateComments() routine. If the comments were
 * empty, CreateComments() will drop any comments associated with
 * the object.
 *------------------------------------------------------------------
*/

void CommentObject(int objtype, char *objname, char *objproperty,
		   List *objlist, char *comment) {

  switch (objtype) {
  case (INDEX):
  case (SEQUENCE):
  case (TABLE):
  case (VIEW):
    CommentRelation(objtype, objname, comment);
    break;
  case (COLUMN):
    CommentAttribute(objname, objproperty, comment);
    break;
  case (DATABASE):
    CommentDatabase(objname, comment);
    break;
  case (RULE):
    CommentRewrite(objname, comment);
    break;
  case (TYPE_P):
    CommentType(objname, comment);
    break;
  case (AGGREGATE):
    CommentAggregate(objname, objproperty, comment);
    break;
  case (FUNCTION):
    CommentProc(objname, objlist, comment);
    break;
  case (OPERATOR):
    CommentOperator(objname, objlist, comment);
    break;
  case (TRIGGER):
    CommentTrigger(objname, objproperty, comment);
    break;
  default:
    elog(ERROR, "An attempt was made to comment on a unknown type: %i",
	 objtype);
  }


}

/*------------------------------------------------------------------
 * CreateComments --
 *
 * This routine is handed the oid and the command associated
 * with that id and will insert, update, or delete (if the
 * comment is an empty string or a NULL pointer) the associated
 * comment from the system cataloge, pg_description.
 *
 *------------------------------------------------------------------
 */

void CreateComments(Oid oid, char *comment) {

  Relation description;
  TupleDesc tupDesc;
  HeapScanDesc scan;
  ScanKeyData entry;
  HeapTuple desctuple = NULL, searchtuple;
  Datum values[Natts_pg_description];
  char nulls[Natts_pg_description];
  char replaces[Natts_pg_description];
  bool modified = false;
  int i;

  /*** Open pg_description, form a new tuple, if necessary ***/

  description = heap_openr(DescriptionRelationName, RowExclusiveLock);
  tupDesc = description->rd_att;
  if ((comment != NULL) && (strlen(comment) > 0)) {
    for (i = 0; i < Natts_pg_description; i++) {
      nulls[i] = ' ';
      replaces[i] = 'r';
      values[i] = (Datum) NULL;
    }
    i = 0;
    values[i++] = ObjectIdGetDatum(oid);
    values[i++] = (Datum) fmgr(F_TEXTIN, comment);
  }

  /*** Now, open pg_description and attempt to find the old tuple ***/

  ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
			 ObjectIdGetDatum(oid));
  scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
  searchtuple = heap_getnext(scan, 0);

  /*** If a previous tuple exists, either delete or prep replacement ***/

  if (HeapTupleIsValid(searchtuple)) {

    /*** If the comment is blank, call heap_delete, else heap_update ***/

    if ((comment == NULL) || (strlen(comment) == 0)) {
      heap_delete(description, &searchtuple->t_self, NULL);
    } else {
      desctuple = heap_modifytuple(searchtuple, description, values,
				   nulls, replaces);
      heap_update(description, &searchtuple->t_self, desctuple, NULL);
      modified = TRUE;
    }

  } else {

	/*** Only if comment is non-blank do we form a new tuple ***/

	if ((comment != NULL) && (strlen(comment) > 0)) {
		desctuple = heap_formtuple(tupDesc, values, nulls);
		heap_insert(description, desctuple);
		modified = TRUE;
	}

  }

  /*** Complete the scan, update indices, if necessary ***/

{'fraction_non_alphanumeric': 0.19913978494623655, 'fraction_numerical': 0.002150537634408602, 'mean_word_length': 2.732263242375602, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6621663', 'n_tokens_mistral': 3359, 'n_tokens_neox': 3259, 'n_words': 1024}