Search in sources :

Example 31 with BinaryObjectBuilder

use of org.apache.ignite.binary.BinaryObjectBuilder in project ignite by apache.

the class UpdatePlan method processRowForUpdate.

/**
 * Convert a row into value.
 *
 * @param row Row to process.
 * @throws IgniteCheckedException if failed.
 * @return Tuple contains: [key, old value, new value]
 */
public T3<Object, Object, Object> processRowForUpdate(List<?> row) throws IgniteCheckedException {
    GridH2RowDescriptor rowDesc = tbl.rowDescriptor();
    GridQueryTypeDescriptor desc = rowDesc.type();
    GridCacheContext cctx = rowDesc.context();
    boolean hasNewVal = (valColIdx != -1);
    boolean hasProps = !hasNewVal || colNames.length > 1;
    Object key = row.get(0);
    Object oldVal = row.get(1);
    if (cctx.binaryMarshaller() && !(oldVal instanceof BinaryObject))
        oldVal = cctx.grid().binary().toBinary(oldVal);
    Object newVal;
    Map<String, Object> newColVals = new HashMap<>();
    for (int i = 0; i < colNames.length; i++) {
        if (hasNewVal && i == valColIdx - 2)
            continue;
        GridQueryProperty prop = tbl.rowDescriptor().type().property(colNames[i]);
        assert prop != null : "Unknown property: " + colNames[i];
        newColVals.put(colNames[i], DmlUtils.convert(row.get(i + 2), rowDesc, prop.type(), colTypes[i]));
    }
    newVal = valSupplier.apply(row);
    if (newVal == null)
        throw new IgniteSQLException("New value for UPDATE must not be null", IgniteQueryErrorCode.NULL_VALUE);
    // Skip key and value - that's why we start off with 3rd column
    for (int i = 0; i < tbl.getColumns().length - DEFAULT_COLUMNS_COUNT; i++) {
        Column c = tbl.getColumn(i + DEFAULT_COLUMNS_COUNT);
        if (rowDesc.isKeyValueOrVersionColumn(c.getColumnId()))
            continue;
        GridQueryProperty prop = desc.property(c.getName());
        if (prop.key())
            // Don't get values of key's columns - we won't use them anyway
            continue;
        boolean hasNewColVal = newColVals.containsKey(c.getName());
        if (!hasNewColVal)
            continue;
        Object colVal = newColVals.get(c.getName());
        // UPDATE currently does not allow to modify key or its fields, so we must be safe to pass null as key.
        rowDesc.setColumnValue(null, newVal, colVal, i);
    }
    if (cctx.binaryMarshaller() && hasProps) {
        assert newVal instanceof BinaryObjectBuilder;
        newVal = ((BinaryObjectBuilder) newVal).build();
    }
    desc.validateKeyAndValue(key, newVal);
    return new T3<>(key, oldVal, newVal);
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) HashMap(java.util.HashMap) GridQueryTypeDescriptor(org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor) GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) BinaryObject(org.apache.ignite.binary.BinaryObject) Column(org.h2.table.Column) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder) T3(org.apache.ignite.internal.util.typedef.T3)

Example 32 with BinaryObjectBuilder

use of org.apache.ignite.binary.BinaryObjectBuilder in project ignite by apache.

the class UpdatePlan method processRow.

/**
 * Convert a row into key-value pair.
 *
 * @param row Row to process.
 * @throws IgniteCheckedException if failed.
 */
public IgniteBiTuple<?, ?> processRow(List<?> row) throws IgniteCheckedException {
    if (mode != BULK_LOAD && row.size() != colNames.length)
        throw new IgniteSQLException("Not enough values in a row: " + row.size() + " instead of " + colNames.length, IgniteQueryErrorCode.ENTRY_PROCESSING);
    GridH2RowDescriptor rowDesc = tbl.rowDescriptor();
    GridQueryTypeDescriptor desc = rowDesc.type();
    GridCacheContext cctx = rowDesc.context();
    Object key = keySupplier.apply(row);
    if (QueryUtils.isSqlType(desc.keyClass())) {
        assert keyColIdx != -1;
        key = DmlUtils.convert(key, rowDesc, desc.keyClass(), colTypes[keyColIdx]);
    }
    Object val = valSupplier.apply(row);
    if (QueryUtils.isSqlType(desc.valueClass())) {
        assert valColIdx != -1;
        val = DmlUtils.convert(val, rowDesc, desc.valueClass(), colTypes[valColIdx]);
    }
    if (key == null) {
        if (F.isEmpty(desc.keyFieldName()))
            throw new IgniteSQLException("Key for INSERT, COPY, or MERGE must not be null", IgniteQueryErrorCode.NULL_KEY);
        else
            throw new IgniteSQLException("Null value is not allowed for column '" + desc.keyFieldName() + "'", IgniteQueryErrorCode.NULL_KEY);
    }
    if (val == null) {
        if (F.isEmpty(desc.valueFieldName()))
            throw new IgniteSQLException("Value for INSERT, COPY, MERGE, or UPDATE must not be null", IgniteQueryErrorCode.NULL_VALUE);
        else
            throw new IgniteSQLException("Null value is not allowed for column '" + desc.valueFieldName() + "'", IgniteQueryErrorCode.NULL_VALUE);
    }
    int actualColCnt = Math.min(colNames.length, row.size());
    Map<String, Object> newColVals = new HashMap<>();
    for (int i = 0; i < actualColCnt; i++) {
        if (i == keyColIdx || i == valColIdx)
            continue;
        String colName = colNames[i];
        GridQueryProperty prop = desc.property(colName);
        assert prop != null;
        Class<?> expCls = prop.type();
        newColVals.put(colName, DmlUtils.convert(row.get(i), rowDesc, expCls, colTypes[i]));
    }
    desc.setDefaults(key, val);
    // We update columns in the order specified by the table for a reason - table's
    // column order preserves their precedence for correct update of nested properties.
    Column[] tblCols = tbl.getColumns();
    // First 3 columns are _key, _val and _ver. Skip 'em.
    for (int i = DEFAULT_COLUMNS_COUNT; i < tblCols.length; i++) {
        if (tbl.rowDescriptor().isKeyValueOrVersionColumn(i))
            continue;
        String colName = tblCols[i].getName();
        if (!newColVals.containsKey(colName))
            continue;
        Object colVal = newColVals.get(colName);
        desc.setValue(colName, key, val, colVal);
    }
    if (cctx.binaryMarshaller()) {
        if (key instanceof BinaryObjectBuilder)
            key = ((BinaryObjectBuilder) key).build();
        if (val instanceof BinaryObjectBuilder)
            val = ((BinaryObjectBuilder) val).build();
    }
    desc.validateKeyAndValue(key, val);
    return new IgniteBiTuple<>(key, val);
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) HashMap(java.util.HashMap) IgniteBiTuple(org.apache.ignite.lang.IgniteBiTuple) GridQueryTypeDescriptor(org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor) GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) Column(org.h2.table.Column) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder)

Example 33 with BinaryObjectBuilder

use of org.apache.ignite.binary.BinaryObjectBuilder in project ignite by apache.

the class UpdatePlanBuilder method createSupplier.

/**
 * Detect appropriate method of instantiating key or value (take from param, create binary builder,
 * invoke default ctor, or allocate).
 *
 * @param cctx Cache context.
 * @param desc Table descriptor.
 * @param colIdx Column index if key or value is present in columns list, {@code -1} if it's not.
 * @param hasProps Whether column list affects individual properties of key or value.
 * @param key Whether supplier should be created for key or for value.
 * @return Closure returning key or value.
 * @throws IgniteCheckedException If failed.
 */
@SuppressWarnings({ "ConstantConditions", "unchecked" })
private static KeyValueSupplier createSupplier(final GridCacheContext<?, ?> cctx, GridQueryTypeDescriptor desc, final int colIdx, boolean hasProps, final boolean key, boolean forUpdate) throws IgniteCheckedException {
    final String typeName = key ? desc.keyTypeName() : desc.valueTypeName();
    // Try to find class for the key locally.
    final Class<?> cls = key ? U.firstNotNull(U.classForName(desc.keyTypeName(), null), desc.keyClass()) : desc.valueClass();
    boolean isSqlType = QueryUtils.isSqlType(cls);
    // If we don't need to construct anything from scratch, just return value from given list.
    if (isSqlType || !hasProps) {
        if (colIdx != -1)
            return new PlainValueSupplier(colIdx);
        else if (isSqlType)
            // Non constructable keys and values (SQL types) must be present in the query explicitly.
            throw new IgniteCheckedException((key ? "Key" : "Value") + " is missing from query");
    }
    if (cctx.binaryMarshaller()) {
        if (colIdx != -1) {
            // If we have key or value explicitly present in query, create new builder upon them...
            return new KeyValueSupplier() {

                /**
                 * {@inheritDoc}
                 */
                @Override
                public Object apply(List<?> arg) throws IgniteCheckedException {
                    Object obj = arg.get(colIdx);
                    if (obj == null)
                        return null;
                    BinaryObject bin = cctx.grid().binary().toBinary(obj);
                    BinaryObjectBuilder builder = cctx.grid().binary().builder(bin);
                    cctx.prepareAffinityField(builder);
                    return builder;
                }
            };
        } else {
            // ...and if we don't, just create a new builder.
            return new KeyValueSupplier() {

                /**
                 * {@inheritDoc}
                 */
                @Override
                public Object apply(List<?> arg) throws IgniteCheckedException {
                    BinaryObjectBuilder builder = cctx.grid().binary().builder(typeName);
                    cctx.prepareAffinityField(builder);
                    return builder;
                }
            };
        }
    } else {
        if (colIdx != -1) {
            if (forUpdate && colIdx == 1) {
                // so we have to clone it. And on UPDATE we don't expect any key supplier.
                assert !key;
                return new KeyValueSupplier() {

                    /**
                     * {@inheritDoc}
                     */
                    @Override
                    public Object apply(List<?> arg) throws IgniteCheckedException {
                        byte[] oldPropBytes = cctx.marshaller().marshal(arg.get(1));
                        // colVal is another object now, we can mutate it
                        return cctx.marshaller().unmarshal(oldPropBytes, U.resolveClassLoader(cctx.gridConfig()));
                    }
                };
            } else
                // We either are not updating, or the new value is given explicitly, no cloning needed.
                return new PlainValueSupplier(colIdx);
        }
        Constructor<?> ctor;
        try {
            ctor = cls.getDeclaredConstructor();
            ctor.setAccessible(true);
        } catch (NoSuchMethodException | SecurityException ignored) {
            ctor = null;
        }
        if (ctor != null) {
            final Constructor<?> ctor0 = ctor;
            // Use default ctor, if it's present...
            return new KeyValueSupplier() {

                /**
                 * {@inheritDoc}
                 */
                @Override
                public Object apply(List<?> arg) throws IgniteCheckedException {
                    try {
                        return ctor0.newInstance();
                    } catch (Exception e) {
                        if (S.INCLUDE_SENSITIVE)
                            throw new IgniteCheckedException("Failed to instantiate " + (key ? "key" : "value") + " [type=" + typeName + ']', e);
                        else
                            throw new IgniteCheckedException("Failed to instantiate " + (key ? "key" : "value") + '.', e);
                    }
                }
            };
        } else {
            // ...or allocate new instance with unsafe, if it's not
            return new KeyValueSupplier() {

                /**
                 * {@inheritDoc}
                 */
                @Override
                public Object apply(List<?> arg) throws IgniteCheckedException {
                    try {
                        return GridUnsafe.allocateInstance(cls);
                    } catch (InstantiationException e) {
                        if (S.INCLUDE_SENSITIVE)
                            throw new IgniteCheckedException("Failed to instantiate " + (key ? "key" : "value") + " [type=" + typeName + ']', e);
                        else
                            throw new IgniteCheckedException("Failed to instantiate " + (key ? "key" : "value") + '.', e);
                    }
                }
            };
        }
    }
}
Also used : SQLException(java.sql.SQLException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) BinaryObject(org.apache.ignite.binary.BinaryObject) ArrayList(java.util.ArrayList) List(java.util.List) BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder)

Example 34 with BinaryObjectBuilder

use of org.apache.ignite.binary.BinaryObjectBuilder in project ignite by apache.

the class BinaryMarshallerSelfTest method testFieldOrderByBuilder.

/**
 * The test must be refactored after {@link IgniteSystemProperties#IGNITE_BINARY_SORT_OBJECT_FIELDS}
 * is removed.
 *
 * @throws Exception If failed.
 */
public void testFieldOrderByBuilder() throws Exception {
    if (BinaryUtils.FIELDS_SORTED_ORDER)
        return;
    BinaryMarshaller m = binaryMarshaller();
    BinaryObjectBuilder builder = new BinaryObjectBuilderImpl(binaryContext(m), "MyFakeClass");
    String[] fieldNames = { "field9", "field8", "field0", "field1", "field2" };
    for (String fieldName : fieldNames) builder.setField(fieldName, 0);
    BinaryObject binObj = builder.build();
    Collection<String> fieldsBin = binObj.type().fieldNames();
    assertEquals(fieldNames.length, fieldsBin.size());
    int i = 0;
    for (String fieldName : fieldsBin) {
        assertEquals(fieldNames[i], fieldName);
        ++i;
    }
}
Also used : BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilderImpl(org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder)

Example 35 with BinaryObjectBuilder

use of org.apache.ignite.binary.BinaryObjectBuilder in project ignite by apache.

the class BinaryMarshallerSelfTest method testThreadLocalArrayReleased.

/**
 * @throws IgniteCheckedException If failed.
 */
public void testThreadLocalArrayReleased() throws Exception {
    // Checking the writer directly.
    assertEquals(false, INSTANCE.isAcquired());
    BinaryMarshaller marsh = binaryMarshaller();
    try (BinaryWriterExImpl writer = new BinaryWriterExImpl(binaryContext(marsh))) {
        assertEquals(true, INSTANCE.isAcquired());
        writer.writeString("Thread local test");
        writer.array();
        assertEquals(true, INSTANCE.isAcquired());
    }
    // Checking the binary marshaller.
    assertEquals(false, INSTANCE.isAcquired());
    marsh = binaryMarshaller();
    marsh.marshal(new SimpleObject());
    assertEquals(false, INSTANCE.isAcquired());
    marsh = binaryMarshaller();
    // Checking the builder.
    BinaryObjectBuilder builder = new BinaryObjectBuilderImpl(binaryContext(marsh), "org.gridgain.foo.bar.TestClass");
    builder.setField("a", "1");
    BinaryObject binaryObj = builder.build();
    assertEquals(false, INSTANCE.isAcquired());
}
Also used : BinaryObject(org.apache.ignite.binary.BinaryObject) BinaryObjectBuilderImpl(org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl) BinaryObjectBuilder(org.apache.ignite.binary.BinaryObjectBuilder)

Aggregations

BinaryObjectBuilder (org.apache.ignite.binary.BinaryObjectBuilder)83 BinaryObject (org.apache.ignite.binary.BinaryObject)63 Ignite (org.apache.ignite.Ignite)11 IgniteBinary (org.apache.ignite.IgniteBinary)8 GridBinaryTestClasses (org.apache.ignite.internal.binary.mutabletest.GridBinaryTestClasses)7 Date (java.util.Date)4 HashMap (java.util.HashMap)4 BinaryType (org.apache.ignite.binary.BinaryType)4 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)4 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 GridQueryProperty (org.apache.ignite.internal.processors.query.GridQueryProperty)3 GridQueryTypeDescriptor (org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor)3 GridH2RowDescriptor (org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor)3 GridAbsPredicate (org.apache.ignite.internal.util.lang.GridAbsPredicate)3 Column (org.h2.table.Column)3 Field (java.lang.reflect.Field)2 SQLException (java.sql.SQLException)2 LinkedHashMap (java.util.LinkedHashMap)2 UUID (java.util.UUID)2