Как стать автором
Обновить

Комментарии 33

Спасибо за ваш вопрос. С целью упрощения API, в TrueSql нет именованных параметров. TrueSql старается не ставить перед разработчиками проблемы выбора. Даже самого минимального, что позволяет направить когнитивный ресурс на разработку, собственно, бизнес логики.

Понял. Просто с моей точки зрения - позиционные параметры вещь хрупкая и к багам ведущая. Но может у вас другой опыт. Я просто всегда на именованных параметрах сидел и хрупкость чисто умозрительно говорю.

Действительно, именованные параметры более устойчивы к изменениям. Это правда. Однако, мы всегда вынуждены выбирать исходя из некоторой суммы. Наименьший синтаксис и поддержка IDE из коробки(без каких либо сторонних плагинов) были важными метриками при разработке TrueSql - обычные вопросики (? - jdbc стандарт) они понимают лучше. Также в синтаксисе PG есть : и ::, значит такие синтаксические конструкцию пользователю пришлось бы экранировать.

Напишите запрос с десятком параметров и поймете, что он становится практически не поддерживаемым. Библиотека, которая декларирует всяческие удобства для пользователя, должна вопрос с именованными параметрами первым делом решать.

Посмотрел чисто из любопытства. Возник единственный вопрос - опять же из любопытства.

Вы рассматриваете 5 различающихся по возвращаемому набору методов. Но все они получают ОДИН набор данных. В то же время некоторые СУБД вполне могут возвращать и несколько наборов, если в качестве выполняемого запроса используется обращение к хранимому объекту. Например, в MySQL хранимая процедура может вывалить в выходной поток несколько, а в теории в принципе сколько угодно, наборов данных. В том числе каждый из наборов вполне может иметь оригинальную, отличающуюся от других, структуру.

Может ли обрабатываться такой случай? Ведь в таком случае просто невозможно указать какой-то определённый результирующий класс..

Добрый день! Если кратко ответить на ваш вопрос, то ДА. Но есть нюансы, связанные с тем что время жизни курсоров - connection level, плюс не будет доступно проверок на этапе компиляции так как в JDBC метаданные курсоров untyped. Если вам нужен конкретный пример под вашу задачу, то вот контакты tg: @overln2, @aka_naked_gun

Вот признаться, совсем не понял, каким боком тут курсор. Он вообще тут вторичный исполнительный механизм.

Совсем по-обывательски ежели, то курсор - это такая штука, которую мы цепляем за набор записей, она в момент присоединения формирует структуру, которая соответствует структуре набора, и потом она ползёт по набору, получая оттуда записи, раскладывая их по полям структуры и отдавая это нам. То есть в момент, когда курсор находится где-то посередине полученного набора данных, мы не можем внести изменения в структуру, которая будет принимать записи из набора. То есть курсор - он не connection-level, он rowset-level, который в свою очередь connection-level. Просто это от нас прячут.

А я как раз говорю о случае, когда один результирующий набор, полученный нами, состоит не из записей, а из наборов с записями. То есть нужен какой-то над-метод, который за каждый отдельный набор записей будет цеплять свой курсор. Ну или один и тот же, но после того, как тот отфетчил предыдущий набор, с соотв. переинициализацией приёмной структуры. Особенно с учётом того, что подобные коллекции наборов записей на стороне SQL-сервера обычно forward-only.

Нет, даже обычный одиночный набор записей, полученный от простого запроса, на самом деле имеет такую же поли-структуру. Просто дефолтно ожидается единственный набор в коллекции, и курсор сразу цепляется за самый первый набор. Как я уже сказал, от нас это прячут.

Как раз ниже у вас в комментарии есть такие слова:

Драйвер привозит ResultSet, который является, структурно, плоской таблицей.

Так вот это как раз не обязательно. Драйвер запросто может привезти пачку таких плоских таблиц, различных по структуре.

Думаю в наших рассуждениях нет противоречий. Комментарий про плоскую структуру я дал в контексте одного выходного result set. Позже пришлем пример двух result set для mysql.

Используйте его [fetchNone], когда вам не нужны выходные строки, например удалим клиента […]

Удаление в PostgreSQL, например, возвращает удаленную запись или ошибку, если при попытке удаления были нарушены констрейнты. Как узнать, успех, или неудача нас постигла? Ловить exception, брошенный из ds.q? Какой именно?

Мы рекомендуем не писать DTO руками, просто добавьте .g

Это экспоненциально повышает плотность WTF для всех, кто этот код будет читать.

Ну и, наконец, самый интересный вопрос: не натолкнемся ли мы на проблему N+1, печально известную по миру рельсов? Что вернется, если я получаю список записей из джойна через fetchList, из запроса со звёздочкой в селекте? Как глубоко пойдёт маппер?

Приветствую! Для работы с исключениями есть соответствующий API. Наличие/отсутствие в БД констрейнта с нужным именем также проверяется на этапе компиляции. Если вам нужно вернуть поля из удаленной строки, то воспользуйтесь .asGeneratedKeys() в TrueSql или returning в PG и, соответствующим fetch (уже не fetchNone). Если нужно количество "затронутых" строк, в TrueSql есть .withUpdateCount. Подробное описание этого функционала будет дано в следующих статьях.

По поводу плотности WTF мы вас не поняли, вы можете смотреть на выходные колонки в запросе или сгенерированные DTO. Также, эти сгенерированные DTO автоматически появятся и в open API (см. комментарий выше).

В TrueSql нет проблемы N+1, аналогичной ORM-библиотекам, TrueSql вообще не ORM-библиотека. TrueSql исполняет запрос на стороне базы данных. Драйвер привозит ResultSet, который является, структурно, плоской таблицей. Из неё собирается одна/несколько DTO. Собираются они через дополнительный group-by на Java стороне в случае, если в dto появляются не только скаляры, но и списки.

Действительно, fetchStream является наиболее общим интерфейсом, но дальше начинаются нюансы Java и ее stdlib.

  1. FetchStream ленивый и держит внутри себя ResultSet и Connection, а в Java нет деструкторов, поэтому fetchStream можно использовать только через try-with-resource, иначе будут утечки

  2. На Stream нет многих utility методов, которые есть, например, в Kotlin. Соответственно, разработчикам будет просто не удобно каждый раз писать один и тот же код: v = stream.findFirst(); if( v,isEmpty) throw ... и так далее

Если в джаве нет материализации стримов, то стоит её, наконец, изобрести.

А как материализовать бесконечный стрим?

А sql умеет возвращать беконечные наборы?

Ну сущность StreamThatCannotBeInfinite — выглядит крайне странно, я затрудняюсь назвать хоть одну команду разработки языка, которая бы согласилась добавить такое в корку.

Кроме того, sql умеет возвращать очень большие объёмы данных, для которых был придуман метод fetchStream и если разработчику возвращать всегда именно стрим, то разработчик начнет везде писать result.materialize(), что приведет к отыквенью в самый неожиданный момент и (это же джава) повалит весь сервис.

void main()
{
    import std.array;
    import std.range : repeat;
    import std.stdio: write, writeln, writef, writefln;
    
    auto a = 42.repeat;
    writeln(a);
}

Такой код написать сложно даже джуну. А вот такой:

void log(Range range) => writeln(range);

уже проще.

А уж если это вообще сторонняя библиотечная функция — так и вообще.

Я же не предлагаю отказаться от стримов. Я всего лишь сообщил, что полагаться на интеллект и внимательность всех пользователей библиотеки — путь в никуда. Особенно, если неверная реализация через materialize выстрелит через год в продакшене.

D куда более лаконичный язык:

import std;
void main() {
    42.repeat.writeln;
}

Нет абсолютно никакой разницы между fetchList и fetchStream().toArray().

fetchStream можно использовать только через try-with-resource

При желании это всё решаемо простым flatMap()-ом.

Stream.of(fetchStream()).flatMap(Function.identity())

Почему в JS нельзя оставить один setTimeout для имитации асинхронности, а пользователь потом сам разберется, как ему определить все эти async и await как промисы?

Читаю не первую статью о ваше библиотеке. Смотрели ли вы в сторону JOOQ https://www.jooq.org/? Ваше решение реализует такой же принцип работы с базой, но при этом в JOOQ очень хорошо реализована типобезопасность параметров запросов, да и при сборке запроса также осуществляется его валидация на этапе компиляции. Чем ваше решение лучше?

Добрый день! Вы видимо считаете что JOOQ хорошая технология, однако подумайте о том что JOOQ существует более 16 лет и при этом имеет <<1% market-share. TrueSql не стоит денег. Ваш вопрос про валидацию: в TrueSql всё это есть и даже лучше, следите за будущими публикациями. Тезисно ответил чем TrueSql лучше JOOQ в нашем тг-канале: https://t.me/TrueSql.

Прочитал ваши тезисы, жаль, что вы не изложили их здесь. Пока из ответов явных преимуществ не увидел. Как реализуется валидация средствами БД? Отправкой некорректного запроса и получением ошибки?

<<1% market share

https://github.com/jOOQ/jOOQ

6300 звёзд, 1200 форков

Для сравнения у спринга 57500 звёзд, а у trueSql - 14.

У кого нет своего мозга, тот думает чужим.

Это вы что имеете ввиду? Поясните, пожалуйста.

Ну раз вы так просите, то подумаю за вас: вы меряетесь звёздами, форками и маркет шарами, надеясь, что все те миллионы мух провели технический анализ и выбрали лучшее решение из возможных, а на самом деле большая часть из них не то что технического, а вообще никакого анализа не сделала и порой даже не пробовала в деле.

Поэтому имеет смысл публиковать бенчмарки и прочие сравнения с теми, комго уже выбрали миллионы мух, если ты, по сути, повторяешь их решение с незаметными глазу отличиями.

Было бы в тексте: «вот пример на JOOQ, вот на TrueSql, мы в триста раз быстрее, а JOOQ вообще возвращает таймаут и валится в корку».

Пока сравнений нет, у библиотеки с 1200 форков есть, как минимум, 1200 пользователей, которые погоняли её, понаступали на грабли, понаприсылали пуллреквестов (шучу, конечно, понаоставляли гневных ишью), и так далее.

А библиотека с 14 звездами, скорее всего, тестировалась только в тепличных условиях.

Вы меня извините, но я отвечал на конкретный тезис про "<<1% market share". Что, очевидно, не правда - и количество звёзд в репозитории здесь отличный показатель.

Ещё меня несколько напрягает токсичность евангелистов этой вашей чудо-библиотеки: вместо того, чтобы ответить по существу, они зачем-то сравнивают незнакомых людей с мухами и делают необоснованные выводы о чужих умственных способностях. Не надо так!

Сначала люди думают, что звёзды сложно накрутить, а потом обижаются на сравнения с мухами. Если вы не готовы воспринимать чужую аналитику - думайте своей головой.

Люди не думают, что звёзды сложно накрутить. Звёзды накрутить легко, и это всем очевидно.

Люди думают, что уважающие себя авторы библиотеки не станут таким заниматься по той простой причине, что им это не нужно.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации