/* * __rename_tree -- * Rename an index or colgroup reference. */ static int __rename_tree(WT_SESSION_IMPL *session, WT_TABLE *table, const char *newuri, const char *name, const char *cfg[]) { WT_CONFIG_ITEM cval; WT_DECL_ITEM(nn); WT_DECL_ITEM(ns); WT_DECL_ITEM(nv); WT_DECL_ITEM(os); WT_DECL_RET; bool is_colgroup; const char *newname, *olduri, *suffix; char *value; olduri = table->name; value = NULL; newname = newuri; (void)WT_PREFIX_SKIP(newname, "table:"); /* * Create the new data source URI and update the schema value. * * 'name' has the format (colgroup|index):<tablename>[:<suffix>]; * we need the suffix. */ is_colgroup = WT_PREFIX_MATCH(name, "colgroup:"); if (!is_colgroup && !WT_PREFIX_MATCH(name, "index:")) WT_ERR_MSG(session, EINVAL, "expected a 'colgroup:' or 'index:' source: '%s'", name); suffix = strchr(name, ':'); /* An existing table should have a well formed name. */ WT_ASSERT(session, suffix != NULL); suffix = strchr(suffix + 1, ':'); WT_ERR(__wt_scr_alloc(session, 0, &nn)); WT_ERR(__wt_buf_fmt(session, nn, "%s%s%s", is_colgroup ? "colgroup:" : "index:", newname, (suffix == NULL) ? "" : suffix)); /* Skip the colon, if any. */ if (suffix != NULL) ++suffix; /* Read the old schema value. */ WT_ERR(__wt_metadata_search(session, name, &value)); /* * Calculate the new data source URI. Use the existing table structure * and substitute the new name temporarily. */ WT_ERR(__wt_scr_alloc(session, 0, &ns)); table->name = newuri; if (is_colgroup) WT_ERR(__wt_schema_colgroup_source( session, table, suffix, value, ns)); else WT_ERR(__wt_schema_index_source( session, table, suffix, value, ns)); if ((ret = __wt_config_getones(session, value, "source", &cval)) != 0) WT_ERR_MSG(session, EINVAL, "index or column group has no data source: %s", value); /* Take a copy of the old data source. */ WT_ERR(__wt_scr_alloc(session, 0, &os)); WT_ERR(__wt_buf_fmt(session, os, "%.*s", (int)cval.len, cval.str)); /* Overwrite it with the new data source. */ WT_ERR(__wt_scr_alloc(session, 0, &nv)); WT_ERR(__wt_buf_fmt(session, nv, "%.*s%s%s", (int)WT_PTRDIFF(cval.str, value), value, (const char *)ns->data, cval.str + cval.len)); /* * Do the rename before updating the metadata to avoid leaving the * metadata inconsistent if the rename fails. */ WT_ERR(__wt_schema_rename(session, os->data, ns->data, cfg)); /* * Remove the old metadata entry. * Insert the new metadata entry. */ WT_ERR(__wt_metadata_remove(session, name)); WT_ERR(__wt_metadata_insert(session, nn->data, nv->data)); err: __wt_scr_free(session, &nn); __wt_scr_free(session, &ns); __wt_scr_free(session, &nv); __wt_scr_free(session, &os); __wt_free(session, value); table->name = olduri; return (ret); }
/* * __create_colgroup -- * Create a column group. */ static int __create_colgroup(WT_SESSION_IMPL *session, const char *name, int exclusive, const char *config) { WT_CONFIG_ITEM cval; WT_DECL_RET; WT_ITEM confbuf, fmt, namebuf; WT_TABLE *table; size_t tlen; const char **cfgp, *cfg[4] = { WT_CONFIG_BASE(session, colgroup_meta), config, NULL, NULL }; const char *sourcecfg[] = { config, NULL, NULL }; const char *cgname, *source, *sourceconf, *tablename; char *cgconf, *oldconf; sourceconf = NULL; cgconf = oldconf = NULL; WT_CLEAR(fmt); WT_CLEAR(confbuf); WT_CLEAR(namebuf); tablename = name; if (!WT_PREFIX_SKIP(tablename, "colgroup:")) return (EINVAL); cgname = strchr(tablename, ':'); if (cgname != NULL) { tlen = (size_t)(cgname - tablename); ++cgname; } else tlen = strlen(tablename); if ((ret = __wt_schema_get_table(session, tablename, tlen, 1, &table)) != 0) WT_RET_MSG(session, (ret == WT_NOTFOUND) ? ENOENT : ret, "Can't create '%s' for non-existent table '%.*s'", name, (int)tlen, tablename); /* Make sure the column group is referenced from the table. */ if (cgname != NULL && (ret = __wt_config_subgets(session, &table->cgconf, cgname, &cval)) != 0) WT_ERR_MSG(session, EINVAL, "Column group '%s' not found in table '%.*s'", cgname, (int)tlen, tablename); /* Find the first NULL entry in the cfg stack. */ for (cfgp = &cfg[1]; *cfgp; cfgp++) ; /* Add the source to the colgroup config before collapsing. */ if (__wt_config_getones( session, config, "source", &cval) == 0 && cval.len != 0) { WT_ERR(__wt_buf_fmt( session, &namebuf, "%.*s", (int)cval.len, cval.str)); source = namebuf.data; } else { WT_ERR(__wt_schema_colgroup_source( session, table, cgname, config, &namebuf)); source = namebuf.data; WT_ERR(__wt_buf_fmt( session, &confbuf, "source=\"%s\"", source)); *cfgp++ = confbuf.data; } /* Calculate the key/value formats: these go into the source config. */ WT_ERR(__wt_buf_fmt(session, &fmt, "key_format=%s", table->key_format)); if (cgname == NULL) WT_ERR(__wt_buf_catfmt (session, &fmt, ",value_format=%s", table->value_format)); else { if (__wt_config_getones(session, config, "columns", &cval) != 0) WT_ERR_MSG(session, EINVAL, "No 'columns' configuration for '%s'", name); WT_ERR(__wt_buf_catfmt(session, &fmt, ",value_format=")); WT_ERR(__wt_struct_reformat(session, table, cval.str, cval.len, NULL, 1, &fmt)); } sourcecfg[1] = fmt.data; WT_ERR(__wt_config_merge(session, sourcecfg, NULL, &sourceconf)); WT_ERR(__wt_schema_create(session, source, sourceconf)); WT_ERR(__wt_config_collapse(session, cfg, &cgconf)); if ((ret = __wt_metadata_insert(session, name, cgconf)) != 0) { /* * If the entry already exists in the metadata, we're done. * This is an error for exclusive creates but okay otherwise. */ if (ret == WT_DUPLICATE_KEY) ret = exclusive ? EEXIST : 0; goto err; } WT_ERR(__wt_schema_open_colgroups(session, table)); err: __wt_free(session, cgconf); __wt_free(session, sourceconf); __wt_free(session, oldconf); __wt_buf_free(session, &confbuf); __wt_buf_free(session, &fmt); __wt_buf_free(session, &namebuf); __wt_schema_release_table(session, table); return (ret); }