1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NDB_TRIGGER_DEFINITIONS_H
26 #define NDB_TRIGGER_DEFINITIONS_H
27 
28 #include <ndb_global.h>
29 #include "ndb_limits.h"
30 #include <Bitmask.hpp>
31 #include <signaldata/DictTabInfo.hpp>
32 
33 #define ILLEGAL_TRIGGER_ID ((Uint32)(~0))
34 
35 struct TriggerType {
36   enum Value {
37     //CONSTRAINT            = 0,
38     SECONDARY_INDEX         = DictTabInfo::HashIndexTrigger,
39     FK_PARENT               = DictTabInfo::FKParentTrigger,
40     FK_CHILD                = DictTabInfo::FKChildTrigger,
41     //SCHEMA_UPGRADE        = 3,
42     //API_TRIGGER           = 4,
43     //SQL_TRIGGER           = 5,
44     SUBSCRIPTION          = DictTabInfo::SubscriptionTrigger,
45     READ_ONLY_CONSTRAINT  = DictTabInfo::ReadOnlyConstraint,
46     ORDERED_INDEX         = DictTabInfo::IndexTrigger,
47 
48     SUBSCRIPTION_BEFORE   = 9, // Only used by TUP/SUMA, should be REMOVED!!
49     REORG_TRIGGER         = DictTabInfo::ReorgTrigger
50   };
51 };
52 
53 struct TriggerActionTime {
54   enum Value {
55     TA_BEFORE   = 0, /* Immediate, before operation */
56     TA_AFTER    = 1, /* Immediate, after operation */
57     TA_DEFERRED = 2, /* Before commit */
58     TA_DETACHED = 3, /* After commit in a separate transaction, NYI */
59     TA_CUSTOM   = 4  /* Hardcoded per TriggerType */
60   };
61 };
62 
63 struct TriggerEvent {
64   /** TableEvent must match 1 << TriggerEvent */
65   enum Value {
66     TE_INSERT = 0,
67     TE_DELETE = 1,
68     TE_UPDATE = 2,
69     TE_CUSTOM = 3    /* Hardcoded per TriggerType */
70   };
71 };
72 
73 struct TriggerInfo {
74   TriggerType::Value triggerType;
75   TriggerActionTime::Value triggerActionTime;
76   TriggerEvent::Value triggerEvent;
77   bool monitorReplicas;
78   bool monitorAllAttributes;
79   bool reportAllMonitoredAttributes;
80 
81   // static methods
82 
83   // get/set bits in Uint32
84   static TriggerType::Value
getTriggerTypeTriggerInfo85   getTriggerType(const Uint32& info) {
86     const Uint32 val = BitmaskImpl::getField(1, &info, 0, 8);
87     return (TriggerType::Value)val;
88   }
89   static void
setTriggerTypeTriggerInfo90   setTriggerType(Uint32& info, TriggerType::Value val) {
91     BitmaskImpl::setField(1, &info, 0, 8, (Uint32)val);
92   }
93   static TriggerActionTime::Value
getTriggerActionTimeTriggerInfo94   getTriggerActionTime(const Uint32& info) {
95     const Uint32 val = BitmaskImpl::getField(1, &info, 8, 8);
96     return (TriggerActionTime::Value)val;
97   }
98   static void
setTriggerActionTimeTriggerInfo99   setTriggerActionTime(Uint32& info, TriggerActionTime::Value val) {
100     BitmaskImpl::setField(1, &info, 8, 8, (Uint32)val);
101   }
102   static TriggerEvent::Value
getTriggerEventTriggerInfo103   getTriggerEvent(const Uint32& info) {
104     const Uint32 val = BitmaskImpl::getField(1, &info, 16, 8);
105     return (TriggerEvent::Value)val;
106   }
107   static void
setTriggerEventTriggerInfo108   setTriggerEvent(Uint32& info, TriggerEvent::Value val) {
109     BitmaskImpl::setField(1, &info, 16, 8, (Uint32)val);
110   }
111   static bool
getMonitorReplicasTriggerInfo112   getMonitorReplicas(const Uint32& info) {
113     return BitmaskImpl::getField(1, &info, 24, 1);
114   }
115   static void
setMonitorReplicasTriggerInfo116   setMonitorReplicas(Uint32& info, bool val) {
117     BitmaskImpl::setField(1, &info, 24, 1, val);
118   }
119   static bool
getMonitorAllAttributesTriggerInfo120   getMonitorAllAttributes(const Uint32& info) {
121     return BitmaskImpl::getField(1, &info, 25, 1);
122   }
123   static void
setMonitorAllAttributesTriggerInfo124   setMonitorAllAttributes(Uint32& info, bool val) {
125     BitmaskImpl::setField(1, &info, 25, 1, val);
126   }
127   static bool
getReportAllMonitoredAttributesTriggerInfo128   getReportAllMonitoredAttributes(const Uint32& info) {
129     return BitmaskImpl::getField(1, &info, 26, 1);
130   }
131   static void
setReportAllMonitoredAttributesTriggerInfo132   setReportAllMonitoredAttributes(Uint32& info, bool val) {
133     BitmaskImpl::setField(1, &info, 26, 1, val);
134   }
135 
136   // convert between Uint32 and struct
137   static void
packTriggerInfoTriggerInfo138   packTriggerInfo(Uint32& val, const TriggerInfo& str) {
139     val = 0;
140     setTriggerType(val, str.triggerType);
141     setTriggerActionTime(val, str.triggerActionTime);
142     setTriggerEvent(val, str.triggerEvent);
143     setMonitorReplicas(val, str.monitorReplicas);
144     setMonitorAllAttributes(val, str.monitorAllAttributes);
145     setReportAllMonitoredAttributes(val, str.reportAllMonitoredAttributes);
146   }
147   static void
unpackTriggerInfoTriggerInfo148   unpackTriggerInfo(const Uint32& val, TriggerInfo& str) {
149     str.triggerType = getTriggerType(val);
150     str.triggerActionTime = getTriggerActionTime(val);
151     str.triggerEvent = getTriggerEvent(val);
152     str.monitorReplicas = getMonitorReplicas(val);
153     str.monitorAllAttributes = getMonitorAllAttributes(val);
154     str.reportAllMonitoredAttributes = getReportAllMonitoredAttributes(val);
155   }
156 
157   // for debug print
158   static const char*
triggerTypeNameTriggerInfo159   triggerTypeName(Uint32 val) {
160     switch (val) {
161     case TriggerType::SECONDARY_INDEX:
162       return "SECONDARY_INDEX";
163     case TriggerType::SUBSCRIPTION:
164       return "SUBSCRIPTION";
165     case TriggerType::READ_ONLY_CONSTRAINT:
166       return "READ_ONLY_CONSTRAINT";
167     case TriggerType::ORDERED_INDEX:
168       return "ORDERED_INDEX";
169     case TriggerType::SUBSCRIPTION_BEFORE:
170       return "SUBSCRIPTION_BEFORE";
171     }
172     return "UNKNOWN";
173   }
174   static const char*
triggerActionTimeNameTriggerInfo175   triggerActionTimeName(Uint32 val) {
176     switch (val) {
177     case TriggerActionTime::TA_BEFORE:
178       return "TA_BEFORE";
179     case TriggerActionTime::TA_AFTER:
180       return "TA_AFTER";
181     case TriggerActionTime::TA_DEFERRED:
182       return "TA_DEFERRED";
183     case TriggerActionTime::TA_DETACHED:
184       return "TA_DETACHED";
185     case TriggerActionTime::TA_CUSTOM:
186       return "TA_CUSTOM";
187     }
188     return "UNKNOWN";
189   }
190   static const char*
triggerEventNameTriggerInfo191   triggerEventName(Uint32 val) {
192     switch (val) {
193     case TriggerEvent::TE_INSERT:
194       return "TE_INSERT";
195     case TriggerEvent::TE_DELETE:
196       return "TE_DELETE";
197     case TriggerEvent::TE_UPDATE:
198       return "TE_UPDATE";
199     case TriggerEvent::TE_CUSTOM:
200       return "TE_CUSTOM";
201     }
202     return "UNKNOWN";
203   }
204 };
205 
206 struct NoOfFiredTriggers
207 {
208   STATIC_CONST( DeferredUKBit = (Uint32(1) << 31) );
209   STATIC_CONST( DeferredFKBit = (Uint32(1) << 30) );
210   STATIC_CONST( DeferredBits = (DeferredUKBit | DeferredFKBit));
211 
getFiredCountNoOfFiredTriggers212   static Uint32 getFiredCount(Uint32 v) {
213     return v & ~(Uint32(DeferredBits));
214   }
getDeferredUKBitNoOfFiredTriggers215   static Uint32 getDeferredUKBit(Uint32 v) {
216     return (v & Uint32(DeferredUKBit)) != 0;
217   }
setDeferredUKBitNoOfFiredTriggers218   static void setDeferredUKBit(Uint32 & v) {
219     v |= Uint32(DeferredUKBit);
220   }
getDeferredFKBitNoOfFiredTriggers221   static Uint32 getDeferredFKBit(Uint32 v) {
222     return (v & Uint32(DeferredFKBit)) != 0;
223   }
setDeferredFKBitNoOfFiredTriggers224   static void setDeferredFKBit(Uint32 & v) {
225     v |= Uint32(DeferredFKBit);
226   }
227 
getDeferredAllSetNoOfFiredTriggers228   static bool getDeferredAllSet(Uint32 v) {
229     return (v & Uint32(DeferredBits)) == DeferredBits;
230   }
231 };
232 
233 struct TriggerPreCommitPass
234 {
235   /**
236    * When using deferred triggers...
237    * - UK are split into 2 passes...
238    * - FK needs to be evaluated *after* UK has been processed
239    *   as it (can) use UK
240    *
241    * When having cascadeing FK's they can provoke UK updates
242    *   in such cases...the passes are
243    *   N * (PASS_MAX + 1) + PASS
244    */
245   enum
246   {
247     UK_PASS_0 = 0,
248     UK_PASS_1 = 1,
249     FK_PASS_0 = 7, // leave some room...(unsure if it's needed)
250     TPCP_PASS_MAX = 15
251   };
252 };
253 
254 #endif
255