aboutsummaryrefslogtreecommitdiff
path: root/odb/relational/context.hxx
blob: 56159dbce9d38e76daf20c5dd8359bef0edc8654 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// file      : odb/relational/context.hxx
// copyright : Copyright (c) 2009-2017 Code Synthesis Tools CC
// license   : GNU GPL v3; see accompanying LICENSE file

#ifndef ODB_RELATIONAL_CONTEXT_HXX
#define ODB_RELATIONAL_CONTEXT_HXX

#include <odb/context.hxx>

#include <odb/semantics/relational.hxx>
#include <odb/traversal/relational.hxx>

namespace relational
{
  namespace sema_rel = semantics::relational;
  namespace trav_rel = traversal::relational;

  enum statement_kind
  {
    statement_select,
    statement_insert,
    statement_update,
    statement_delete,
    statement_where   // WHERE clause.
  };

  // Index.
  //
  struct index
  {
    location_t loc;      // Location of this index definition.
    std::string name;    // If empty, then derive from the member name.
    std::string type;    // E.g., "UNIQUE", etc.
    std::string method;  // E.g., "BTREE", etc.
    std::string options; // Database-specific index options.

    struct member
    {
      location_t loc;        // Location of this member specifier.
      std::string name;      // Member name, e.g., foo_, foo_.bar_.
      data_member_path path; // Member path.
      std::string options;   // Member options, e.g., "ASC", etc.
    };
    typedef std::vector<member> members_type;

    members_type members;
  };

  typedef std::vector<index> indexes;

  // Indexes in the above vector are in location order.
  //
  struct index_comparator
  {
    bool
    operator() (index const& x, index const& y) const
    {
      return x.loc < y.loc;
    }
  };

  // Custom database type mapping.
  //
  struct custom_db_type
  {
    regex type;
    std::string as;
    std::string to;
    std::string from;
    location_t loc;
  };

  typedef std::vector<custom_db_type> custom_db_types;

  class context: public virtual ::context
  {
  public:
    // Return true if an object or value type has members for which
    // the image can grow. If section is not specified, then ignore
    // separately loaded members. Otherwise ignore members that do
    // not belong to the section.
    //
    bool
    grow (semantics::class_&, user_section* = 0);

    // The same for a member's value type.
    //
    bool
    grow (semantics::data_member&);

    bool
    grow (semantics::data_member&,
          semantics::type&,
          const custom_cxx_type*,
          string const& key_prefix);

  public:
    // Quote SQL string.
    //
    string
    quote_string (string const&) const;

    // Quote SQL identifier.
    //
    string
    quote_id (string const&) const;

    string
    quote_id (qname const&) const;

    // Quoted column and table names.
    //
    string
    column_qname (semantics::data_member& m, column_prefix const& cp) const
    {
      return quote_id (column_name (m, cp));
    }

    string
    column_qname (data_member_path const& mp) const
    {
      return quote_id (column_name (mp));
    }

    string
    column_qname (semantics::data_member& m,
                  string const& key_prefix,
                  string const& default_name,
                  column_prefix const& cp) const
    {
      return quote_id (column_name (m, key_prefix, default_name, cp));
    }

    string
    table_qname (semantics::class_& c) const
    {
      return quote_id (table_name (c));
    }

    string
    table_qname (semantics::class_& obj, data_member_path const& mp) const
    {
      return quote_id (table_name (obj, mp));
    }

    string
    table_qname (semantics::data_member& m, table_prefix const& p) const
    {
      return quote_id (table_name (m, p));
    }

  public:
    string
    index_name (qname const& table, string const& base);

    string
    fkey_name (qname const& table, string const& base);

    // Custom database type conversion.
    //
  public:
    string
    convert_to (string const& expr,
                string const& sqlt,
                semantics::data_member& m)
    {
      string const& conv (current ().convert_expr (sqlt, m, true));
      return conv.empty () ? expr : convert (expr, conv);
    }

    string
    convert_from (string const& expr,
                  string const& sqlt,
                  semantics::data_member& m)
    {
      string const& conv (current ().convert_expr (sqlt, m, false));
      return conv.empty () ? expr : convert (expr, conv);
    }

    // These shortcut versions should only be used on special members
    // (e.g., auto id, version, etc) since they may not determine the
    // proper SQL type in other cases (prefixes, composite ids, etc).
    //
    string
    convert_to (string const& expr, semantics::data_member& m)
    {
      return convert_to (expr, column_type (m), m);
    }

    string
    convert_from (string const& expr, semantics::data_member& m)
    {
      return convert_from (expr, column_type (m), m);
    }

    // Return the conversion expression itself.
    //
    string const&
    convert_to_expr (string const& sqlt, semantics::data_member& m)
    {
      return current ().convert_expr (sqlt, m, true);
    }

  protected:
    virtual string const&
    convert_expr (string const& sqlt, semantics::data_member&, bool to);

    string
    convert (string const& expr, string const& conv);

  protected:
    // The default implementation returns false.
    //
    virtual bool
    grow_impl (semantics::class_&, user_section*);

    virtual bool
    grow_impl (semantics::data_member&);

    virtual bool
    grow_impl (semantics::data_member&,
               semantics::type&,
               const custom_cxx_type*,
               string const&);

    // The default implementation uses the ISO quoting ('') and
    // escapes singe quotes inside the string by double-quoting
    // (' -> ''). Some (most?) database systems support escape
    // sequences. We may want to provide utilize that to support
    // things like \n, \t, etc.
    //
    virtual string
    quote_string_impl (string const&) const;

    // The default implementation uses the ISO quoting ("").
    //
    virtual string
    quote_id_impl (qname const&) const;

  public:
    virtual
    ~context ();
    context ();

    static context&
    current ()
    {
      return *current_;
    }

  protected:
    struct data;
    typedef context base_context;

    context (data*, sema_rel::model*);

  private:
    static context* current_;

  protected:
    struct data: root_context::data
    {
      data (std::ostream& os): root_context::data (os) {}

      string bind_vector_;
      string truncated_vector_;
    };
    data* data_;

  public:
    sema_rel::model* model;

    bool generate_grow;
    bool need_alias_as;
    bool insert_send_auto_id;
    bool delay_freeing_statement_result;
    bool need_image_clone;
    bool generate_bulk;

    bool global_index;
    bool global_fkey;

    string const& bind_vector;
    string const& truncated_vector;
  };
}

#include <odb/relational/context.ixx>

#endif // ODB_RELATIONAL_CONTEXT_HXX