Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
teletha committed Apr 20, 2024
1 parent f7b5e42 commit decb7ac
Show file tree
Hide file tree
Showing 18 changed files with 767 additions and 93 deletions.
5 changes: 3 additions & 2 deletions src/main/java/typewriter/api/QueryExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import typewriter.api.Specifier.StringSpecifier;
import typewriter.api.Specifier.ZonedDateTimeSpecifier;
import typewriter.query.AVGOption;
import typewriter.rdb.Dialect;

public abstract class QueryExecutor<M extends Identifiable, R, Q extends Queryable<M, Q>, Self extends QueryExecutor<M, R, Q, Self>>
implements Queryable<M, R>, Accumulable<M>, Updatable<M>, Deletable<M>, Restorable<M>, Transactional<Self> {
Expand Down Expand Up @@ -288,7 +289,7 @@ public R findBy(long id) {
* @param specifiers
* @return
*/
protected static Signal<String> names(Specifier[] specifiers) {
return I.signal(specifiers).skipNull().map(specifier -> specifier.propertyName());
protected static Signal<String> names(Dialect dialect, Specifier[] specifiers) {
return I.signal(specifiers).skipNull().map(specifier -> specifier.propertyName(dialect));
}
}
29 changes: 20 additions & 9 deletions src/main/java/typewriter/api/Specifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import java.util.function.Function;

import kiss.I;
import reincarnation.Reincarnation;
import typewriter.query.SQLCoder;
import typewriter.rdb.Dialect;

/**
* Generic property specifier.
Expand Down Expand Up @@ -55,19 +58,27 @@ default Method method() {
*
* @return
*/
default String propertyName() {
default String propertyName(Dialect dialect) {
Method method = method();
String name = method.getName();
if (method.getReturnType() == boolean.class) {
if (name.startsWith("is")) {
name = name.substring(2);
}
if (method.isSynthetic()) {
// lambda expression
SQLCoder coder = new SQLCoder(method);
Reincarnation.exhume(method.getDeclaringClass()).rebirth(coder);
return coder.write(dialect);
} else {
if (name.startsWith("get")) {
name = name.substring(3);
// method reference
String name = method.getName();
if (method.getReturnType() == boolean.class) {
if (name.startsWith("is")) {
name = name.substring(2);
}
} else {
if (name.startsWith("get")) {
name = name.substring(3);
}
}
return Introspector.decapitalize(name);
}
return Introspector.decapitalize(name);
}

/**
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/typewriter/mongo/Mongo.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public long count() {
public <V> Signal<V> distinct(Specifier<M, V> specifier) {
return new Signal<>((observer, disposer) -> {
try {
Property property = model.property(specifier.propertyName());
Property property = model.property(specifier.propertyName(null));

DistinctIterable<V> founds = collection.distinct(property.name, (Class<V>) property.model.type);
for (V found : founds) {
Expand All @@ -190,23 +190,23 @@ public <V> Signal<V> distinct(Specifier<M, V> specifier) {
*/
@Override
public <C extends Comparable> C min(Specifier<M, C> specifier) {
return (C) collection.aggregate(List.of(group(null, Accumulators.min("R", "$" + specifier.propertyName())))).first().get("R");
return (C) collection.aggregate(List.of(group(null, Accumulators.min("R", "$" + specifier.propertyName(null))))).first().get("R");
}

/**
* {@inheritDoc}
*/
@Override
public <C extends Comparable> C max(Specifier<M, C> specifier) {
return (C) collection.aggregate(List.of(group(null, Accumulators.max("R", "$" + specifier.propertyName())))).first().get("R");
return (C) collection.aggregate(List.of(group(null, Accumulators.max("R", "$" + specifier.propertyName(null))))).first().get("R");
}

/**
* {@inheritDoc}
*/
@Override
public <N extends Number> Signal<Double> avg(Specifier<M, N> specifier, UnaryOperator<AVGOption<M>> option) {
return I.signal(collection.aggregate(List.of(group(null, Accumulators.avg("R", "$" + specifier.propertyName()))))
return I.signal(collection.aggregate(List.of(group(null, Accumulators.avg("R", "$" + specifier.propertyName(null)))))
.first()
.getDouble("R"));
}
Expand All @@ -216,7 +216,7 @@ public <N extends Number> Signal<Double> avg(Specifier<M, N> specifier, UnaryOpe
*/
@Override
public <N extends Number> N sum(Specifier<M, N> specifier) {
return (N) collection.aggregate(List.of(group(null, Accumulators.sum("R", "$" + specifier.propertyName())))).first().get("R");
return (N) collection.aggregate(List.of(group(null, Accumulators.sum("R", "$" + specifier.propertyName(null))))).first().get("R");
}

/**
Expand Down Expand Up @@ -268,7 +268,7 @@ private Signal<M> find(Function<MongoCollection, FindIterable<Document>> process
public Signal<M> restore(M model, Specifier<M, ?>... specifiers) {
return new Signal<M>((observer, disposer) -> {
try {
List<String> names = names(specifiers).toList();
List<String> names = names(null, specifiers).toList();

Document doc = collection.find(identify(model)).projection(names.isEmpty() ? null : Projections.include(names)).first();

Expand Down Expand Up @@ -300,7 +300,7 @@ public void delete(M model, Specifier<M, ?>... specifiers) {
List<Bson> operations = new ArrayList();
for (Specifier<M, ?> specifier : specifiers) {
if (specifier != null) {
operations.add(Updates.unset(specifier.propertyName()));
operations.add(Updates.unset(specifier.propertyName(null)));
}
}
collection.updateOne(identify(model), Updates.combine(operations));
Expand All @@ -325,7 +325,7 @@ public void update(M model, Specifier<M, ?>... specifiers) {
List<Bson> operations = new ArrayList();
for (Specifier<M, ?> specifier : specifiers) {
if (specifier != null) {
String name = specifier.propertyName();
String name = specifier.propertyName(null);
Property property = m.property(name);

operations.add(Updates.set(name, m.get(model, property)));
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/typewriter/mongo/MongoConstraint.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
*/
package typewriter.mongo;

import static java.util.Objects.requireNonNull;
import static typewriter.api.Constraint.ZonedDateTimeConstraint.UTC;
import static java.util.Objects.*;
import static typewriter.api.Constraint.ZonedDateTimeConstraint.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -49,7 +49,7 @@ abstract class MongoConstraint<V, Self> implements Constraint<V, Self> {
* @param specifier The property specifier.
*/
protected MongoConstraint(Specifier specifier) {
this.propertyName = specifier.propertyName();
this.propertyName = specifier.propertyName(null);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/typewriter/mongo/MongoQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public <N> MongoQuery<M> sortBy(Specifier<M, N> specifier, boolean ascending) {
if (sorts == null) {
sorts = new ArrayList();
}
sorts.add(I.pair(specifier.propertyName(), ascending));
sorts.add(I.pair(specifier.propertyName(null), ascending));

return this;
}
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/typewriter/query/AVGOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.function.UnaryOperator;

import typewriter.api.Specifier;
import typewriter.rdb.Dialect;

public class AVGOption<M> {

Expand All @@ -23,11 +24,14 @@ public class AVGOption<M> {

public String orderBy;

private final Dialect dialect;

/**
* @param option
*/
public AVGOption(UnaryOperator<AVGOption> option) {
public AVGOption(UnaryOperator<AVGOption> option, Dialect dialect) {
if (option != null) option.apply(this);
this.dialect = dialect;
}

/**
Expand Down Expand Up @@ -58,7 +62,7 @@ public AVGOption frame(int from, int to) {
* @return
*/
public AVGOption orderBy(Specifier<M, ?> specifier) {
this.orderBy = specifier.propertyName();
this.orderBy = specifier.propertyName(dialect);
return this;
}
}
52 changes: 52 additions & 0 deletions src/main/java/typewriter/query/MethodChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 Nameless Production Committee
*
* Licensed under the MIT License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/mit-license.php
*/
package typewriter.query;

import java.util.List;

import ch.epfl.labos.iu.orm.queryll2.path.PathAnalysisMethodChecker;
import ch.epfl.labos.iu.orm.queryll2.symbolic.BasicSymbolicInterpreter.OperationSideEffect;
import ch.epfl.labos.iu.orm.queryll2.symbolic.MethodSignature;
import ch.epfl.labos.iu.orm.queryll2.symbolic.TypedValue;

public class MethodChecker implements PathAnalysisMethodChecker {

/**
* {@inheritDoc}
*/
@Override
public boolean isFluentChaining(MethodSignature m) {
return false;
}

/**
* {@inheritDoc}
*/
@Override
public boolean isPutFieldAllowed() {
return false;
}

/**
* {@inheritDoc}
*/
@Override
public OperationSideEffect isStaticMethodSafe(MethodSignature m) {
return null;
}

/**
* {@inheritDoc}
*/
@Override
public OperationSideEffect isMethodSafe(MethodSignature m, TypedValue base, List<TypedValue> args) {
return null;
}
}
90 changes: 90 additions & 0 deletions src/main/java/typewriter/query/QueryWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (C) 2024 Nameless Production Committee
*
* Licensed under the MIT License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/mit-license.php
*/
package typewriter.query;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import typewriter.api.Identifiable;
import typewriter.api.Specifier;
import typewriter.rdb.Dialect;

public class QueryWriter<M extends Identifiable> {

private final Dialect dialect;

private final List<String> selects = new ArrayList();

/**
* @param dialect
*/
public QueryWriter(Dialect dialect) {
this.dialect = dialect;
}

/**
* Select column by name.
*
* @param column
* @return
*/
public QueryWriter<M> select(String column) {
return selectAs(null, column);
}

/**
* Select column by name with alias.
*
* @param alias An alias of column.
* @param column A column name.
* @return
*/
public QueryWriter<M> selectAs(String alias, String column) {
if (alias == null || alias.isEmpty()) {
selects.add(column);
} else {
selects.add(column + " AS " + alias);
}
return this;
}

/**
* Select column by {@link Specifier}.
*
* @param specifier A column specifier.
* @return
*/
public QueryWriter<M> select(Specifier<M, ?> specifier) {
return select(specifier.propertyName(dialect));
}

/**
* Select column by {@link Specifier} with alias.
*
* @param alias An alias of column.
* @param specifier A column specifier.
* @return
*/
public QueryWriter<M> selectAs(String alias, Specifier<M, ?> specifier) {
return selectAs(alias, specifier.propertyName(dialect));
}

/**
* @param dialect
*/
public String build(Dialect dialect) {
StringBuilder builder = new StringBuilder();

builder.append(selects.stream().collect(Collectors.joining(", ", "SELECT ", "")));

return builder.toString();
}
}
Loading

0 comments on commit decb7ac

Please sign in to comment.