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