diff --git a/src/main/java/com/samskivert/depot/impl/BuildVisitor.java b/src/main/java/com/samskivert/depot/impl/BuildVisitor.java index 635263a..23937c5 100644 --- a/src/main/java/com/samskivert/depot/impl/BuildVisitor.java +++ b/src/main/java/com/samskivert/depot/impl/BuildVisitor.java @@ -467,7 +467,8 @@ public abstract class BuildVisitor implements FragmentVisitor _builder.append(" = "); if (pojo != null) { bindField(pClass, fields[ii], pojo); - + } else if (values[ii] instanceof ValueExp) { + bindFieldValue(pClass, fields[ii], (ValueExp)values[ii]); } else { values[ii].accept(this); } @@ -747,18 +748,61 @@ public abstract class BuildVisitor implements FragmentVisitor return null; } - protected Void bindValue (Object object) + protected Void bindValue (final Object value) { - _bindables.add(newBindable(object)); + _bindables.add(new Bindable() { + public void doBind (Connection conn, PreparedStatement stmt, int argIx) + throws Exception { + // TODO: how can we abstract this fieldless marshalling + if (value instanceof ByteEnum) { + // byte enums require special conversion + stmt.setByte(argIx, ((ByteEnum)value).toByte()); + } else if (value instanceof Enum) { + // enums are converted to strings + stmt.setString(argIx, ((Enum)value).name()); + } else if (value instanceof int[]) { + // int arrays require conversion to byte arrays + int[] data = (int[])value; + ByteBuffer bbuf = ByteBuffer.allocate(data.length * 4); + bbuf.asIntBuffer().put(data); + stmt.setObject(argIx, bbuf.array()); + } else { + stmt.setObject(argIx, value); + } + } + }); _builder.append("?"); return null; } protected Void bindField ( - Class pClass, ColumnExp field, Object pojo) + Class pClass, ColumnExp field, final Object pojo) { - final DepotMarshaller marshaller = _types.getMarshaller(pClass); - _bindables.add(newBindable(marshaller, field, pojo)); + final FieldMarshaller fmarsh = + _types.getMarshaller(pClass).getFieldMarshaller(field.name); + _bindables.add(new Bindable() { + public void doBind (Connection conn, PreparedStatement stmt, int argIx) + throws Exception { + fmarsh.getAndWriteToStatement(stmt, argIx, pojo); + } + }); + _builder.append("?"); + return null; + } + + protected Void bindFieldValue ( + Class pClass, ColumnExp field, final ValueExp value) + { + // we know that the Ts match in FieldMarshaller and ValueExp, but it's hard + // to convince the type system of that + final @SuppressWarnings("unchecked") FieldMarshaller fmarsh = + (FieldMarshaller)_types.getMarshaller(pClass).getFieldMarshaller(field.name); + _bindables.add(new Bindable() { + public void doBind (Connection conn, PreparedStatement stmt, int argIx) + throws Exception { + fmarsh.writeToStatement(stmt, argIx, value.getValue()); + } + }); _builder.append("?"); return null; } @@ -936,42 +980,6 @@ public abstract class BuildVisitor implements FragmentVisitor void doBind (Connection conn, PreparedStatement stmt, int argIx) throws Exception; } - protected static Bindable newBindable ( - final DepotMarshaller marshaller, final ColumnExp field, final Object pojo) - { - return new Bindable() { - public void doBind (Connection conn, PreparedStatement stmt, int argIx) - throws Exception { - marshaller.getFieldMarshaller(field.name).getAndWriteToStatement(stmt, argIx, pojo); - } - }; - } - - protected static Bindable newBindable (final Object value) - { - return new Bindable() { - public void doBind (Connection conn, PreparedStatement stmt, int argIx) - throws Exception { - // TODO: how can we abstract this fieldless marshalling - if (value instanceof ByteEnum) { - // byte enums require special conversion - stmt.setByte(argIx, ((ByteEnum)value).toByte()); - } else if (value instanceof Enum) { - // enums are converted to strings - stmt.setString(argIx, ((Enum)value).name()); - } else if (value instanceof int[]) { - // int arrays require conversion to byte arrays - int[] data = (int[])value; - ByteBuffer bbuf = ByteBuffer.allocate(data.length * 4); - bbuf.asIntBuffer().put(data); - stmt.setObject(argIx, bbuf.array()); - } else { - stmt.setObject(argIx, value); - } - } - }; - } - protected DepotTypes _types; /** For each SQL parameter ? we add an {@link Comparable} to bind to this list. */ diff --git a/src/test/java/com/samskivert/depot/TransformTest.java b/src/test/java/com/samskivert/depot/TransformTest.java index 0f8381a..3f5f6b1 100644 --- a/src/test/java/com/samskivert/depot/TransformTest.java +++ b/src/test/java/com/samskivert/depot/TransformTest.java @@ -240,6 +240,19 @@ public class TransformTest extends TestBase delete(in); } + @Test public void testUpdatePartial () + { + TransformRecord in = createAndInsert(new String[] { "one", "two", "three" }); + + EnumSet nbobs = EnumSet.of(ExtraOrdinal.ONE, ExtraOrdinal.THREE); + _repo.updatePartial(TransformRecord.getKey(in.recordId), TransformRecord.BOBS, nbobs); + + TransformRecord in2 = _repo.load(TransformRecord.getKey(in.recordId)); + assertEquals(nbobs, in2.bobs); + + delete(in); + } + protected TransformRecord createAndInsert (String[] strings) { TransformRecord in = new TransformRecord();