Skip to content

File trigger_manager.h

File List > cubrid > src > object > trigger_manager.h

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

#ifndef _TRIGGER_MANAGER_H_
#define _TRIGGER_MANAGER_H_

#ident "$Id$"

#if defined (SERVER_MODE)
#error Does not belong to server module
#endif /* defined (SERVER_MODE) */

#include "memory_alloc.h"
#include "dbtype_def.h"
#include "class_object.h"

/*
 * TR_LOWEST_PRIORITY
 *
 * Note:
 *    This defines the default lowest priority for a trigger.
 *
 */

#define TR_LOWEST_PRIORITY          0.0

/*
 * TR_INFINITE_RECURSION_LEVEL
 *
 * Note:
 *    This number is used to indicate an infinite recursion level.
 *
 */

#define TR_MAX_RECURSION_LEVEL      32

/*
 * TR_MAX_PRINT_STRING
 *
 * Note:
 *    Maximum length of string available for use in the PRINT action.
 *
 */

#define TR_MAX_PRINT_STRING 2048

/* free_and_init routine */
#define tr_free_schema_cache_and_init(cache) \
  do \
    { \
      tr_free_schema_cache ((cache)); \
      (cache) = NULL; \
    } \
  while (0)

typedef struct tr_trigger
{
  DB_OBJECT *owner;
  DB_OBJECT *object;
  char *name;
  double priority;
  DB_TRIGGER_STATUS status;
  DB_TRIGGER_EVENT event;
  DB_OBJECT *class_mop;
  char *attribute;

  struct tr_activity *condition;
  struct tr_activity *action;

  char *current_refname;
  char *temp_refname;
  int class_attribute;

  /*
   * copy of the "cache coherency number" from the instance, used
   * to detect when the object gets modified and the trigger cache
   * needs to be re-evaluated
   */
  int chn;
  const char *comment;
  DB_DATETIME created_time;
  DB_DATETIME updated_time;
} TR_TRIGGER;



typedef struct tr_triglist
{
  struct tr_triglist *next;
  struct tr_triglist *prev;

  TR_TRIGGER *trigger;
  DB_OBJECT *target;        /* associated target instance */
} TR_TRIGLIST;

typedef struct tr_deferred_context
{
  struct tr_deferred_context *next;
  struct tr_deferred_context *prev;

  TR_TRIGLIST *head;
  TR_TRIGLIST *tail;

  void *savepoint_id;
} TR_DEFERRED_CONTEXT;

/*
 * TR_ACTIVITY
 *
 * Note:
 *    This is a substructure of the TR_TRIGGER structure and is used
 *    to hold the state of the condition and action activities.
 *
 */

typedef struct tr_activity TR_ACTIVITY;
struct tr_activity
{
  DB_TRIGGER_ACTION type;
  DB_TRIGGER_TIME time;
  char *source;         /* source text (or string for PRINT) */
  void *parser;         /* parser for statement */
  void *statement;      /* PT_NODE* of statement */
  int exec_cnt;         /* number of executions */
};

/*
 * TR_STATE
 *
 * Note:
 *    This structure is used to pass trigger execution state between
 *    tr_before, tr_after, and tr_abort.
 *
 */

typedef struct tr_state
{
  TR_TRIGLIST *triggers;
} TR_STATE;



typedef struct tr_schema_cache
{
  struct tr_schema_cache *next; /* all caches maintained on a global list */
  DB_OBJLIST *objects;      /* flattened object list */
  short compiled;       /* flag set when object list is compiled */
  unsigned short array_length;  /* number of elements in array */

  TR_TRIGLIST *triggers[1]; /* will actually allocate of variable length */
} TR_SCHEMA_CACHE;

/*
 * TR_CACHE_TYPE
 *
 * Note:
 *    This is used by the functions that allocate class caches.  Rather
 *    than passing in the length, just specify the type of cache and the
 *    tr_ module will allocate it of the appropriate length.
 *
 */

typedef enum
{
  TR_CACHE_CLASS,
  TR_CACHE_ATTRIBUTE
} TR_CACHE_TYPE;

/* TR_RECURSION_DECISION */
/* When analyzing the stack searching for recursion (which is forbidden),
 * there are three scenarios:
 * 1. no recursive activity found: continue
 * 2. we found a recursive trigger and we must return an error
 * 3. we found a recursive STATEMENT trigger. This is supposed to happen, and
 *    we should not continue the trigger firing chain, but we should allow
 *    the transaction to go on.
 */
typedef enum
{
  TR_DECISION_CONTINUE,
  TR_DECISION_HALT_WITH_ERROR,
  TR_DECISION_DO_NOT_CONTINUE
} TR_RECURSION_DECISION;

/* TRIGGER OBJECT ATTRIBUTES */
/*
 * Names of the trigger class and its attributes.
 */

extern const char *TR_CLASS_NAME;
extern const char *TR_ATT_UNIQUE_NAME;
extern const char *TR_ATT_NAME;
extern const char *TR_ATT_OWNER;
extern const char *TR_ATT_EVENT;
extern const char *TR_ATT_STATUS;
extern const char *TR_ATT_PRIORITY;
extern const char *TR_ATT_CLASS;
extern const char *TR_ATT_ATTRIBUTE;
extern const char *TR_ATT_CLASS_ATTRIBUTE;
extern const char *TR_ATT_CONDITION_TYPE;
extern const char *TR_ATT_CONDITION_TIME;
extern const char *TR_ATT_CONDITION;
extern const char *TR_ATT_ACTION_TYPE;
extern const char *TR_ATT_ACTION_TIME;
extern const char *TR_ATT_ACTION;
extern const char *TR_ATT_ACTION_OLD;
extern const char *TR_ATT_PROPERTIES;
extern const char *TR_ATT_COMMENT;
extern const char *TR_ATT_CREATED_TIME;
extern const char *TR_ATT_UPDATED_TIME;

extern int tr_Current_depth;
extern int tr_Maximum_depth;
extern bool tr_Invalid_transaction;
extern char tr_Invalid_transaction_trigger[SM_MAX_IDENTIFIER_LENGTH + 2];

extern bool tr_Trace;

extern TR_DEFERRED_CONTEXT *tr_Deferred_activities;
extern TR_DEFERRED_CONTEXT *tr_Deferred_activities_tail;

extern int tr_Recursion_level;
extern int tr_Recursion_level_max;

extern TR_TRIGLIST *tr_Deferred_triggers;
extern TR_TRIGLIST *tr_Deferred_triggers_tail;

/*
* EVAL_PREFIX, EVAL_SUFFIX
*
* Note:
*    This is used to replace the condition clause with an evaluate clause when creating or unloading a trigger.
*/

extern const char *EVAL_PREFIX;
extern const char *EVAL_SUFFIX;

/* INTERFACE FUNCTIONS */

/* Module control */

extern void tr_init (void);
extern void tr_final (void);
extern void tr_dump (FILE * fpp);   /* debug status */

/* Global trigger firing state : enable/disable functions */

extern bool tr_get_execution_state (void);
extern bool tr_set_execution_state (bool new_state);

/* Trigger creation */

extern DB_OBJECT *tr_create_trigger (const char *name, DB_TRIGGER_STATUS status, double priority,
                     DB_TRIGGER_EVENT event, DB_OBJECT * class_, const char *attribute,
                     DB_TRIGGER_TIME cond_time, const char *cond_source, DB_TRIGGER_TIME action_time,
                     DB_TRIGGER_ACTION action_type, const char *action_source, const char *comment);

/* Trigger location */

extern int tr_find_all_triggers (DB_OBJLIST ** list);
extern DB_OBJECT *tr_find_trigger (const char *name);
extern int tr_find_event_triggers (DB_TRIGGER_EVENT event, DB_OBJECT * class_, const char *attribute, bool active,
                   DB_OBJLIST ** list);

/* Check access rights */
extern int tr_check_authorization (DB_OBJECT * trigger_object, int alter_flag);

/* Trigger modification */

extern int tr_drop_trigger (DB_OBJECT * obj, bool call_from_api);
extern int tr_rename_trigger (DB_OBJECT * trigger_object, const char *name, bool call_from_api, bool deferred_flush);

extern int tr_set_status (DB_OBJECT * trigger_object, DB_TRIGGER_STATUS status, bool call_from_api);
extern int tr_set_priority (DB_OBJECT * trigger_object, double priority, bool call_from_api);
extern int tr_set_comment (DB_OBJECT * trigger_object, const char *comment, bool call_from_api);
extern int tr_update_trigger_timestamp (DB_OBJECT * trigger_object);

/* Parameters */
extern int tr_get_depth (void);
extern int tr_set_depth (int depth);
extern int tr_get_trace (void);
extern int tr_set_trace (bool trace);

/* Signaling */

extern int tr_prepare_statement (TR_STATE ** state_p, DB_TRIGGER_EVENT event, DB_OBJECT * class_, int attcount,
                 const char **attnames);
#if defined(ENABLE_UNUSED_FUNCTION)
extern int tr_prepare (TR_STATE ** state_p, TR_TRIGLIST * triggers);
#endif
extern int tr_prepare_class (TR_STATE ** state_p, TR_SCHEMA_CACHE * cache, MOP class_Mop, DB_TRIGGER_EVENT event);

extern int tr_before_object (TR_STATE * state, DB_OBJECT * current, DB_OBJECT * temp);
extern int tr_before (TR_STATE * state);
extern int tr_after_object (TR_STATE * state, DB_OBJECT * current, DB_OBJECT * temp);
extern int tr_after (TR_STATE * state);

extern void tr_abort (TR_STATE * state);

/* Transaction manager trigger hooks */

extern int tr_has_user_trigger (bool * has_user_trigger);
extern int tr_check_commit_triggers (DB_TRIGGER_TIME time);
extern void tr_check_rollback_triggers (DB_TRIGGER_TIME time);
#if defined(ENABLE_UNUSED_FUNCTION)
extern void tr_check_timeout_triggers (void);
#endif
extern void tr_check_abort_triggers (void);

#if defined(ENABLE_UNUSED_FUNCTION)
extern int tr_set_savepoint (void *savepoint_id);
extern int tr_abort_to_savepoint (void *savepoint_id);
#endif

/* Deferred activity control */

extern int tr_execute_deferred_activities (DB_OBJECT * trigger_object, DB_OBJECT * target);
extern int tr_drop_deferred_activities (DB_OBJECT * trigger_object, DB_OBJECT * target);

/* Trigger object accessors */

extern int tr_trigger_name (DB_OBJECT * trigger_object, char **name);
extern int tr_trigger_status (DB_OBJECT * trigger_object, DB_TRIGGER_STATUS * status);
extern int tr_trigger_priority (DB_OBJECT * trigger_object, double *priority);
extern int tr_trigger_event (DB_OBJECT * trigger_object, DB_TRIGGER_EVENT * event);
extern int tr_trigger_class (DB_OBJECT * trigger_object, DB_OBJECT ** class_);
extern int tr_trigger_attribute (DB_OBJECT * trigger_object, char **attribute);
extern int tr_trigger_condition (DB_OBJECT * trigger_object, char **condition);
extern int tr_trigger_condition_time (DB_OBJECT * trigger_object, DB_TRIGGER_TIME * tr_time);
extern int tr_trigger_action (DB_OBJECT * trigger_object, char **action);
extern int tr_trigger_action_time (DB_OBJECT * trigger_object, DB_TRIGGER_TIME * tr_time);
extern int tr_trigger_action_type (DB_OBJECT * trigger_object, DB_TRIGGER_ACTION * type);
extern int tr_trigger_comment (DB_OBJECT * trigger_objet, char **comment);
extern int tr_is_trigger (DB_OBJECT * trigger_object, int *status);

/* Special schema functions */

extern TR_SCHEMA_CACHE *tr_make_schema_cache (TR_CACHE_TYPE type, DB_OBJLIST * objects);
extern TR_SCHEMA_CACHE *tr_copy_schema_cache (TR_SCHEMA_CACHE * cache, MOP filter_class);
extern int tr_merge_schema_cache (TR_SCHEMA_CACHE * destination, TR_SCHEMA_CACHE * source);
extern int tr_empty_schema_cache (TR_SCHEMA_CACHE * cache);
extern void tr_free_schema_cache (TR_SCHEMA_CACHE * cache);

extern int tr_get_cache_objects (TR_SCHEMA_CACHE * cache, DB_OBJLIST ** list);
extern int tr_validate_schema_cache (TR_SCHEMA_CACHE * cache, MOP class_mop);

extern int tr_active_schema_cache (MOP class_mop, TR_SCHEMA_CACHE * cache, DB_TRIGGER_EVENT event_type,
                   bool * has_event_type_triggers);
extern int tr_delete_schema_cache (TR_SCHEMA_CACHE * cache, DB_OBJECT * class_object);

extern int tr_add_cache_trigger (TR_SCHEMA_CACHE * cache, DB_OBJECT * trigger_object);
extern int tr_drop_cache_trigger (TR_SCHEMA_CACHE * cache, DB_OBJECT * trigger_object);

extern int tr_delete_triggers_for_class (TR_SCHEMA_CACHE ** cache, DB_OBJECT * class_object);


/* Shouldn't be external any more ? */

extern TR_TRIGGER *tr_map_trigger (DB_OBJECT * object, int fetch);
extern int tr_unmap_trigger (TR_TRIGGER * trigger);

/* Cache control */

extern int tr_update_user_cache (void);
extern void tr_invalidate_user_cache (void);

/* Migration and information functions */

extern const char *tr_time_as_string (DB_TRIGGER_TIME time);
extern const char *tr_event_as_string (DB_TRIGGER_EVENT event);
extern const char *tr_status_as_string (DB_TRIGGER_STATUS status);
#if defined(ENABLE_UNUSED_FUNCTION)
extern int tr_dump_all_triggers (FILE * fp, bool quoted_id_flag);
#endif
extern void tr_free_trigger_list (TR_TRIGLIST * list);
extern const char *tr_get_class_name (void);

#if defined(ENABLE_UNUSED_FUNCTION)
extern int tr_reset_schema_cache (TR_SCHEMA_CACHE * cache);
extern int tr_downcase_all_trigger_info (void);
#endif

/* Remove appended trigger evaluate info */
extern char *remove_appended_trigger_evaluate (char *trigger_stmt_str, int with_evaluate);

#endif /* _TRIGGER_MANAGER_H_ */