Qstore: support LIMIT and OFFSET clauses.
[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         Expression*   limit_count;
94         Expression*   offset_count;
95 };
96
97 typedef enum {
98         FRT_RELATION,
99         FRT_SUBQUERY,
100         FRT_FUNCTION
101 } FromRelationType;
102
103 typedef enum {
104         JT_NONE,
105         JT_INNER,
106         JT_LEFT,
107         JT_RIGHT,
108         JT_FULL
109 } JoinType;
110
111 struct FromRelation_ {
112         FromRelation*    next;
113         int              id;
114         FromRelationType type;
115         char*            table_name;
116         char*            class_name;
117         int              subquery_id;
118         StoredQ*         subquery;
119         int              function_call_id;
120         Expression*      function_call;
121         char*            table_alias;
122         int              parent_relation_id;
123         int              seq_no;
124         JoinType         join_type;
125         Expression*      on_clause;
126         FromRelation*    join_list;
127 };
128
129 struct SelectItem_ {
130         SelectItem* next;
131         int         id;
132         int         stored_query_id;
133         int         seq_no;
134         Expression* expression;
135         char*       column_alias;
136         int         grouped_by;        // Boolean
137 };
138
139 typedef enum {
140         BIND_STR,
141         BIND_NUM,
142         BIND_STR_LIST,
143         BIND_NUM_LIST
144 } BindVarType;
145
146 struct BindVar_ {
147         BindVar*    next;
148         char*       name;
149         char*       label;
150         BindVarType type;
151         char*       description;
152         jsonObject* default_value;
153         jsonObject* actual_value;
154 };
155
156 struct CaseBranch_ {
157         CaseBranch* next;
158         int id;
159         Expression* condition;
160         Expression* result;
161 };
162
163 struct Datatype_ {
164         Datatype* next;
165         int       id;
166         char*     datatype_name;
167         int       is_numeric;          // Boolean
168         int       is_composite;        // Boolean
169 };
170
171 typedef enum {
172         EXP_BETWEEN,
173         EXP_BIND,
174         EXP_BOOL,
175         EXP_CASE,
176         EXP_CAST,
177         EXP_COLUMN,
178         EXP_EXIST,
179         EXP_FUNCTION,
180         EXP_IN,
181         EXP_ISNULL,
182         EXP_NULL,
183         EXP_NUMBER,
184         EXP_OPERATOR,
185     EXP_SERIES,
186         EXP_STRING,
187         EXP_SUBQUERY
188 } ExprType;
189
190 struct Expression_ {
191         Expression* next;
192         int         id;
193         ExprType    type;
194         int         parenthesize;       // Boolean
195         int         parent_expr_id;
196         int         seq_no;
197         char*       literal;
198         char*       table_alias;
199         char*       column_name;
200         Expression* left_operand;
201         char*       op;                 // Not called "operator" because that's a keyword in C++
202         Expression* right_operand;
203         int         subquery_id;
204         StoredQ*    subquery;
205         Datatype*   cast_type;
206         int         negate;             // Boolean
207         BindVar*    bind;
208         Expression* subexp_list;        // Linked list of subexpressions
209         CaseBranch* branch_list;        // Linked list of CASE branches
210         // The next column comes, not from query.expression,
211         // but from query.function_sig:
212         char*       function_name;
213 };
214
215 struct QSeq_ {
216         QSeq*    next;
217         int      id;
218         int      parent_query_id;
219         int      seq_no;
220         StoredQ* child_query;
221 };
222
223 struct OrderItem_ {
224         OrderItem* next;
225         int        id;
226         int        stored_query_id;
227         int        seq_no;
228         Expression* expression;
229 };
230
231 BuildSQLState* buildSQLStateNew( dbi_conn dbhandle );
232
233 void buildSQLStateFree( BuildSQLState* state );
234
235 void buildSQLCleanup( void );
236
237 const char* sqlAddMsg( BuildSQLState* state, const char* msg, ... );
238
239 StoredQ* getStoredQuery( BuildSQLState* state, int query_id );
240
241 jsonObject* oilsGetColNames( BuildSQLState* state, StoredQ* query );
242
243 void pop_id( IdNode** stack );
244
245 void storedQFree( StoredQ* sq );
246
247 void storedQCleanup( void );
248
249 int buildSQL( BuildSQLState* state, const StoredQ* query );
250
251 void oilsStoredQSetVerbose( void );
252
253 jsonObject* oilsFirstRow( BuildSQLState* state );
254
255 jsonObject* oilsNextRow( BuildSQLState* state );
256
257 jsonObject* oilsBindVarList( osrfHash* bindvar_list );
258
259 int oilsApplyBindValues( BuildSQLState* state, const jsonObject* bindings );
260
261 #ifdef __cplusplus
262 }
263 #endif
264
265 #endif