summaryrefslogtreecommitdiff
path: root/odb/relational/mysql/schema.cxx
blob: 428db1cc392651cb84fb379ad8f457b04fc3d3ec (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
// file      : odb/relational/mysql/schema.cxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
// license   : GNU GPL v3; see accompanying LICENSE file

#include <odb/relational/schema.hxx>

#include <odb/relational/mysql/common.hxx>
#include <odb/relational/mysql/context.hxx>

namespace relational
{
  namespace mysql
  {
    namespace schema
    {
      namespace relational = relational::schema;

      //
      // Create.
      //

      struct create_column: relational::create_column, context
      {
        create_column (base const& x): base (x) {}

        virtual void
        null (sema_rel::column& c)
        {
          // MySQL TIMESTAMP is by default NOT NULL. If we want it
          // to contain NULL values, we need to explicitly declare
          // the column as NULL.
          //
          if (c.null ())
          {
            // This should never fail since we have already parsed this.
            //
            sql_type const& t (parse_sql_type (c.type ()));

            if (t.type == sql_type::TIMESTAMP)
            {
              os << " NULL";
              return;
            }
          }

          base::null (c);
        }

        virtual void
        auto_ (sema_rel::column&)
        {
          os << " AUTO_INCREMENT";
        }
      };
      entry<create_column> create_column_;

      struct create_foreign_key: relational::create_foreign_key, context
      {
        create_foreign_key (base const& x): base (x) {}

        virtual void
        traverse (sema_rel::foreign_key& fk)
        {
          // MySQL does not support deferred constraint checking. Output
          // such foreign keys as comments, for documentation, unless we
          // are generating embedded schema.
          //
          if (fk.deferred ())
          {
            // Don't bloat C++ code with comment strings if we are
            // generating embedded schema.
            //
            if (format_ != schema_format::embedded)
            {
              os << endl
                 << endl
                 << "  /*" << endl;

              base::create (fk);

              os << endl
                 << "  */";
            }
          }
          else
            base::traverse (fk);
        }

        virtual string
        name (sema_rel::foreign_key& fk)
        {
          // In MySQL, foreign key names are database-global. Make them
          // unique by prefixing the key name with table name.
          //
          return static_cast<sema_rel::table&> (fk.scope ()).name () +
            '_' + fk.name ();
        }

        virtual void
        deferred ()
        {
          // MySQL doesn't support deferred.
        }
      };
      entry<create_foreign_key> create_foreign_key_;

      struct create_table: relational::create_table, context
      {
        create_table (base const& x): base (x) {}

        virtual void
        create_post ()
        {
          os << ")";

          string const& engine (options.mysql_engine ());

          if (engine != "default")
            os << endl
               << " ENGINE=" << engine;

          os << endl;
        }
      };
      entry<create_table> create_table_;
    }
  }
}