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