CUBRID Engine  latest
esql_gadget.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * esql_gadget.c - Gadget Interface
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include "db.h"
29 #include "esql_gadget.h"
30 #include "parser.h"
31 #include "dbtype.h"
32 
33 #define NOT_FOUND -1
34 
35 static int gadget_attr_index (DB_GADGET * gadget, const char *attr_name);
36 
37 /*
38  * db_gadget_create() - Look up the class and build attribute descriptors for
39  * all of the supplied attributes.
40  *
41  * return : gadget pointer
42  * class_name(in): name of class for which to create gadget
43  * attribute_names(in): NULL-terminated array containing names of attributes
44  * the user will supply values for
45  *
46  * note : Using gadgets to insert into views is not supported due to
47  * the special casing and extra checks required and our inability to
48  * support check option.
49  */
50 DB_GADGET *
51 db_gadget_create (const char *class_name, const char *attribute_names[])
52 {
53  DB_OBJECT *class_;
54  DB_GADGET *gadget = NULL;
55  const char **att_name = attribute_names;
56  int listlen = 0, i;
57 
58 
59  if (class_name == NULL || (class_ = db_find_class (class_name)) == NULL)
60  {
62  goto error;
63  }
64 
65  if (db_is_vclass (class_))
66  {
68  goto error;
69  }
70 
71  gadget = (DB_GADGET *) malloc (sizeof (DB_GADGET));
72  if (gadget == NULL)
73  {
74  goto error;
75  }
76  gadget->attrs = NULL;
77  gadget->class_ = class_;
78 
79  while (att_name[listlen])
80  {
81  listlen++;
82  }
83  gadget->num_attrs = listlen;
84 
85  /* If no attribute list was supplied, assume all attributes */
86  if (listlen == 0)
87  {
88  DB_ATTRIBUTE *attribute = db_get_attributes (gadget->class_);
89 
90  if (attribute == NULL)
91  {
92  goto error;
93  }
94  for (; attribute; attribute = db_attribute_next (attribute))
95  {
96  gadget->num_attrs++;
97  }
98  }
99 
100  gadget->attrs = (ATTR_VAL *) malloc ((gadget->num_attrs + 1) * sizeof (ATTR_VAL));
101  if (gadget->num_attrs > 0 && gadget->attrs == NULL)
102  {
103  goto error;
104  }
105 
106  for (i = 0; i < gadget->num_attrs; i++)
107  {
108  gadget->attrs[i].attr_desc = NULL;
109  gadget->attrs[i].value = NULL;
110  }
111 
112  if (listlen == 0)
113  {
114  DB_ATTRIBUTE *attribute = db_get_attributes (gadget->class_);
115 
116  if (attribute == NULL)
117  {
118  goto error;
119  }
120  for (i = 0; attribute; i++, attribute = db_attribute_next (attribute))
121  {
123  (class_, db_attribute_name (attribute), false, true, &gadget->attrs[i].attr_desc))
124  {
125  goto error;
126  }
127  }
128  }
129  else
130  {
131  for (i = 0, att_name = attribute_names; i < gadget->num_attrs; i++, att_name++)
132  {
133  if (gadget_attr_index (gadget, *att_name) != NOT_FOUND)
134  {
136  goto error;
137  }
138  if (db_get_attribute_descriptor (class_, *att_name, false, true, &gadget->attrs[i].attr_desc))
139  {
140  goto error;
141  }
142  }
143  }
144 
145  return gadget;
146 
147 error:
148  if (gadget)
149  {
150  db_gadget_destroy (gadget);
151  }
152  return NULL;
153 }
154 
155 /*
156  * db_gadget_destroy() - Tear down the the given gadget. The gadget owns any
157  * DB_VALUEs that have been supplied via db_gadget_bind, so it should clear
158  * them before returning.
159  * return : void
160  * gadget(in): gadget pointer to tear down
161  */
162 void
164 {
165  int i;
166 
167  if (gadget == NULL)
168  {
169  return;
170  }
171 
172  for (i = 0; gadget->attrs && (i < gadget->num_attrs); i++)
173  {
174  if (gadget->attrs[i].attr_desc)
175  {
177  }
178  if (gadget->attrs[i].value)
179  {
180  (void) db_value_clear (gadget->attrs[i].value);
181  free_and_init (gadget->attrs[i].value);
182  }
183  }
184 
185  if (gadget->attrs)
186  {
187  free_and_init (gadget->attrs);
188  }
189  free_and_init (gadget);
190 
191  return;
192 }
193 
194 /*
195  * db_gadget_bind() - Associate the given value with the given attribute.
196  * A NULL DB_VALUE pointer indicates that any previous binding should be
197  * erased. The incoming DB_VALUE is coerced to the proper domain before
198  * being stored so as to avoid coercion during repeated inserts.
199  * return : error code
200  * gadget(in): gadget containing insert data
201  * attribute_name(in): number of db_values in dbvals array
202  * dbval(in): array containing values for unbound attributes
203  */
204 int
205 db_gadget_bind (DB_GADGET * gadget, const char *attribute_name, DB_VALUE * dbval)
206 {
207  int i = 0;
208 
209  if (gadget == NULL || gadget->class_ == NULL)
210  {
212  return ER_GADGET_INVALID;
213  }
214 
215  if (attribute_name == NULL || (i = gadget_attr_index (gadget, attribute_name)) == NOT_FOUND)
216  {
218  db_get_class_name (gadget->class_));
220  }
221 
222  /* Free any previous value before rebinding */
223  if (gadget->attrs[i].value != NULL)
224  {
225  db_value_clear (gadget->attrs[i].value);
226  free_and_init (gadget->attrs[i].value);
227  }
228 
229  /* A null dbval indicates previous binding should be erased */
230  if (dbval == NULL)
231  {
232  return NO_ERROR;
233  }
234 
235  gadget->attrs[i].value = (DB_VALUE *) malloc (sizeof (DB_VALUE));
236  if (gadget->attrs[i].value == NULL)
237  {
240  }
241 
242  return tp_value_coerce (dbval, gadget->attrs[i].value, db_attdesc_domain (gadget->attrs[i].attr_desc));
243 }
244 
245 /*
246  * db_gadget_exec() - Creates a new instance using templates and the
247  * descriptors acquired when the DB_GADGET was initialized.
248  *
249  * return : pointer to inserted instance object
250  * gadget(in): gadget containing insert data
251  * num_dbvals(in): number of db_values in dbvals array
252  * dbvals(in): array containing values for unbound attributes
253  */
254 DB_OBJECT *
255 db_gadget_exec (DB_GADGET * gadget, int num_dbvals, DB_VALUE dbvals[])
256 {
257  int dbvals_index = 0;
258  DB_VALUE *value = NULL;
259  DB_OTMPL *otemplate = NULL;
260  DB_OBJECT *obj = NULL;
261  int num_vals = num_dbvals;
262  int i;
263 
264  if (gadget == NULL || gadget->class_ == NULL)
265  {
267  goto error;
268  }
269 
270  otemplate = dbt_create_object_internal (gadget->class_);
271  if (otemplate == NULL)
272  {
273  goto error;
274  }
275 
276  for (i = 0; i < gadget->num_attrs; i++)
277  {
278  value = gadget->attrs[i].value;
279  if (value == NULL)
280  {
281  if (dbvals_index < num_dbvals)
282  {
283  value = &dbvals[dbvals_index++];
284  }
285  }
286 
287  if (value == NULL)
288  {
289  for (i = 0; i < gadget->num_attrs; i++)
290  {
291  if (gadget->attrs[i].value)
292  {
293  num_vals++;
294  }
295  }
297  goto error;
298  }
299 
300  if (dbt_dput_internal (otemplate, gadget->attrs[i].attr_desc, value) != NO_ERROR)
301  {
302  goto error;
303  }
304  }
305 
306  obj = dbt_finish_object (otemplate);
307  if (obj == NULL)
308  {
309  goto error;
310  }
311 
312  return obj;
313 
314 error:
315  if (otemplate)
316  {
317  dbt_abort_object (otemplate);
318  }
319  return NULL;
320 }
321 
322 /*
323  * gadget_attr_index() - Perform case-insensitive search for given attribute
324  * and return its position within the gadget if found.
325  * return : attribute's index
326  * gadget(in): gadget to search
327  * attr_names(in): name of attributes to find index of
328  */
329 static int
330 gadget_attr_index (DB_GADGET * gadget, const char *attr_name)
331 {
332  int i;
333 
334  for (i = 0; i < gadget->num_attrs; i++)
335  {
336  if (gadget->attrs[i].attr_desc
337  && pt_str_compare (attr_name, gadget->attrs[i].attr_desc->name, CASE_INSENSITIVE) == 0)
338  {
339  return i;
340  }
341  }
342 
343  return NOT_FOUND;
344 }
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
TP_DOMAIN_STATUS tp_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
DB_OBJECT * db_gadget_exec(DB_GADGET *gadget, int num_dbvals, DB_VALUE dbvals[])
Definition: esql_gadget.c:255
#define NO_ERROR
Definition: error_code.h:46
int db_gadget_bind(DB_GADGET *gadget, const char *attribute_name, DB_VALUE *dbval)
Definition: esql_gadget.c:205
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
static const char * attribute_name(PARSER_CONTEXT *parser, PT_NODE *att)
DB_OBJECT * dbt_finish_object(DB_OTMPL *def)
Definition: db_obj.c:560
void dbt_abort_object(DB_OTMPL *def)
Definition: db_obj.c:616
DB_ATTDESC * attr_desc
Definition: esql_gadget.h:37
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
void db_gadget_destroy(DB_GADGET *gadget)
Definition: esql_gadget.c:163
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
#define ER_LC_UNKNOWN_CLASSNAME
Definition: error_code.h:121
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define ER_GADGET_INVALID
Definition: error_code.h:886
#define ER_GADGET_ATTRS_VALS_NE
Definition: error_code.h:887
void db_free_attribute_descriptor(DB_ATTDESC *descriptor)
Definition: db_obj.c:835
DB_GADGET * db_gadget_create(const char *class_name, const char *attribute_names[])
Definition: esql_gadget.c:51
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
#define NOT_FOUND
Definition: esql_gadget.c:33
#define ER_OBJ_DUPLICATE_ASSIGNMENT
Definition: error_code.h:298
DB_OBJECT * class_
Definition: esql_gadget.h:43
int db_get_attribute_descriptor(DB_OBJECT *obj, const char *attname, int class_attribute, int for_update, DB_ATTDESC **descriptor)
Definition: db_obj.c:763
int pt_str_compare(const char *p, const char *q, CASE_SENSITIVENESS case_flag)
#define NULL
Definition: freelistheap.h:34
int num_attrs
Definition: esql_gadget.h:44
struct attr_val ATTR_VAL
Definition: esql_gadget.h:34
DB_DOMAIN * db_attdesc_domain(DB_ATTDESC *desc)
Definition: db_obj.c:790
static void error(const char *msg)
Definition: gencat.c:331
#define ER_SM_UNKNOWN_ATTRIBUTE
Definition: error_code.h:569
DB_OTMPL * dbt_create_object_internal(DB_OBJECT *classobj)
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define ER_GADGET_NO_VCLASSES
Definition: error_code.h:888
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static int gadget_attr_index(DB_GADGET *gadget, const char *attr_name)
Definition: esql_gadget.c:330
int dbt_dput_internal(DB_OTMPL *def, DB_ATTDESC *attribute, DB_VALUE *value)
Definition: db_obj.c:977
int i
Definition: dynamic_load.c:954
ATTR_VAL * attrs
Definition: esql_gadget.h:45
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
DB_VALUE * value
Definition: esql_gadget.h:38