summaryrefslogtreecommitdiff
path: root/src/schema/schema_alter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/schema/schema_alter.c')
-rw-r--r--src/schema/schema_alter.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/schema/schema_alter.c b/src/schema/schema_alter.c
new file mode 100644
index 00000000000..e8b619737ed
--- /dev/null
+++ b/src/schema/schema_alter.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 2014-2016 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __alter_file --
+ * Alter a file.
+ */
+static int
+__alter_file(
+ WT_SESSION_IMPL *session, const char *uri, const char *newcfg[])
+{
+ WT_DECL_RET;
+ const char *cfg[4], *filename;
+ char *config, *newconfig;
+
+ filename = uri;
+ newconfig = NULL;
+ if (!WT_PREFIX_SKIP(filename, "file:"))
+ return (__wt_unexpected_object_type(session, uri, "file:"));
+
+ /* Find the URI */
+ WT_RET(__wt_metadata_search(session, uri, &config));
+
+ WT_ASSERT(session, newcfg[0] != NULL);
+ /*
+ * Start with the base configuration because collapse is like
+ * a projection and if we are reading older metadata, it may not
+ * have all the components.
+ */
+ cfg[0] = WT_CONFIG_BASE(session, file_meta);
+ cfg[1] = config;
+ cfg[2] = newcfg[0];
+ cfg[3] = NULL;
+ WT_ERR(__wt_config_collapse(session, cfg, &newconfig));
+ /*
+ * Only rewrite if there are changes.
+ */
+ if (strcmp(config, newconfig) != 0)
+ WT_ERR(__wt_metadata_update(session, uri, newconfig));
+ else
+ WT_STAT_CONN_INCR(session, session_table_alter_skip);
+
+err: __wt_free(session, config);
+ __wt_free(session, newconfig);
+ return (ret);
+}
+
+/*
+ * __alter_colgroup --
+ * WT_SESSION::alter for a colgroup.
+ */
+static int
+__alter_colgroup(
+ WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
+{
+ WT_COLGROUP *colgroup;
+ WT_DECL_RET;
+
+ WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_TABLE));
+
+ /* If we can get the colgroup, perform any potential alterations. */
+ if ((ret = __wt_schema_get_colgroup(
+ session, uri, false, NULL, &colgroup)) == 0)
+ WT_TRET(__wt_schema_alter(session, colgroup->source, cfg));
+
+ return (ret);
+}
+
+/*
+ * __alter_index --
+ * WT_SESSION::alter for an index.
+ */
+static int
+__alter_index(
+ WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
+{
+ WT_INDEX *idx;
+ WT_DECL_RET;
+
+ /* If we can get the index, perform any potential alterations. */
+ if ((ret = __wt_schema_get_index(
+ session, uri, false, NULL, &idx)) == 0)
+ WT_TRET(__wt_schema_alter(session, idx->source, cfg));
+
+ return (ret);
+}
+
+/*
+ * __alter_table --
+ * WT_SESSION::alter for a table.
+ */
+static int
+__alter_table(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
+{
+ WT_COLGROUP *colgroup;
+ WT_DECL_RET;
+ WT_TABLE *table;
+ const char *name;
+ u_int i;
+
+ name = uri;
+ (void)WT_PREFIX_SKIP(name, "table:");
+
+ WT_RET(__wt_schema_get_table(
+ session, name, strlen(name), true, &table));
+
+ /*
+ * Alter the column groups only if we are using the default
+ * column group. Otherwise the user should alter each
+ * index or column group explicitly.
+ */
+ if (table->ncolgroups == 0)
+ for (i = 0; i < WT_COLGROUPS(table); i++) {
+ if ((colgroup = table->cgroups[i]) == NULL)
+ continue;
+ /*
+ * Alter the column group before updating the metadata
+ * to avoid the metadata for the table becoming
+ * inconsistent if we can't get exclusive access.
+ */
+ WT_ERR(__wt_schema_alter(
+ session, colgroup->source, cfg));
+ }
+err: __wt_schema_release_table(session, table);
+ return (ret);
+}
+
+/*
+ * __wt_schema_alter --
+ * Process a WT_SESSION::alter operation for all supported types.
+ */
+int
+__wt_schema_alter(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
+{
+ WT_DATA_SOURCE *dsrc;
+ WT_DECL_RET;
+
+ WT_RET(__wt_meta_track_on(session));
+
+ /* Paranoia: clear any handle from our caller. */
+ session->dhandle = NULL;
+
+ if (WT_PREFIX_MATCH(uri, "colgroup:"))
+ ret = __alter_colgroup(session, uri, cfg);
+ else if (WT_PREFIX_MATCH(uri, "file:"))
+ ret = __alter_file(session, uri, cfg);
+ else if (WT_PREFIX_MATCH(uri, "index:"))
+ ret = __alter_index(session, uri, cfg);
+ else if (WT_PREFIX_MATCH(uri, "lsm:"))
+ ret = __wt_lsm_tree_alter(session, uri, cfg);
+ else if (WT_PREFIX_MATCH(uri, "table:"))
+ ret = __alter_table(session, uri, cfg);
+ else if ((dsrc = __wt_schema_get_source(session, uri)) != NULL)
+ ret = dsrc->alter == NULL ?
+ __wt_object_unsupported(session, uri) :
+ dsrc->alter(dsrc,
+ &session->iface, uri, (WT_CONFIG_ARG *)cfg);
+ else
+ ret = __wt_bad_object_type(session, uri);
+
+ /*
+ * Map WT_NOTFOUND to ENOENT, based on the assumption WT_NOTFOUND means
+ * there was no metadata entry.
+ */
+ if (ret == WT_NOTFOUND)
+ ret = ENOENT;
+
+ /* Bump the schema generation so that stale data is ignored. */
+ ++S2C(session)->schema_gen;
+
+ WT_TRET(__wt_meta_track_off(session, true, ret != 0));
+
+ return (ret);
+}