Contiki-NG
aql-exec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Query execution functions for AQL.
36  * \author
37  * Nicolas Tsiftes <nvt@sics.se>
38  */
39 
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 
44 #define DEBUG DEBUG_NONE
45 #include "net/ipv6/uip-debug.h"
46 
47 #include "index.h"
48 #include "relation.h"
49 #include "result.h"
50 #include "aql.h"
51 
52 static aql_adt_t adt;
53 
54 static void
55 clear_handle(db_handle_t *handle)
56 {
57  memset(handle, 0, sizeof(*handle));
58 
59  handle->result_rel = NULL;
60  handle->left_rel = NULL;
61  handle->right_rel = NULL;
62  handle->join_rel = NULL;
63 }
64 
65 static db_result_t
66 aql_execute(db_handle_t *handle, aql_adt_t *adt)
67 {
68  uint8_t optype;
69  int first_rel_arg;
70  db_result_t result;
71  relation_t *rel;
72  aql_attribute_t *attr;
73  attribute_t *relattr;
74 
75  optype = AQL_GET_TYPE(adt);
76  if(optype == AQL_TYPE_NONE) {
77  /* No-ops always succeed. These can be generated by
78  empty lines or comments in the query language. */
79  return DB_OK;
80  }
81 
82  /* If the ASSIGN flag is set, the first relation in the array is
83  the desired result relation. */
84  first_rel_arg = !!(adt->flags & AQL_FLAG_ASSIGN);
85 
86  if(optype != AQL_TYPE_CREATE_RELATION &&
87  optype != AQL_TYPE_REMOVE_RELATION &&
88  optype != AQL_TYPE_JOIN) {
89  rel = relation_load(adt->relations[first_rel_arg]);
90  if(rel == NULL) {
91  return DB_NAME_ERROR;
92  }
93  } else {
94  rel = NULL;
95  }
96 
97  result = DB_RELATIONAL_ERROR;
98  switch(optype) {
99  case AQL_TYPE_CREATE_ATTRIBUTE:
100  attr = &adt->attributes[0];
101  if(relation_attribute_add(rel, DB_STORAGE, attr->name, attr->domain,
102  attr->element_size) != NULL) {
103  result = DB_OK;
104  }
105  break;
106  case AQL_TYPE_CREATE_INDEX:
107  relattr = relation_attribute_get(rel, adt->attributes[0].name);
108  if(relattr == NULL) {
109  result = DB_NAME_ERROR;
110  break;
111  }
112  result = index_create(AQL_GET_INDEX_TYPE(adt), rel, relattr);
113  break;
114  case AQL_TYPE_CREATE_RELATION:
115  if(relation_create(adt->relations[0], DB_STORAGE) != NULL) {
116  result = DB_OK;
117  }
118  break;
119  case AQL_TYPE_REMOVE_ATTRIBUTE:
120  result = relation_attribute_remove(rel, adt->attributes[0].name);
121  break;
122  case AQL_TYPE_REMOVE_INDEX:
123  relattr = relation_attribute_get(rel, adt->attributes[0].name);
124  if(relattr != NULL) {
125  if(relattr->index != NULL) {
126  result = index_destroy(relattr->index);
127  } else {
128  result = DB_OK;
129  }
130  } else {
131  result = DB_NAME_ERROR;
132  }
133  break;
134  case AQL_TYPE_REMOVE_RELATION:
135  result = relation_remove(adt->relations[0], 1);
136  break;
137 #if DB_FEATURE_REMOVE
138  case AQL_TYPE_REMOVE_TUPLES:
139  /* Overwrite the attribute array with a full copy of the original
140  relation's attributes. */
141  adt->attribute_count = 0;
142  for(relattr = list_head(rel->attributes);
143  relattr != NULL;
144  relattr = relattr->next) {
145  AQL_ADD_ATTRIBUTE(adt, relattr->name, DOMAIN_UNSPECIFIED, 0);
146  }
147  AQL_SET_FLAG(adt, AQL_FLAG_INVERSE_LOGIC);
148 #endif /* DB_FEATURE_REMOVE */
149  case AQL_TYPE_SELECT:
150  if(handle == NULL) {
151  result = DB_ARGUMENT_ERROR;
152  break;
153  }
154  result = relation_select(handle, rel, adt);
155  break;
156  case AQL_TYPE_INSERT:
157  result = relation_insert(rel, adt->values);
158  break;
159 #if DB_FEATURE_JOIN
160  case AQL_TYPE_JOIN:
161  if(handle == NULL) {
162  result = DB_ARGUMENT_ERROR;
163  break;
164  }
165  handle->left_rel = relation_load(adt->relations[first_rel_arg]);
166  if(handle->left_rel == NULL) {
167  break;
168  }
169  handle->right_rel = relation_load(adt->relations[first_rel_arg + 1]);
170  if(handle->right_rel == NULL) {
171  relation_release(handle->left_rel);
172  break;
173  }
174  result = relation_join(handle, adt);
175  break;
176 #endif /* DB_FEATURE_JOIN */
177  default:
178  break;
179  }
180 
181  if(rel != NULL) {
182  if(handle == NULL || !(handle->flags & DB_HANDLE_FLAG_PROCESSING)) {
183  relation_release(rel);
184  }
185  }
186 
187  return result;
188 }
189 
190 db_result_t
191 db_query(db_handle_t *handle, const char *format, ...)
192 {
193  va_list ap;
194  char query_string[AQL_MAX_QUERY_LENGTH];
195 
196  va_start(ap, format);
197  vsnprintf(query_string, sizeof(query_string), format, ap);
198  va_end(ap);
199 
200  if(handle != NULL) {
201  clear_handle(handle);
202  }
203 
204  if(AQL_ERROR(aql_parse(&adt, query_string))) {
205  return DB_PARSING_ERROR;
206  }
207 
208  /*aql_optimize(&adt);*/
209 
210  return aql_execute(handle, &adt);
211 }
212 
213 db_result_t
214 db_process(db_handle_t *handle)
215 {
216  uint8_t optype;
217 
218  optype = ((aql_adt_t *)handle->adt)->optype;
219 
220  switch(optype) {
221 #if DB_FEATURE_REMOVE
222  case AQL_TYPE_REMOVE_TUPLES:
223  return relation_process_remove(handle);
224  break;
225 #endif
226  case AQL_TYPE_SELECT:
227  return relation_process_select(handle);
228  break;
229 #if DB_FEATURE_JOIN
230  case AQL_TYPE_JOIN:
231  return relation_process_join(handle);
232 #endif /* DB_FEATURE_JOIN */
233  default:
234  break;
235  }
236 
237  PRINTF("DB: Invalid operation type: %d\n", optype);
238 
239  return DB_INCONSISTENCY_ERROR;
240 }
A set of debugging macros for the IP stack
Definitions and declarations for AQL, the Antelope Query Language.
Declarations for the result acquisition API.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82