Skúšobne som si vytvoril CLR procesor pre farebný výpis na konzole. Syntax sa ale v blízkej budúcnosti pravdepodobne môže zmeniť.
import java.util.List; import java.util.ArrayList; import java.util.Arrays; enum Ansi { RESET("\u001B[0m"), RED("\u001B[31m"), GREEN("\u001B[32m"), YELLOW("\u001B[33m"), BLUE("\u001B[34m"), WHITE("\u001B[37m"), DEFAULT("\u001B[39m"); private final String code; Ansi(String code) { this.code = code; } public String c() { return code; } public static boolean contains(String val) { return Arrays.stream(Ansi.values()).anyMatch(n -> n.name().equalsIgnoreCase(val)); } } void main() { System.out.println(Ansi.RED); String name = "John Doe"; System.out.println(STR."\{Ansi.BLUE.c()}an old falcon \{Ansi.RESET.c()}"); System.out.println(CLR."RED Hello \{name}!"); System.out.println(CLR."GREEN Hi \{name}!"); System.out.println(CLR."YELLOW Halo \{name}!"); System.out.println(CLR."BLUE Ahoj \{name}!"); System.out.println(CLR."GREEN Ahoj \{name}!"); System.out.println(CLR."BLUE Ahoj ako sa mas \{name}?"); System.out.println(CLR."BLUEs ? 21 d"); System.out.println(CLR.""); System.out.println(CLR." "); } StringTemplate.Processor<String, RuntimeException> CLR = temp -> { List<String> fragments = new ArrayList<>(temp.fragments()); String first = fragments.getFirst(); String[] els = first.split(" ", 2); if (els.length != 2) { return StringTemplate.interpolate(temp.fragments(), temp.values()); } Ansi val = Ansi.DEFAULT; String col = els[0]; String msg = els[1]; if (!Ansi.contains(col)) { return StringTemplate.interpolate(temp.fragments(), temp.values()); } else { val = Ansi.valueOf(col); String res = switch (val) { // case null -> Ansi.DEFAULT.c(); case Ansi.RED -> Ansi.RED.c(); case Ansi.GREEN -> Ansi.GREEN.c(); case Ansi.YELLOW -> Ansi.YELLOW.c(); case Ansi.BLUE -> Ansi.BLUE.c(); default -> Ansi.DEFAULT.c(); }; fragments.removeFirst(); fragments.addFirst(res + msg); String last = fragments.removeLast(); fragments.addLast(last + Ansi.RESET.c()); return StringTemplate.interpolate(fragments, temp.values()); } };
To je neobratně řečeno. Jejich argument je, že když by zavedli jen běžnou interpolaci, tak by se to těžko ošetřovalo. Proto umožňili tvorbu vlastních procesorů, do kterých si vývojář může napsat jakoukoli kontrolu, escapování atd. a tedy ošetřit konkrétní nasazení třeba pro sestavení SQL query apod.
O tomto mluvi Ink:
cursor.execute("insert into some_table (id, created_at, last_name) values (%s, %s, %s);", (10, datetime.date(2020, 11, 18), "O'Reilly"))
Dle meho si jen nerozumite. Ten samotný dotaz bez dat si naopak umim predstavit, ze nejaka knihovna "poslepuje" ze stringu, napr. interpoluje nazev tabulky atd.
23. 3. 2024, 13:12 editováno autorem komentáře
Len pre uplnost by som doplnil, ze dalsim pristupom (okrem vseobecne znameho ORM, JPA/hibernate) je aj jooq ci querydsl:
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
.from(AUTHOR)
.join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
.where(BOOK.LANGUAGE.eq("DE"))
.and(BOOK.PUBLISHED.gt(date("2008-01-01")))
.groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
.having(count().gt(5))
.orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
.limit(2)
.offset(1)
Je to typesafe na urovni aplikacneho kodu a nasledne sa clovek spolieha na kvalitu kniznice, ktora psoklada parametricku query pre jdbc, alebo R2DBC driver pre db.
JEP má príklad pre Query Builder.
PreparedStatement ps = DB."SELECT * FROM Person p WHERE p.last_name = \{name}"; ResultSet rs = ps.executeQuery();
Je to riešené tak šalamúnsky. V tom DB procesore to hodia do metódy prepareStatement
. Nerobia vlastnú kontrolu, len ide o sprehľadnenie a zjednodušenie syntaxe.
Tá kontrola má stovky riadkov kódu, pričom sú odlišnosti pre MySQL a pre Postgres. Takže určite žiadna vlastná kontrola na strane klienta.
23. 3. 2024, 11:00 editováno autorem komentáře
Řešením je vlastní procesor, který bezpečně sestaví objekt `PreparedStatement`. Elegantní řešení je naznačeno tady:
https://openjdk.org/jeps/459#Safely-composing-and-executing-database-queries
26. 3. 2024, 15:15 editováno autorem komentáře
Ono by to nebola Java kebyže nepríde s podstatne komplexnejším riešením. String Templates umožňujú vytvoriť svoje vlastné string procesory.
Zas taková zvláštnost to není, třeba JavaScript to umožňuje také.