summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-12-11 16:06:51 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-12-11 16:06:51 +1100
commit500c7e17ff813ba33f198f5c19bd13469b900280 (patch)
treebaf5d55f31a288cd4e205b8158db7277c474ad4d
parentd7030574d78b30949f88791af744d839252477d6 (diff)
downloadmongo-500c7e17ff813ba33f198f5c19bd13469b900280.tar.gz
More fixes for complex schema, this time to retrieve values correctly.
closes #409
-rw-r--r--src/schema/schema_project.c161
1 files changed, 79 insertions, 82 deletions
diff --git a/src/schema/schema_project.c b/src/schema/schema_project.c
index 904d17b6406..ebf3a057f0e 100644
--- a/src/schema/schema_project.c
+++ b/src/schema/schema_project.c
@@ -19,7 +19,7 @@ __wt_schema_project_in(WT_SESSION_IMPL *session,
WT_CURSOR *c;
WT_ITEM *buf;
WT_PACK pack;
- WT_PACK_VALUE pv;
+ WT_PACK_VALUE pv, old_pv;
char *proj;
uint8_t *p, *end;
const uint8_t *next;
@@ -75,50 +75,47 @@ __wt_schema_project_in(WT_SESSION_IMPL *session,
*/
for (arg = (arg == 0) ? 1 : arg; arg > 0; arg--) {
switch (*proj) {
- case WT_PROJ_NEXT:
case WT_PROJ_SKIP:
WT_RET(__pack_next(&pack, &pv));
- if (*proj == WT_PROJ_SKIP) {
- /*
- * A nasty case: if we are inserting
- * out-of-order, we may reach the end
- * of the data. That's okay: we want
- * to append in that case, and we're
- * positioned to do that.
- */
- if (p == end) {
- /* Set up an empty value. */
- WT_CLEAR(pv.u);
- if (pv.type == 'S' ||
- pv.type == 's')
- pv.u.s = "";
-
- len = __pack_size(session, &pv);
- WT_RET(__wt_buf_grow(session,
- buf, buf->size + len));
- p = (uint8_t *)buf->mem +
- buf->size;
- WT_RET(__pack_write(
- session, &pv, &p, len));
- buf->size += WT_STORE_SIZE(len);
- end = (uint8_t *)buf->mem +
- buf->size;
- } else if (*proj == WT_PROJ_SKIP)
- WT_RET(__unpack_read(session,
- &pv, (const uint8_t **)&p,
- (size_t)(end - p)));
+ /*
+ * A nasty case: if we are inserting
+ * out-of-order, we may reach the end of the
+ * data. That's okay: we want to append in
+ * that case, and we're positioned to do that.
+ */
+ if (p == end) {
+ /* Set up an empty value. */
+ WT_CLEAR(pv.u);
+ if (pv.type == 'S' || pv.type == 's')
+ pv.u.s = "";
+
+ len = __pack_size(session, &pv);
+ WT_RET(__wt_buf_grow(session,
+ buf, buf->size + len));
+ p = (uint8_t *)buf->mem + buf->size;
+ WT_RET(__pack_write(
+ session, &pv, &p, len));
+ buf->size += WT_STORE_SIZE(len);
+ end = (uint8_t *)buf->mem + buf->size;
+ } else if (*proj == WT_PROJ_SKIP)
+ WT_RET(__unpack_read(session,
+ &pv, (const uint8_t **)&p,
+ (size_t)(end - p)));
+ break;
- break;
- }
+ case WT_PROJ_NEXT:
+ WT_RET(__pack_next(&pack, &pv));
WT_PACK_GET(session, pv, ap);
/* FALLTHROUGH */
case WT_PROJ_REUSE:
/* Read the item we're about to overwrite. */
next = p;
- if (p < end)
- WT_RET(__unpack_read(session, &pv,
+ if (p < end) {
+ old_pv = pv;
+ WT_RET(__unpack_read(session, &old_pv,
&next, (size_t)(end - p)));
+ }
old_len = (size_t)(next - p);
len = __pack_size(session, &pv);
@@ -199,16 +196,14 @@ __wt_schema_project_out(WT_SESSION_IMPL *session,
switch (*proj) {
case WT_PROJ_NEXT:
case WT_PROJ_SKIP:
+ case WT_PROJ_REUSE:
WT_RET(__pack_next(&pack, &pv));
WT_RET(__unpack_read(session, &pv,
(const uint8_t **)&p, (size_t)(end - p)));
- if (*proj == WT_PROJ_SKIP)
+ /* Only copy the value out once. */
+ if (*proj != WT_PROJ_NEXT)
break;
WT_UNPACK_PUT(session, pv, ap);
- /* FALLTHROUGH */
-
- case WT_PROJ_REUSE:
- /* Don't copy out the same value twice. */
break;
}
}
@@ -295,45 +290,42 @@ __wt_schema_project_slice(WT_SESSION_IMPL *session, WT_CURSOR **cp,
*/
for (arg = (arg == 0) ? 1 : arg; arg > 0; arg--) {
switch (*proj) {
- case WT_PROJ_NEXT:
case WT_PROJ_SKIP:
- if (!skip) {
- WT_RET(__pack_next(&pack, &pv));
-
- /*
- * A nasty case: if we are inserting
- * out-of-order, append a zero value
- * to keep the buffer in the correct
- * format.
- */
- if (*proj == WT_PROJ_SKIP &&
- p == end) {
- /* Set up an empty value. */
- WT_CLEAR(pv.u);
- if (pv.type == 'S' ||
- pv.type == 's')
- pv.u.s = "";
-
- len = __pack_size(session, &pv);
- WT_RET(__wt_buf_grow(session,
- buf, buf->size + len));
- p = (uint8_t *)buf->data +
- buf->size;
- WT_RET(__pack_write(
- session, &pv, &p, len));
- end = p;
- buf->size += WT_STORE_SIZE(len);
- } else if (*proj == WT_PROJ_SKIP)
- WT_RET(__unpack_read(session,
- &pv, (const uint8_t **)&p,
- (size_t)(end - p)));
- }
- if (*proj == WT_PROJ_SKIP)
+ if (skip)
break;
+ WT_RET(__pack_next(&pack, &pv));
+
+ /*
+ * A nasty case: if we are inserting
+ * out-of-order, append a zero value to keep
+ * the buffer in the correct format.
+ */
+ if (p == end) {
+ /* Set up an empty value. */
+ WT_CLEAR(pv.u);
+ if (pv.type == 'S' || pv.type == 's')
+ pv.u.s = "";
+
+ len = __pack_size(session, &pv);
+ WT_RET(__wt_buf_grow(session,
+ buf, buf->size + len));
+ p = (uint8_t *)buf->data + buf->size;
+ WT_RET(__pack_write(
+ session, &pv, &p, len));
+ end = p;
+ buf->size += WT_STORE_SIZE(len);
+ } else
+ WT_RET(__unpack_read(session,
+ &pv, (const uint8_t **)&p,
+ (size_t)(end - p)));
+ break;
+
+ case WT_PROJ_NEXT:
WT_RET(__pack_next(&vpack, &vpv));
WT_RET(__unpack_read(session, &vpv,
&vp, (size_t)(vend - vp)));
/* FALLTHROUGH */
+
case WT_PROJ_REUSE:
if (skip)
break;
@@ -347,15 +339,19 @@ __wt_schema_project_slice(WT_SESSION_IMPL *session, WT_CURSOR **cp,
* columns in the middle of a packed struct,
* but not if they are at the end of a struct.
*/
+ WT_RET(__pack_next(&pack, &pv));
+
next = p;
- if (p < end) {
+ if (p < end)
WT_RET(__unpack_read(session, &pv,
&next, (size_t)(end - p)));
- pv.u = vpv.u;
- } else
- pv = vpv;
old_len = (size_t)(next - p);
+ /* Make sure the types are compatible. */
+ WT_ASSERT(session,
+ tolower(pv.type) == tolower(vpv.type));
+ pv.u = vpv.u;
+
len = __pack_size(session, &pv);
offset = WT_PTRDIFF(p, buf->data);
WT_RET(__wt_buf_grow(session,
@@ -442,13 +438,18 @@ __wt_schema_project_merge(WT_SESSION_IMPL *session,
switch (*proj) {
case WT_PROJ_NEXT:
case WT_PROJ_SKIP:
+ case WT_PROJ_REUSE:
WT_RET(__pack_next(&pack, &pv));
WT_RET(__unpack_read(session, &pv,
&p, (size_t)(end - p)));
- if (*proj == WT_PROJ_SKIP)
+ /* Only copy the value out once. */
+ if (*proj != WT_PROJ_NEXT)
break;
WT_RET(__pack_next(&vpack, &vpv));
+ /* Make sure the types are compatible. */
+ WT_ASSERT(session,
+ tolower(pv.type) == tolower(vpv.type));
vpv.u = pv.u;
len = __pack_size(session, &vpv);
WT_RET(__wt_buf_grow(session,
@@ -456,10 +457,6 @@ __wt_schema_project_merge(WT_SESSION_IMPL *session,
vp = (uint8_t *)value->mem + value->size;
WT_RET(__pack_write(session, &vpv, &vp, len));
value->size += WT_STORE_SIZE(len);
- /* FALLTHROUGH */
-
- case WT_PROJ_REUSE:
- /* Don't copy the same value twice. */
break;
}
}