Skip to content

Commit

Permalink
Adds Datum#row() constructor methods
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedquinn committed Jan 24, 2025
1 parent 5b1eca6 commit a0b1ab1
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 0 deletions.
65 changes: 65 additions & 0 deletions partiql-spi/src/main/java/org/partiql/spi/value/Datum.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.time.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
* This is a representation of a value in PartiQL's type system. The intention of this modeling is to
Expand Down Expand Up @@ -691,6 +695,15 @@ static Datum struct() {
return struct(Collections.emptyList());
}

/**
* @param values the backing values
* @return a value of type {@link PType#STRUCT}
*/
@NotNull
static Datum struct(@NotNull Field... values) {
return new DatumStruct(Arrays.stream(values).collect(Collectors.toList()));
}

/**
* @param values the backing values
* @return a value of type {@link PType#STRUCT}
Expand All @@ -700,6 +713,58 @@ static Datum struct(@NotNull Iterable<Field> values) {
return new DatumStruct(values);
}

/**
* Returns an empty {@link PType#ROW}
* @return a value of type {@link PType#ROW}
*/
@NotNull
static Datum row() {
return new DatumRow(new ArrayList<>(), PType.row());
}

/**
* This creates a row.
* @param values the backing values
* @return a value of type {@link PType#ROW}
*/
@NotNull
static Datum row(@NotNull Field... values) {
return new DatumRow(Arrays.stream(values).collect(Collectors.toList()));
}

/**
* This creates a row. Use this if you'd like to save on the computational cost of computing the final type.
* @param typeFields the backing type fields
* @param values the backing values
* @return a value of type {@link PType#ROW}
*/
@NotNull
static Datum row(List<org.partiql.spi.types.Field> typeFields, @NotNull Field... values) {
return row(typeFields, Arrays.stream(values).collect(Collectors.toList()));
}

/**
* Creates a row with the given values.
* @param values the backing values
* @return a value of type {@link PType#ROW}
*/
@NotNull
static Datum row(@NotNull List<Field> values) {
return new DatumRow(values);
}

/**
* Creates a row with the given values. Use this if you'd like to save on the computational cost of computing the final type.
* @param typeFields the backing type fields
* @param values the backing values
* @return a value of type {@link PType#ROW}
*/
@NotNull
static Datum row(@NotNull List<org.partiql.spi.types.Field> typeFields, @NotNull List<Field> values) {
PType type = PType.row(typeFields);
return new DatumRow(values, type);
}

/**
* @param value the backing Ion
* @return a value of type {@link PType#VARIANT}
Expand Down
111 changes: 111 additions & 0 deletions partiql-spi/src/main/java/org/partiql/spi/value/DatumRow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.partiql.spi.value;

import org.jetbrains.annotations.NotNull;
import org.partiql.spi.types.PType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* This shall always be package-private (internal).
*/
class DatumRow implements Datum {

@NotNull
private final HashMap<String, List<Datum>> _delegate;

@NotNull
private final HashMap<String, List<Datum>> _delegateNormalized;

private final PType _type;

DatumRow(@NotNull Iterable<Field> fields, @NotNull PType type) {
_type = type;
_delegate = new HashMap<>();
_delegateNormalized = new HashMap<>();
for (Field field : fields) {
String key = field.getName();
String keyNormalized = field.getName().toLowerCase();
Datum value = field.getValue();
addFieldToStruct(_delegate, key, value);
addFieldToStruct(_delegateNormalized, keyNormalized, value);
}
}

DatumRow(@NotNull Iterable<Field> fields) {
this(fields, getTypeFromFields(fields));
}

private static PType getTypeFromFields(@NotNull Iterable<Field> fields) {
List<org.partiql.spi.types.Field> fieldTypes = new ArrayList<>();
fields.forEach((f) -> {
PType fType = f.getValue().getType();
org.partiql.spi.types.Field typeField = org.partiql.spi.types.Field.of(f.getName(), fType);
fieldTypes.add(typeField);
});
return PType.row(fieldTypes);
}

private void addFieldToStruct(Map<String, List<Datum>> struct, String key, Datum value) {
List<Datum> values = struct.getOrDefault(key, new ArrayList<>());
values.add(value);
struct.put(key, values);
}

@Override
@NotNull
public Iterator<Field> getFields() {
return _delegate.entrySet().stream().flatMap(
entry -> entry.getValue().stream().map(
value -> Field.of(entry.getKey(), value)
)
).iterator();
}

@Override
public Datum get(@NotNull String name) {
List<Datum> values = _delegate.get(name);
if (values == null) {
return null;
}
if (values.isEmpty()) {
return null;
}
return values.get(0);
}

@Override
public Datum getInsensitive(@NotNull String name) {
List<Datum> values = _delegateNormalized.get(name.toLowerCase());
if (values == null) {
return null;
}
if (values.isEmpty()) {
return null;
}
return values.get(0);
}

@NotNull
@Override
public PType getType() {
return _type;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("struct::{ ");
for (Map.Entry<String, List<Datum>> entry : _delegate.entrySet()) {
sb.append(entry.getKey());
sb.append(": ");
sb.append(entry.getValue().toString());
sb.append(", ");
}
sb.append(" }");
return sb.toString();
}
}

0 comments on commit a0b1ab1

Please sign in to comment.