summaryrefslogtreecommitdiff
path: root/odb/relational/sqlite/schema.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/sqlite/schema.cxx')
-rw-r--r--odb/relational/sqlite/schema.cxx456
1 files changed, 0 insertions, 456 deletions
diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx
deleted file mode 100644
index c0603c1..0000000
--- a/odb/relational/sqlite/schema.cxx
+++ /dev/null
@@ -1,456 +0,0 @@
-// file : odb/relational/sqlite/schema.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/schema.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-namespace relational
-{
- namespace sqlite
- {
- namespace schema
- {
- namespace relational = relational::schema;
-
- //
- // Drop.
- //
-
- struct drop_column: trav_rel::drop_column, relational::common
- {
- drop_column (relational::common const& c)
- : relational::common (c), first_ (true) {}
-
- virtual void
- traverse (sema_rel::drop_column& dc)
- {
- // SQLite does not support dropping columns. If this column is
- // not NULLable, then there is nothing we can do. Otherwise, do
- // a logical DROP by setting all the values to NULL.
- //
- sema_rel::column& c (find<sema_rel::column> (dc));
-
- if (!c.null ())
- {
- cerr << "error: SQLite does not support dropping of columns" <<
- endl;
- cerr << "info: first dropped column is '" << dc.name () <<
- "' in table '" << dc.table ().name () << "'" << endl;
- cerr << "info: could have performed logical drop if the column " <<
- "allowed NULL values" << endl;
- throw operation_failed ();
- }
-
- if (first_)
- first_ = false;
- else
- os << "," << endl
- << " ";
-
- os << quote_id (dc.name ()) << " = NULL";
- }
-
- private:
- bool first_;
- };
- // Not registered as an override.
-
- struct drop_index: relational::drop_index, context
- {
- drop_index (base const& x): base (x) {}
-
- virtual string
- name (sema_rel::index& in)
- {
- // In SQLite, index names can be qualified with the database.
- //
- sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
- sema_rel::qname n (t.name ().qualifier ());
- n.append (in.name ());
- return quote_id (n);
- }
- };
- entry<drop_index> drop_index_;
-
- struct drop_table: relational::drop_table, context
- {
- drop_table (base const& x): base (x) {}
-
- virtual void
- traverse (sema_rel::table& t, bool migration)
- {
- // In SQLite there is no way to drop foreign keys except as part
- // of the table.
- //
- if (pass_ != 2)
- return;
-
- // Polymorphic base cleanup code. Because we cannot drop foreign
- // keys, we will trigger cascade deletion. The only way to work
- // around this problem is to delete from the root table and rely
- // on the cascade to clean up the rest.
- //
- if (migration && t.extra ()["kind"] == "polymorphic derived object")
- {
- using sema_rel::model;
- using sema_rel::table;
- using sema_rel::primary_key;
- using sema_rel::foreign_key;
-
- model& m (dynamic_cast<model&> (t.scope ()));
-
- table* p (&t);
- do
- {
- // The polymorphic link is the first primary key.
- //
- for (table::names_iterator i (p->names_begin ());
- i != p->names_end (); ++i)
- {
- if (foreign_key* fk = dynamic_cast<foreign_key*> (
- &i->nameable ()))
- {
- p = m.find<table> (fk->referenced_table ());
- assert (p != 0); // Base table should be there.
- break;
- }
- }
- }
- while (p->extra ()["kind"] != "polymorphic root object");
-
- primary_key& rkey (*p->find<primary_key> (""));
- primary_key& dkey (*t.find<primary_key> (""));
- assert (rkey.contains_size () == dkey.contains_size ());
- delete_ (p->name (), t.name (), rkey, dkey);
- }
-
- drop (t, migration);
- }
- };
- entry<drop_table> drop_table_;
-
- //
- // Create.
- //
-
- struct create_column: relational::create_column, context
- {
- create_column (base const& x): base (x) {}
-
- virtual void
- traverse (sema_rel::add_column& ac)
- {
- using sema_rel::alter_table;
- using sema_rel::add_column;
- using sema_rel::add_foreign_key;
-
- alter_table& at (static_cast<alter_table&> (ac.scope ()));
-
- pre_statement ();
-
- os << "ALTER TABLE " << quote_id (at.name ()) << endl
- << " ADD COLUMN ";
-
- // In SQLite it is impossible to alter a column later, so unless
- // it has a default value, we add it as NULL. Without this, it
- // will be impossible to add a column to a table that contains
- // some rows.
- //
- create (ac);
-
- // SQLite doesn't support adding foreign keys other than inline
- // via a column definition. See if we can handle any.
- //
- add_foreign_key* afk (0);
-
- for (add_column::contained_iterator i (ac.contained_begin ());
- i != ac.contained_end ();
- ++i)
- {
- if ((afk = dynamic_cast<add_foreign_key*> (&i->key ())))
- {
- // Check that it is a single-column foreign key. Also make
- // sure the column and foreign key are from the same changeset.
- //
- if (afk->contains_size () != 1 || &ac.scope () != &afk->scope ())
- afk = 0;
- else
- break;
- }
- }
-
- if (afk != 0)
- {
- os << " CONSTRAINT " << quote_id (afk->name ()) << " REFERENCES " <<
- quote_id (afk->referenced_table ().uname ()) << " (" <<
- quote_id (afk->referenced_columns ()[0]) << ")";
-
- bool del (afk->on_delete () != sema_rel::foreign_key::no_action);
- bool def (!afk->not_deferrable ());
-
- if (del || def)
- {
- instance<relational::create_foreign_key> cfk (*this);
-
- if (del)
- cfk->on_delete (afk->on_delete ());
-
- if (def)
- cfk->deferrable (afk->deferrable ());
- }
-
- afk->set ("sqlite-fk-defined", true); // Mark it as defined.
- }
-
- os << endl;
- post_statement ();
- }
-
- virtual void
- auto_ (sema_rel::primary_key& pk)
- {
- if (pk.extra ().count ("lax"))
- os << " /*AUTOINCREMENT*/";
- else
- os << " AUTOINCREMENT";
- }
- };
- 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)
- {
- // In SQLite, all constraints are defined as part of a table.
- //
- os << "," << endl
- << " CONSTRAINT ";
-
- create (fk);
- }
-
- virtual string
- table_name (sema_rel::foreign_key& fk)
- {
- // In SQLite, the referenced table cannot be qualified with the
- // database name (it has to be in the same database anyway).
- //
- return quote_id (fk.referenced_table ().uname ());
- }
- };
- entry<create_foreign_key> create_foreign_key_;
-
- struct create_index: relational::create_index, context
- {
- create_index (base const& x): base (x) {}
-
- virtual string
- name (sema_rel::index& in)
- {
- // In SQLite, index names can be qualified with the database.
- //
- sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
- sema_rel::qname n (t.name ().qualifier ());
- n.append (in.name ());
- return quote_id (n);
- }
-
- virtual string
- table_name (sema_rel::index& in)
- {
- // In SQLite, the index table cannot be qualified with the
- // database name (it has to be in the same database).
- //
- return quote_id (
- static_cast<sema_rel::table&> (in.scope ()).name ().uname ());
- }
- };
- entry<create_index> create_index_;
-
- struct create_table: relational::create_table, context
- {
- create_table (base const& x): base (x) {}
-
- void
- traverse (sema_rel::table& t)
- {
- // For SQLite we do everything in a single pass since there
- // is no way to add constraints later.
- //
- if (pass_ == 1)
- create (t);
- }
- };
- entry<create_table> create_table_;
-
- //
- // Alter.
- //
-
- struct alter_table_pre: relational::alter_table_pre, context
- {
- alter_table_pre (base const& x): base (x) {}
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- // SQLite can only add a single column per ALTER TABLE statement.
- //
- instance<create_column> cc (*this);
- trav_rel::unames n (*cc);
- names (at, n);
-
- // SQLite does not support altering columns.
- //
- if (sema_rel::alter_column* ac = check<sema_rel::alter_column> (at))
- {
- cerr << "error: SQLite does not support altering of columns"
- << endl;
- cerr << "info: first altered column is '" << ac->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
-
- // SQLite does not support dropping constraints. We are going to
- // ignore this if the column is NULL'able since in most cases
- // the constraint is going to be dropped as a result of the
- // column drop (e.g., an object pointer member got deleted).
- // If we were not to allow this, then it would be impossible
- // to do logical drop for pointer columns.
- //
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- using sema_rel::foreign_key;
- using sema_rel::drop_foreign_key;
-
- drop_foreign_key* dfk (
- dynamic_cast<drop_foreign_key*> (&i->nameable ()));
-
- if (dfk == 0)
- continue;
-
- foreign_key& fk (find<foreign_key> (*dfk));
-
- for (foreign_key::contains_iterator j (fk.contains_begin ());
- j != fk.contains_end (); ++j)
- {
- if (j->column ().null ())
- continue;
-
- cerr << "error: SQLite does not support dropping of foreign " <<
- "keys" << endl;
- cerr << "info: first dropped foreign key is '" << dfk->name () <<
- "' in table '" << at.name () << "'" << endl;
- cerr << "info: could have ignored it if the contained " <<
- "column(s) allowed NULL values" << endl;
- throw operation_failed ();
- }
- }
- }
- };
- entry<alter_table_pre> alter_table_pre_;
-
- struct alter_table_post: relational::alter_table_post, context
- {
- alter_table_post (base const& x): base (x) {}
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- // SQLite does not support altering columns (we have to do this
- // in both alter_table_pre/post because of the
- // check_alter_column_null() test in the common code).
- //
- if (sema_rel::alter_column* ac = check<sema_rel::alter_column> (at))
- {
- cerr << "error: SQLite does not support altering of columns"
- << endl;
- cerr << "info: first altered column is '" << ac->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
-
- // Try to do logical column drop.
- //
- if (check<sema_rel::drop_column> (at))
- {
- pre_statement ();
-
- os << "UPDATE " << quote_id (at.name ()) << endl
- << " SET ";
-
- drop_column dc (*this);
- trav_rel::unames n (dc);
- names (at, n);
- os << endl;
-
- post_statement ();
- }
-
- // SQLite doesn't support adding foreign keys other than inline
- // via a column definition. See if there are any that we couldn't
- // handle that way.
- //
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- sema_rel::add_foreign_key* afk (
- dynamic_cast<sema_rel::add_foreign_key*> (&i->nameable ()));
-
- if (afk == 0 || afk->count ("sqlite-fk-defined"))
- continue;
-
- cerr << "error: SQLite does not support adding foreign keys"
- << endl;
- cerr << "info: first added foreign key is '" << afk->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
- }
- };
- entry<alter_table_post> alter_table_post_;
-
- //
- // Schema version table.
- //
-
- struct version_table: relational::version_table, context
- {
- version_table (base const& x): base (x) {}
-
- virtual void
- create_table ()
- {
- pre_statement ();
-
- os << "CREATE TABLE IF NOT EXISTS " << qt_ << " (" << endl
- << " " << qn_ << " TEXT NOT NULL PRIMARY KEY," << endl
- << " " << qv_ << " INTEGER NOT NULL," << endl
- << " " << qm_ << " INTEGER NOT NULL)" << endl;
-
- post_statement ();
- }
-
- virtual void
- create (sema_rel::version v)
- {
- pre_statement ();
-
- os << "INSERT OR IGNORE INTO " << qt_ << " (" << endl
- << " " << qn_ << ", " << qv_ << ", " << qm_ << ")" << endl
- << " VALUES (" << qs_ << ", " << v << ", 0)" << endl;
-
- post_statement ();
- }
- };
- entry<version_table> version_table_;
- }
- }
-}