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