]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/include/openils/oils_buildq.h
1. Degrade gracefully when the database connection dies.
[working/Evergreen.git] / Open-ILS / include / openils / oils_buildq.h
1 /**
2         @file buildquery.h
3         @brief Header for routines for building database queries.
4 */
5
6 #ifndef OILS_BUILDQ_H
7 #define OILS_BUILDQ_H
8
9 #include "opensrf/osrf_json.h"
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15 struct StoredQ_;
16 typedef struct StoredQ_ StoredQ;
17
18 struct FromRelation_;
19 typedef struct FromRelation_ FromRelation;
20
21 struct SelectItem_;
22 typedef struct SelectItem_ SelectItem;
23
24 struct BindVar_;
25 typedef struct BindVar_ BindVar;
26
27 struct CaseBranch_;
28 typedef struct CaseBranch_ CaseBranch;
29
30 struct Datatype_;
31 typedef struct Datatype_ Datatype;
32
33 struct Expression_;
34 typedef struct Expression_ Expression;
35
36 struct QSeq_;
37 typedef struct QSeq_ QSeq;
38
39 struct OrderItem_;
40 typedef struct OrderItem_ OrderItem;
41
42 struct BuildSQLState_;
43 typedef struct BuildSQLState_ BuildSQLState;
44
45 struct IdNode_;
46 typedef struct IdNode_ IdNode;
47
48 /**
49         @brief Stores various things related to the construction of an SQL query.
50         
51         This struct carries around various bits and scraps of context for constructing and
52         executing an SQL query.  It also provides a way for buildSQLQuery() to return more than
53         one kind of thing to its caller.  In particular it can return a status code, a list of
54         error messages, and (if there is no error) an SQL string.
55 */
56 struct BuildSQLState_ {
57         dbi_conn dbhandle;            /**< Handle for the database connection */
58         dbi_result result;            /**< Reference to current row or result set */
59         int error;                    /**< Boolean; true if an error has occurred */
60         osrfStringArray* error_msgs;  /**< Descriptions of errors, if any */
61         growing_buffer* sql;          /**< To hold the constructed query */
62         osrfHash* bindvar_list;       /**< List of bind variables used by this query, each with
63                                            a pointer to the corresponding BindVar. */
64         IdNode* query_stack;          /**< For avoiding infinite recursion of nested queries */
65         IdNode* expr_stack;           /**< For avoiding infinite recursion of nested expressions */
66         IdNode* from_stack;           /**< For avoiding infinite recursion of from clauses */
67         int indent;                   /**< For prettifying SQL output: level of indentation */
68         int defaults_usable;          /**< Boolean; if true, we can use unconfirmed default
69                                            values for bind variables */
70         int values_required;          /**< Boolean: if true, we need values for a bind variables */
71         int panic;                    /**< Boolean: set to true if database connection dies */
72 };
73
74 typedef enum {
75         QT_SELECT,
76         QT_UNION,
77         QT_INTERSECT,
78         QT_EXCEPT
79 } QueryType;
80
81 struct StoredQ_ {
82         StoredQ*      next;
83         int           id;
84         QueryType     type;
85         int           use_all;        /**< Boolean */
86         int           use_distinct;   /**< Boolean */
87         FromRelation* from_clause;
88         Expression*   where_clause;
89         SelectItem*   select_list;
90         QSeq*         child_list;
91         Expression*   having_clause;
92         OrderItem*    order_by_list;
93 };
94
95 typedef enum {
96         FRT_RELATION,
97         FRT_SUBQUERY,
98         FRT_FUNCTION
99 } FromRelationType;
100
101 typedef enum {
102         JT_NONE,
103         JT_INNER,
104         JT_LEFT,
105         JT_RIGHT,
106         JT_FULL
107 } JoinType;
108
109 struct FromRelation_ {
110         FromRelation*    next;
111         int              id;
112         FromRelationType type;
113         char*            table_name;
114         char*            class_name;
115         int              subquery_id;
116         StoredQ*         subquery;
117         int              function_call_id;
118         Expression*      function_call;
119         char*            table_alias;
120         int              parent_relation_id;
121         int              seq_no;
122         JoinType         join_type;
123         Expression*      on_clause;
124         FromRelation*    join_list;
125 };
126
127 struct SelectItem_ {
128         SelectItem* next;
129         int         id;
130         int         stored_query_id;
131         int         seq_no;
132         Expression* expression;
133         char*       column_alias;
134         int         grouped_by;        // Boolean
135 };
136
137 typedef enum {
138         BIND_STR,
139         BIND_NUM,
140         BIND_STR_LIST,
141         BIND_NUM_LIST
142 } BindVarType;
143
144 struct BindVar_ {
145         BindVar*    next;
146         char*       name;
147         char*       label;
148         BindVarType type;
149         char*       description;
150         jsonObject* default_value;
151         jsonObject* actual_value;
152 };
153
154 struct CaseBranch_ {
155         CaseBranch* next;
156         int id;
157         Expression* condition;
158         Expression* result;
159 };
160
161 struct Datatype_ {
162         Datatype* next;
163         int       id;
164         char*     datatype_name;
165         int       is_numeric;          // Boolean
166         int       is_composite;        // Boolean
167 };
168
169 typedef enum {
170         EXP_BETWEEN,
171         EXP_BIND,
172         EXP_BOOL,
173         EXP_CASE,
174         EXP_CAST,
175         EXP_COLUMN,
176         EXP_EXIST,
177         EXP_FUNCTION,
178         EXP_IN,
179         EXP_ISNULL,
180         EXP_NULL,
181         EXP_NUMBER,
182         EXP_OPERATOR,
183     EXP_SERIES,
184         EXP_STRING,
185         EXP_SUBQUERY
186 } ExprType;
187
188 struct Expression_ {
189         Expression* next;
190         int         id;
191         ExprType    type;
192         int         parenthesize;       // Boolean
193         int         parent_expr_id;
194         int         seq_no;
195         char*       literal;
196         char*       table_alias;
197         char*       column_name;
198         Expression* left_operand;
199         char*       op;                 // Not called "operator" because that's a keyword in C++
200         Expression* right_operand;
201         int         subquery_id;
202         StoredQ*    subquery;
203         Datatype*   cast_type;
204         int         negate;             // Boolean
205         BindVar*    bind;
206         Expression* subexp_list;        // Linked list of subexpressions
207         CaseBranch* branch_list;        // Linked list of CASE branches
208         // The next column comes, not from query.expression,
209         // but from query.function_sig:
210         char*       function_name;
211 };
212
213 struct QSeq_ {
214         QSeq*    next;
215         int      id;
216         int      parent_query_id;
217         int      seq_no;
218         StoredQ* child_query;
219 };
220
221 struct OrderItem_ {
222         OrderItem* next;
223         int        id;
224         int        stored_query_id;
225         int        seq_no;
226         Expression* expression;
227 };
228
229 BuildSQLState* buildSQLStateNew( dbi_conn dbhandle );
230
231 void buildSQLStateFree( BuildSQLState* state );
232
233 void buildSQLCleanup( void );
234
235 const char* sqlAddMsg( BuildSQLState* state, const char* msg, ... );
236
237 StoredQ* getStoredQuery( BuildSQLState* state, int query_id );
238
239 jsonObject* oilsGetColNames( BuildSQLState* state, StoredQ* query );
240
241 void pop_id( IdNode** stack );
242
243 void storedQFree( StoredQ* sq );
244
245 void storedQCleanup( void );
246
247 int buildSQL( BuildSQLState* state, const StoredQ* query );
248
249 void oilsStoredQSetVerbose( void );
250
251 jsonObject* oilsFirstRow( BuildSQLState* state );
252
253 jsonObject* oilsNextRow( BuildSQLState* state );
254
255 jsonObject* oilsBindVarList( osrfHash* bindvar_list );
256
257 int oilsApplyBindValues( BuildSQLState* state, const jsonObject* bindings );
258
259 #ifdef __cplusplus
260 }
261 #endif
262
263 #endif