Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IGNITE-14692 Validate tuple for STRICT schema #123

Merged
merged 24 commits into from May 20, 2021
7 changes: 7 additions & 0 deletions modules/api/src/main/java/org/apache/ignite/table/Tuple.java
Expand Up @@ -27,6 +27,13 @@
* Provides specialized method for some value-types to avoid boxing/unboxing.
*/
public interface Tuple {
/**
* Returns {@code true} if this tuple contains a column with the specified name.
*
* @return {@code true} if this tuple contains a column with the specified name. Otherwise returns {@code false}.
*/
boolean contains(String colName);

/**
* Gets column value for given column name.
*
Expand Down
Expand Up @@ -23,7 +23,7 @@
* A fixed-sized type representing a bitmask of <code>n</code> bits. The actual size of a bitmask will round up
* to the smallest number of bytes required to store <code>n</code> bits.
*/
public class Bitmask extends NativeType {
public class BitmaskNativeType extends NativeType {
/** */
private final int bits;

Expand All @@ -33,16 +33,16 @@ public class Bitmask extends NativeType {
* @param nBits Maximum number of bits in the bitmask.
* @return Bitmask type.
*/
public static Bitmask of(int nBits) {
return new Bitmask(nBits);
public static BitmaskNativeType of(int nBits) {
return new BitmaskNativeType(nBits);
}

/**
* Creates a bitmask type of size <code>bits</code>. In row will round up to the closest full byte.
*
* @param bits The number of bits in the bitmask.
*/
protected Bitmask(int bits) {
protected BitmaskNativeType(int bits) {
super(NativeTypeSpec.BITMASK, (bits + 7) / 8);

this.bits = bits;
Expand All @@ -63,7 +63,7 @@ public int bits() {
if (o == null || getClass() != o.getClass())
return false;

Bitmask that = (Bitmask)o;
BitmaskNativeType that = (BitmaskNativeType)o;

return bits == that.bits;
}
Expand All @@ -79,7 +79,7 @@ public int bits() {

if (res == 0) {
// The passed in object is also a bitmask, compare the number of bits.
Bitmask that = (Bitmask)o;
BitmaskNativeType that = (BitmaskNativeType)o;

return Integer.compare(bits, that.bits);
}
Expand All @@ -89,6 +89,6 @@ public int bits() {

/** {@inheritDoc} */
@Override public String toString() {
return S.toString(Bitmask.class.getSimpleName(), "bits", bits, "typeSpec", spec(), "len", length());
return S.toString(BitmaskNativeType.class.getSimpleName(), "bits", bits, "typeSpec", spec(), "len", sizeInBytes());
}
}
Expand Up @@ -17,7 +17,9 @@

package org.apache.ignite.internal.schema;

import java.util.function.Supplier;
import org.apache.ignite.internal.tostring.S;
import org.jetbrains.annotations.NotNull;

/**
* Column description for a type schema. Column contains a column name, a column type and a nullability flag.
Expand All @@ -26,6 +28,9 @@
* flag is not taken into account when columns are compared.
*/
public class Column implements Comparable<Column> {
/** Default return NULL. */
tledkov marked this conversation as resolved.
Show resolved Hide resolved
private static final Supplier<Object> NULL_DEFAULT_SUPPLIER = () -> null;

/** Absolute index in schema descriptor. */
private final int schemaIndex;

Expand All @@ -44,6 +49,11 @@ public class Column implements Comparable<Column> {
*/
private final boolean nullable;

/**
* Default value supplier.
*/
private final Supplier<Object> defValSup;

/**
* @param name Column name.
* @param type An instance of column data type.
Expand All @@ -54,7 +64,22 @@ public Column(
NativeType type,
boolean nullable
) {
this(-1, name, type, nullable);
this(-1, name, type, nullable, NULL_DEFAULT_SUPPLIER);
}

/**
* @param name Column name.
* @param type An instance of column data type.
* @param nullable If {@code false}, null values will not be allowed for this column.
* @param defValSup Default value supplier.
*/
public Column(
String name,
NativeType type,
boolean nullable,
@NotNull Supplier<Object> defValSup
) {
this(-1, name, type, nullable, defValSup);
}

/**
Expand All @@ -67,12 +92,14 @@ public Column(
int schemaIndex,
String name,
NativeType type,
boolean nullable
boolean nullable,
@NotNull Supplier<Object> defValSup
) {
this.schemaIndex = schemaIndex;
this.name = name;
this.type = type;
this.nullable = nullable;
this.defValSup = defValSup;
}

/**
Expand Down Expand Up @@ -103,6 +130,19 @@ public boolean nullable() {
return nullable;
}

/**
* Get default value for the column.
*
* @return Default value.
*/
public Object defaultValue() {
Object val = defValSup.get();

assert nullable || val != null : "Null value is not accepted for not nullable column: [col=" + this + ']';

return val;
}

/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
Expand Down Expand Up @@ -132,6 +172,35 @@ public boolean nullable() {
return name.compareTo(o.name);
}

/**
* Validate the object by column's constraint.
*/
public void validate(Object val) {
if (val == null && !nullable) {
throw new IllegalArgumentException("Failed to set column (null was passed, but column is not nullable): " +
"[col=" + this + ']');
}

NativeType objType = NativeType.fromObject(val);

if (objType != null && type.mismatch(objType)) {
throw new InvalidTypeException("Column's type mismatch [" +
"column=" + this +
", expectedType=" + type +
", actualType=" + objType +
", val=" + val + ']');
}
}

/**
* Copy column with new schema index.
*
* @param schemaIndex new schema index.
tledkov marked this conversation as resolved.
Show resolved Hide resolved
*/
public Column copy(int schemaIndex) {
return new Column(schemaIndex, name, type, nullable, defValSup);
}

/** {@inheritDoc} */
@Override public String toString() {
return S.toString(Column.class, this);
Expand Down
Expand Up @@ -195,7 +195,7 @@ private Column[] sortedCopy(int schemaBaseIdx, Column[] cols) {
for (int i = 0; i < cp.length; i++) {
Column c = cp[i];

cp[i] = new Column(schemaBaseIdx + i, c.name(), c.type(), c.nullable());
cp[i] = c.copy(schemaBaseIdx + i);
}

return cp;
Expand Down Expand Up @@ -287,7 +287,7 @@ private int foldManual(int b, int mask) {
", mask=" + mask +
", cols" + Arrays.toString(cols) + ']';

size += cols[idx].type().length();
size += cols[idx].type().sizeInBytes();
}
}

Expand All @@ -309,6 +309,24 @@ public int columnIndex(String colName) {
throw new NoSuchElementException("No field '" + colName + "' defined");
}

/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
return true;

if (o == null || getClass() != o.getClass())
return false;

Columns columns = (Columns)o;

return Arrays.equals(cols, columns.cols);
}

/** {@inheritDoc} */
@Override public int hashCode() {
return Arrays.hashCode(cols);
}

/** {@inheritDoc} */
@Override public String toString() {
return S.arrayToString(cols);
Expand Down