Skip to content

Instantly share code, notes, and snippets.

@lukaseder
Created September 18, 2019 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukaseder/71c42efb450adf07c9cb482e66ff951a to your computer and use it in GitHub Desktop.
Save lukaseder/71c42efb450adf07c9cb482e66ff951a to your computer and use it in GitHub Desktop.
A simple proof of concept for a new Query Object Model in Java, using Immutables annotations
/*
* This work is dual-licensed
* - under the Apache Software License 2.0 (the "ASL")
* - under the jOOQ License and Maintenance Agreement (the "jOOQ License")
* =============================================================================
* You may choose which license applies to you:
*
* - If you're using this work with Open Source databases, you may choose
* either ASL or jOOQ License.
* - If you're using this work with at least one commercial database, you must
* choose jOOQ License
*
* For more information, please visit http://www.jooq.org/licenses
*
* Apache Software License 2.0:
* -----------------------------------------------------------------------------
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* jOOQ License and Maintenance Agreement:
* -----------------------------------------------------------------------------
* Data Geekery grants the Customer the non-exclusive, timely limited and
* non-transferable license to install and use the Software under the terms of
* the jOOQ License and Maintenance Agreement.
*
* This library is distributed with a LIMITED WARRANTY. See the jOOQ License
* and Maintenance Agreement for more details: http://www.jooq.org/licensing
*/
package org.jooq.qom;
import static org.jooq.qom.QOM.ICompOp.GT;
import static org.jooq.qom.QOM.ICompOp.LT;
import java.util.Arrays;
import java.util.List;
import org.immutables.value.Value;
public class QOM {
public static void main(String[] args) {
List<Q> list = Arrays.asList(
CIVal.of(1),
CIAnd.of(
CIComp.of(
CIFieldRef.of(
CITableRef.of(
CISchemaRef.of(CIIdent.of("S")),
CIIdent.of("T")
),
CIIdent.of("C")
),
GT,
CIVal.of(2)
),
CIComp.of(
CIFieldRef.of(
CITableRef.of(
CISchemaRef.of(CIIdent.of("S")),
CIIdent.of("U")
),
CIIdent.of("C")
),
LT,
CIVal.of(2)
)
)
);
list.forEach(System.out::println);
System.out.println();
list.stream().map(QOM::render).forEach(System.out::println);
System.out.println();
list.stream().map(QOM::map).forEach(System.out::println);
System.out.println();
list.stream().map(QOM::map).map(QOM::render).forEach(System.out::println);
System.out.println();
}
public static String render(Q q) {
return render(q, new StringBuilder()).toString();
}
public static StringBuilder render(Q q, StringBuilder sb) {
if (q instanceof IIdent) {
sb.append(((IIdent) q).name());
}
else if (q instanceof IAnd) {
render(((IAnd) q).lhs(), sb);
sb.append(" and ");
render(((IAnd) q).rhs(), sb);
}
else if (q instanceof ICompOp) {
switch ((ICompOp) q) {
case EQ: sb.append(" = "); break;
case NE: sb.append(" != "); break;
case LT: sb.append(" < "); break;
case LE: sb.append(" <= "); break;
case GT: sb.append(" > "); break;
case GE: sb.append(" >= "); break;
default: throw new UnsupportedOperationException();
}
}
else if (q instanceof IComp) {
render(((IComp<?>) q).lhs(), sb);
render(((IComp<?>) q).op(), sb);
render(((IComp<?>) q).rhs(), sb);
}
else if (q instanceof IFieldRef) {
render(((IFieldRef<?>) q).table(), sb);
sb.append(".");
render(((IFieldRef<?>) q).ident(), sb);
}
else if (q instanceof ITableRef) {
render(((ITableRef) q).ident(), sb);
}
else if (q instanceof ISchemaRef) {
render(((ISchemaRef) q).ident(), sb);
}
else if (q instanceof IVal) {
sb.append(((IVal<?>) q).value());
}
return sb;
}
public static <T extends Q> T map(T q) {
if (q instanceof IIdent) {
return q;
}
else if (q instanceof CIAnd) {
CIAnd c = (CIAnd) q;
return (T) c.withLhs(map(c.lhs())).withRhs(map(c.rhs()));
}
else if (q instanceof ICompOp) {
return q;
}
else if (q instanceof CIComp) {
CIComp c = (CIComp) q;
return (T) c.withLhs(map(c.lhs())).withOp(c.op()).withRhs(c.rhs());
}
else if (q instanceof CIFieldRef) {
CIFieldRef c = (CIFieldRef) q;
return (T) c.withTable(map(c.table())).withIdent(map(c.ident()));
}
else if (q instanceof CITableRef) {
CITableRef c = (CITableRef) q;
return (T) c.withSchema(map(c.schema()))
.withIdent("T".equals(c.ident().name())
? map(CIIdent.of("X"))
: map(c.ident()));
}
else if (q instanceof CISchemaRef) {
CISchemaRef c = (CISchemaRef) q;
return (T) c.withIdent(map(c.ident()));
}
else if (q instanceof CIVal) {
CIVal c = (CIVal) q;
return (T) c.withValue(c.value());
}
else {
throw new UnsupportedOperationException();
}
}
public interface Q {}
public interface QField<T> extends Q {}
public interface QTable extends Q {}
public interface QSchema extends Q {}
public interface QCondition extends Q {}
public interface QName extends Q {}
public interface QQuery extends Q {}
@Value.Immutable
public interface ICreateTable extends QQuery {
@Value.Parameter
QTable table();
}
@Value.Immutable
public interface IVal<T> extends QField<T> {
@Value.Parameter
T value();
}
@Value.Immutable
public interface IIdent extends QName {
@Value.Parameter
String name();
}
@Value.Immutable
public interface IFieldRef<T> extends QField<T> {
@Value.Parameter
QTable table();
@Value.Parameter
IIdent ident();
}
@Value.Immutable
public interface ITableRef extends QTable {
@Value.Parameter
QSchema schema();
@Value.Parameter
IIdent ident();
}
@Value.Immutable
public interface ISchemaRef extends QSchema {
@Value.Parameter
IIdent ident();
}
public enum ICompOp implements Q { EQ, NE, GT, GE, LT, LE }
@Value.Immutable
public interface IComp<T> extends QCondition {
@Value.Parameter
QField<T> lhs();
@Value.Parameter
ICompOp op();
@Value.Parameter
QField<T> rhs();
}
@Value.Immutable
public interface IAnd extends QCondition {
@Value.Parameter
QCondition lhs();
@Value.Parameter
QCondition rhs();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment