Все потоки
Поиск
Написать публикацию
Обновить

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

Hola si quieres pueda darte el codigo si lo ncesitas ?

"Здравствуйте, если хотите, я могу дать вам код, если он вам нужен?"

Идея может и интересная академически, но всё ещё непонятно, зачем оно нужно, например, в продакшене? Чтобы увеличить время отработки запроса за счёт парсинга SQL и построения запроса? Чтобы усложнить себе работу за счёт изобретения сферических велосипедов в вакууме? В данном конкретном сценарии запросы простые, и вполне можно обойтись передачей условий как параметров и на стороне backend билдить из них SQL запрос, либо вообще использовать ORM (при желании). Для сколько нибудь сложных запросов придется сюда затащить аналог целого движка SQL и ещё строго проверять, что в этом подзапросе не запросят что-нибудь лишнего из других таблиц, что позволит например методом наблюдения (прошло условие или нет) узнать структуру БД или что-то о данных в этой самой базе. В общем, не вижу практических примеров того, где это реально могло бы помочь и при этом показать себя лучше, чем взять банально тот же GraphQL.

«Просто, элегантно и почти без лишнего кода» - ну такое себе. Себя не похвалишь, никто не похвалит. Это имеется в виду две этих функции - processSqlValue и processSqlExpr? Сама по себе задача то простая. Это даже не полноценный sqlParser/sqlBuilder. Простенький where/between/and/or реализуется.

«Реализовать валидатор SQL-условий WHERE на Go довольно просто — почти тривиально» - как бы и так очевидно. Любой джун конкретно с указанной в статье задачей справится. Если копнуть глубже, вроде условий IN, подстроки или select с join - чем более функционально, тем более сложно будет, придется также учитывать, как обрабатывают SQL конкретные субд/движки.

Ну то есть если кому - то действительно нужно написать много апи, где используется простейший where/and/or, то вместо кучи однообразных апи с преобразованием в Sql через dbx можно использовать такое решение. Или использовать кодогенерацию. Но на практике чаще сразу используют graphql - и более функционален и полно готовых надстроек для контроля доступа

Есть же sqlc который генерит репозиторий на основе запроса SQL , вот он экономит время

Начнем с того, что он не умеет строить чистые запросы для фильтров в where запросе

Возможно и может, там есть sqlc.arg

А если нет, сильно экономит время во всём остальном

А как graphql помогает решать подобную задачу с произвольными фильтрами? Насколько помню в стандарте не было ничего об универсальном языке запросов.

  1. Есть squirrel, который отлично подходит для таких задач.

  2. У меня есть личная аллергия на формирование SQL запроса через принты.

  3. Только мне в обработке строк чудится заготовка под инъекции?

Допустим, вы ищете велосипед из стали весом от 10 до 20 килограммов.

// GET /api/products?material=steel&weightFrom=10&weightTo=20

$qb = $this->productRepository->createQueryBuilder();

if ($queryParams->get('material')) {
  $qb->andWhere('material', '=', $queryParams->get('material'));
}

if ($queryParams->get('weightFrom')) {
  $qb->andWhere('weight', '>=', $queryParams->get('weightFrom'));
}

if ($queryParams->get('weightTo')) {
  $qb->andWhere('weight', '<=', $queryParams->get('weightTo'));
}

$results = $this->productRepository->findByQuery($qb);

10 строк кода без всяких парсеров.

А это точно Golang?)

P.S Аналогичный код на Go + ORM будет не шибко сложнее:

package main

import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "strconv"
)

type Product struct {
    gorm.Model
    Material string
    Weight   float64
}

func GetProducts(db *gorm.DB) gin.HandlerFunc {
    return func(c *gin.Context)  {
        query := db.Model(&Product{})

        if material := c.Query("material"); material != "" {
            query = query.Where("material = ?", material)
        }

        if weightFrom := c.Query("weightFrom"); weightFrom != "" {
            if wf, err := strconv.ParseFloat(weightFrom, 64); err == nil {
                query = query.Where("weight >= ?", wf)
            }
        }

        if weightTo := c.Query("weightTo"); weightTo != "" {
            if wt, err := strconv.ParseFloat(weightTo, 64); err == nil {
                query = query.Where("weight <= ?", wt)
            }
        }

        var products []Product
        if err := query.Find(&products).Error; err != nil {
            c.JSON(500, gin.H{"error": "Failed to fetch products"})
            return
        }

        c.JSON(200, products)
    }
}

Это просто пример, его можно сделать на любом языке. Можно считать его псевдокодом.

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

Публикации