{"id":482051,"date":"2026-06-02T09:21:07","date_gmt":"2026-06-02T09:21:07","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=482051"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=482051","title":{"rendered":"\u042f \u043b\u044e\u0431\u043b\u044e SQL, \u043d\u043e \u0443\u0441\u0442\u0430\u043b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c WHERE \u0447\u0435\u0440\u0435\u0437 fmt.Sprintf: \u0437\u0430\u0447\u0435\u043c \u044f \u0441\u0434\u0435\u043b\u0430\u043b qrafter"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u0439 SQL.<\/p>\n<p>\u041d\u0435 \u00ab\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c\u00bb, \u0430\u00a0\u043f\u0440\u0430\u0432\u0434\u0430 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u0412\u00a0\u0445\u043e\u0440\u043e\u0448\u0435\u043c SQL\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e\u00a0\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u00a0\u0434\u0430\u043d\u043d\u044b\u043c\u0438: \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0451\u043c, \u043a\u0430\u043a\u00a0\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c, \u0433\u0434\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c, \u0447\u0442\u043e\u00a0\u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u043c \u0438 \u0432\u00a0\u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0442\u0434\u0430\u0451\u043c \u043d\u0430\u0440\u0443\u0436\u0443. \u0418 \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f Go \u0437\u0430\u00a0\u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e: \u043a\u043e\u0434 \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u044f\u043c\u043e\u0439, \u044f\u0432\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437\u00a0\u043b\u0438\u0448\u043d\u0438\u0445 \u0446\u0435\u0440\u0435\u043c\u043e\u043d\u0438\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u043b\u0433\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u0431\u0430\u0437\u043e\u0439 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">rows, err := db.QueryContext(ctx, `    SELECT id, user_name, age\u00a0 \u00a0 FROM users\u00a0 \u00a0 WHERE status = $1\u00a0 \u00a0 ORDER BY id\u00a0 \u00a0 LIMIT $2`, status, limit)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412\u0441\u0451 \u0447\u0435\u0441\u0442\u043d\u043e. SQL \u0432\u0438\u0434\u0435\u043d. \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438. \u041d\u043e\u00a0\u043f\u043e\u0442\u043e\u043c \u0432\u00a0\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b. \u041f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u0444\u0438\u043b\u044c\u0442\u0440\u044b. \u041f\u043e\u0442\u043e\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0438\u0437\u00a0API. \u041f\u043e\u0442\u043e\u043c \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044f. \u041f\u043e\u0442\u043e\u043c \u0442\u0430\u043a\u043e\u0439\u00a0\u0436\u0435 <code>WHERE<\/code> \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f <code>COUNT(*)<\/code> \u0434\u043b\u044f\u00a0\u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<p>\u041f\u043e\u0442\u043e\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u00a0SQLite, \u0445\u043e\u0442\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d \u043d\u0430\u00a0PostgreSQL. \u0418 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u00ab\u043f\u0440\u043e\u0441\u0442\u043e \u0441\u044b\u0440\u043e\u0439 SQL\u00bb, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 query builder:<\/p>\n<pre><code class=\"go\">query := `\u00a0 \u00a0 SELECT id, user_name, age\u00a0 \u00a0 FROM users\u00a0 \u00a0 WHERE 1 = 1`args := make([]any, 0)if filter.Status != \"\" {\u00a0 \u00a0 args = append(args, filter.Status)\u00a0 \u00a0 query += fmt.Sprintf(\" AND status = $%d\", len(args))}if filter.MinAge != nil {\u00a0 \u00a0 args = append(args, *filter.MinAge)\u00a0 \u00a0 query += fmt.Sprintf(\" AND age &gt;= $%d\", len(args))}if filter.CreatedAfter != nil {\u00a0 \u00a0 args = append(args, *filter.CreatedAfter)\u00a0 \u00a0 query += fmt.Sprintf(\" AND created_at &gt;= $%d\", len(args))}query += \" ORDER BY id LIMIT 100\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u043d\u0435 \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0430. \u0422\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u042f \u0441\u0430\u043c \u043f\u0438\u0441\u0430\u043b \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437.<\/p>\n<p>\u041d\u043e \u0441 \u043d\u0438\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043e\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0439 \u0440\u0443\u0447\u043d\u043e\u0439 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 SQL-\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u043c, \u043d\u043e\u043c\u0435\u0440\u043e\u043c placeholder\u2019\u0430 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0432 <code>[]any<\/code>.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c \u043d\u043e\u043c\u0435\u0440\u0430. \u041f\u043e\u043c\u0435\u043d\u044f\u043b \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c <code>args<\/code>.<\/p>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0444\u0438\u043b\u044c\u0442\u0440 \u0432 <code>COUNT(*)<\/code> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c, \u0447\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446 \u043e\u0431\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u2014 \u0443\u0434\u0430\u0447\u0438 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 <code>\"user_name\"<\/code> \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443.<\/p>\n<p>\u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043c\u0435\u043d\u044f \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0435 SQL. \u041c\u0435\u043d\u044f \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0430\u0435\u0442 \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0438\u044f \u0432\u043e\u043a\u0440\u0443\u0433 SQL.<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f <strong>qrafter<\/strong>.<\/p>\n<hr\/>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 qrafter<\/h2>\n<p><a href=\"https:\/\/github.com\/SennovE\/qrafter\" rel=\"noopener noreferrer nofollow\"><strong>qrafter<\/strong><\/a><a href=\"https:\/\/github.com\/SennovE\/qrafter\" rel=\"noopener noreferrer nofollow\"> <\/a>\u2014 \u044d\u0442\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f Go.<\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f:<\/p>\n<blockquote>\n<p>SQL \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u044f\u0432\u043d\u044b\u043c, \u043d\u043e \u0438\u043c\u0435\u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a, placeholder\u2019\u044b \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439.<\/p>\n<\/blockquote>\n<p>Qrafter \u0441\u0442\u0440\u043e\u0438\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL \u0438\u0437 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 Go \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0438 \u043e\u0442\u0434\u0430\u0451\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 <code>database\/sql<\/code>, <code>sqlx<\/code> \u0438 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"go\">package mainimport (    \"fmt\"    q \"github.com\/SennovE\/qrafter\"    \"github.com\/SennovE\/qrafter\/dialect\")type User struct {    q.Table `table:\"users\"`    ID       q.Column[int] `db:\"id\"`    UserName q.Column[string]    Age      q.Column[int]}func main() {    users := q.MustNewTable[User]()    sql, args, err := q.Select(users.ID, users.UserName).        Where(            users.Age.Ge(18),            users.UserName.Eq(\"Alice\"),        ).        OrderBy(users.ID.Asc()).        Limit(10).        Render(dialect.PostgreSQL{})    if err != nil {        panic(err)    }    fmt.Println(sql)    fmt.Println(args)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:<\/p>\n<pre><code class=\"sql\">SELECT \"users\".\"id\", \"users\".\"user_name\"FROM \"users\"WHERE \"users\".\"age\" &gt;= $1 AND \"users\".\"user_name\" = $2ORDER BY \"users\".\"id\" ASCLIMIT 10<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<pre><code class=\"go\">[]any{18, \"Alice\"}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u0434 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a SQL: <code>SELECT<\/code>, <code>WHERE<\/code>, <code>ORDER BY<\/code>, <code>LIMIT<\/code>.<\/p>\n<p>\u041d\u043e \u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u0438\u0448\u0443 <code>\"user_name\"<\/code> \u0440\u0443\u043a\u0430\u043c\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0435\u0441\u0442\u0435. \u041d\u0435 \u0441\u0447\u0438\u0442\u0430\u044e <code>$1<\/code>, <code>$2<\/code>, <code>$3<\/code>. \u041d\u0435 \u0434\u0443\u043c\u0430\u044e, \u043a\u0430\u043a\u0438\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0433\u043e SQL-\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430.<\/p>\n<h2>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 ORM<\/h2>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441: \u00ab\u0417\u0430\u0447\u0435\u043c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c ORM?\u00bb<\/p>\n<p>ORM \u2014 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u0441\u0432\u044f\u0437\u0438, \u0436\u0430\u0434\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 CRUD \u0432\u043e\u043a\u0440\u0443\u0433 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p>\u041d\u043e qrafter \u0440\u0435\u0448\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<p>\u042f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u044f\u0442\u0430\u0442\u044c SQL \u0437\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e. \u041d\u0435 \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441\u0432\u044f\u0437\u0435\u0439. \u041d\u0435 \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0440\u0435\u0448\u0430\u043b\u0430, \u043a\u043e\u0433\u0434\u0430 \u0438 \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c  <\/p>\n<p>\u041c\u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u0431\u044b\u043b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u043d\u0438\u0436\u0435: \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Go \u0432 SQL string \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u044f \u0441\u0430\u043c \u0440\u0435\u0448\u0430\u044e, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441: <code>database\/sql<\/code>, <code>sqlx<\/code>, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f, \u0441\u0432\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043c\u0438\u0434\u043b\u0432\u0430\u0440\u044b, \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p><code>database\/sql<\/code> \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Go \u0443\u0436\u0435 \u0434\u0430\u0451\u0442 \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a SQL-like \u0431\u0430\u0437\u0430\u043c, \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u043f\u0443\u043b\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. qrafter \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439, \u0430 \u0432\u0441\u0442\u0430\u0451\u0442 \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c \u043a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<h2>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 sqlc<\/h2>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u0437 sql-\u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>sqlc<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 Go-\u043a\u043e\u0434 \u0438\u0437 SQL. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: SQL \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0438\u0441\u0442\u0438\u043d\u044b, \u0430 Go API \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u0430\u0445, <code>sqlc<\/code> \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c.<\/p>\n<p>\u041d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437 API-\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442:<\/p>\n<p><code>GET \/users?status=active&amp;min_age=18&amp;created_after=2026-01-01<\/code><\/p>\n<p>\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0430\u0441\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 Go-\u043a\u043e\u0434\u0435:<\/p>\n<pre><code class=\"go\">query := q.Select(users.ID, users.UserName, users.Age)if filter.Status != \"\" {    query = query.Where(users.Status.Eq(filter.Status))}if filter.MinAge != nil {    query = query.Where(users.Age.Ge(*filter.MinAge))}if filter.CreatedAfter != nil {    query = query.Where(users.CreatedAt.Ge(*filter.CreatedAfter))}sql, args, err := query.    OrderBy(users.ID.Asc()).    Limit(100).    Render(dialect.PostgreSQL{})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0422\u043e \u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 SQL-\u0441\u0442\u0440\u043e\u043a\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"go\">sql := `    SELECT id, user_name, age    FROM users`where := make([]string, 0)args := make([]any, 0)if filter.Status != \"\" {    args = append(args, filter.Status)    where = append(where, fmt.Sprintf(\"status = $%d\", len(args)))}if filter.MinAge != nil {    args = append(args, *filter.MinAge)    where = append(where, fmt.Sprintf(\"age &gt;= $%d\", len(args)))}if filter.CreatedAfter != nil {    args = append(args, *filter.CreatedAfter)    where = append(where, fmt.Sprintf(\"created_at &gt;= $%d\", len(args)))}if len(where) &gt; 0 {    sql += \" WHERE \" + strings.Join(where, \" AND \")}sql += \" ORDER BY id ASC LIMIT 100\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u043d\u0435 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 SQL-\u0444\u0430\u0439\u043b \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041c\u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0439, \u043d\u043e \u043d\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u044e \u0441\u0442\u0440\u043e\u043a. \u0412\u043e\u0442 \u044d\u0442\u0430 \u0437\u043e\u043d\u0430 \u0438 \u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442\u043e qrafter.<\/p>\n<h2>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 Squirrel<\/h2>\n<p>\u0415\u0441\u0442\u044c \u0438 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Squirrel \u2014 SQL-\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f Go. \u041e\u043d \u0445\u043e\u0440\u043e\u0448\u043e \u0443\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043a\u043b\u0435\u0439\u043a\u0443 \u0441\u0442\u0440\u043e\u043a:<\/p>\n<pre><code class=\"go\">sq.Select(\"id\", \"user_name\").\u00a0 \u00a0 From(\"users\").\u00a0 \u00a0 Where(sq.Eq{\"status\": \"active\"})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c <code>strings.Builder<\/code>, <code>fmt.Sprintf<\/code> \u0438 \u0440\u0443\u0447\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <code>AND<\/code>.<\/p>\n<p>\u041d\u043e \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0434\u0440\u0443\u0433\u043e\u0433\u043e. \u0412 Squirrel \u0438\u043c\u0435\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0447\u0430\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u0410 \u044f \u0445\u043e\u0442\u0435\u043b \u0432\u0438\u0434\u0435\u0442\u044c \u044f\u0432\u043d\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"go\">q.Select(users.ID, users.UserName).\u00a0 \u00a0 Where(users.Status.Eq(\"active\"))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u043d\u0435\u00a0\u0434\u0435\u043b\u0430\u0435\u0442 qrafter \u00ab\u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u0434\u0430\u00bb. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u044b\u0431\u043e\u0440: \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0437\u0430\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u00a0\u043a\u043e\u0434\u0443 \u0445\u043e\u0434\u044f\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u044b \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432.<\/p>\n<h2>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 <\/h2>\n<p>\u0412 qrafter \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u2014 \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u0430\u044f Go-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code class=\"go\">type UserTable struct {    q.Table `table:\"users\"`    ID        q.Column[int64]  `db:\"id\"`    UserName  q.Column[string] `db:\"user_name\"`    Age       q.Column[int]    Status    q.Column[string]    CreatedAt q.Column[time.Time] `db:\"created_at\"`    DeletedAt q.Column[*time.Time] `db:\"deleted_at\"`}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0442\u043e\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c SQL-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445:<\/p>\n<pre><code class=\"go\">users := q.MustNewTable[UserTable]()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e <code>users.Age<\/code>, <code>users.Status<\/code>, <code>users.CreatedAt<\/code> \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0438. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"go\">users.Age.Ge(18)users.Status.Eq(\"active\")users.DeletedAt.IsNull()users.CreatedAt.Ge(since)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>qrafter \u0441\u0430\u043c \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0441 \u0442\u0438\u043f\u043e\u043c <code>Column<\/code> \u0441 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a: \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0433 <code>db<\/code> \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 snake_case \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044f.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 1: \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u044b\u0445 placeholder\u2019\u043e\u0432<\/h2>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0444\u0438\u043b\u044c\u0442\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">type UserFilter struct {    Status         string    MinAge         *int    CreatedAfter   *time.Time    IncludeDeleted bool}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 raw SQL \u044f \u0431\u044b \u0440\u0430\u043d\u044c\u0448\u0435 \u0434\u0435\u0440\u0436\u0430\u043b \u0440\u044f\u0434\u043e\u043c <code>query<\/code>, <code>args<\/code> \u0438 <code>len(args)<\/code>. \u0421 qrafter \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">func listUsers(ctx context.Context, db *sql.DB, filter UserFilter) error {    users := q.MustNewTable[UserTable]()    query := q.Select(users.ID, users.UserName, users.Age, users.Status, users.CreatedAt)    if filter.Status != \"\" {        query = query.Where(users.Status.Eq(filter.Status))    }    if filter.MinAge != nil {        query = query.Where(users.Age.Ge(*filter.MinAge))    }    if filter.CreatedAfter != nil {        query = query.Where(users.CreatedAt.Ge(*filter.CreatedAfter))    }    if !filter.IncludeDeleted {        query = query.Where(users.DeletedAt.IsNull())    }    sqlText, args, err := query.        OrderBy(users.ID.Asc()).        Limit(100).        Render(dialect.PostgreSQL{})    if err != nil {        return err    }    rows, err := db.QueryContext(ctx, sqlText, args...)    if err != nil {        return err    }    defer rows.Close()    \/\/ scan rows...    return rows.Err()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0422\u043e \u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 SQL-\u0441\u0442\u0440\u043e\u043a\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"go\">func listUsers(ctx context.Context, db *sql.DB, filter UserFilter) error {    query := `        SELECT id, user_name, age, status, created_at        FROM users    `    where := make([]string, 0)    args := make([]any, 0)    if filter.Status != \"\" {        args = append(args, filter.Status)        where = append(where, fmt.Sprintf(\"status = $%d\", len(args)))    }    if filter.MinAge != nil {        args = append(args, *filter.MinAge)        where = append(where, fmt.Sprintf(\"age &gt;= $%d\", len(args)))    }    if filter.CreatedAfter != nil {        args = append(args, *filter.CreatedAfter)        where = append(where, fmt.Sprintf(\"created_at &gt;= $%d\", len(args)))    }    if !filter.IncludeDeleted {        where = append(where, \"deleted_at IS NULL\")    }    if len(where) &gt; 0 {        query += \" WHERE \" + strings.Join(where, \" AND \")    }    query += \" ORDER BY id ASC LIMIT 100\"    rows, err := db.QueryContext(ctx, query, args...)    if err != nil {        return err    }    defer rows.Close()    \/\/ scan rows...    return rows.Err()}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u0430\u0436\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u043a\u043e\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435. \u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f. \u0412\u0430\u0436\u043d\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435: \u0438\u0437 \u043a\u043e\u0434\u0430 \u0438\u0441\u0447\u0435\u0437\u043b\u0430 \u0445\u0440\u0443\u043f\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c.<\/p>\n<p>\u0411\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442:<\/p>\n<pre><code class=\"go\">fmt.Sprintf(\"$%d\", len(args))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0411\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e:<\/p>\n<pre><code class=\"go\">args = append(args, value)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0411\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0432 \u0434\u0435\u0441\u044f\u0442\u0438 \u043c\u0435\u0441\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0441\u043a\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>deleted_at<\/code> \u043d\u0430 <code>removed_at<\/code>.<\/p>\n<p>\u0412\u0441\u0435 \u0435\u0449\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f, \u043d\u043e \u0437\u0430 placeholder\u2019\u0430\u043c\u0438 \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 2: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 count<\/h2>\n<p>\u041f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044f \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u0442 \u0434\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"sql\">SELECT id, user_name, ageFROM usersWHERE ...ORDER BY idLIMIT 100;SELECT COUNT(id)FROM usersWHERE ...;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0432 <code>COUNT<\/code>. \u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <code>WHERE<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438, \u0432\u044b \u043b\u0438\u0431\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043b\u0438\u0431\u043e \u043f\u0438\u0448\u0435\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 SQL-\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b <code>[]any<\/code>. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 query builder, \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0435\u0437 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u043e\u0442 \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430.<\/p>\n<p>\u0412 qrafter \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"go\">func applyUserFilter(    query q.SelectQuery,    users UserTable,    filter UserFilter,) q.SelectQuery {    if filter.Status != \"\" {        query = query.Where(users.Status.Eq(filter.Status))    }    if filter.MinAge != nil {        query = query.Where(users.Age.Ge(*filter.MinAge))    }    if filter.CreatedAfter != nil {        query = query.Where(users.CreatedAt.Ge(*filter.CreatedAfter))    }    if !filter.IncludeDeleted {        query = query.Where(users.DeletedAt.IsNull())    }    return query}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0434\u0430\u043b\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0432 \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"go\">users := q.MustNewTable[UserTable]()listQuery := applyUserFilter(    q.Select(users.ID, users.UserName, users.Age),    users,    filter,).OrderBy(users.ID.Asc()).    Limit(100)countQuery := applyUserFilter(    q.Select(q.Count(users.ID)),    users,    filter,)listSQL, listArgs, err := listQuery.Render(dialect.PostgreSQL{})if err != nil {    return err}countSQL, countArgs, err := countQuery.Render(dialect.PostgreSQL{})if err != nil {    return err}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u043c\u0435\u043d\u044f \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0435\u0439. \u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0431\u044b\u0442\u044c \u043a\u0443\u0441\u043a\u043e\u043c \u0441\u0442\u0440\u043e\u043a\u0438. \u041e\u043d \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e Go-\u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0447\u0438\u0442\u0430\u0442\u044c.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 3: dialect-aware SQL \u0431\u0435\u0437 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u00ab\u043e\u0431\u043c\u0430\u043d\u0443\u0442\u044c\u00bb SQL<\/h2>\n<p>\u0423 SQL-\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u043e\u0432 \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f, \u0438 qrafter \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0438\u0434, \u0447\u0442\u043e \u0438\u0445 \u043d\u0435\u0442.<\/p>\n<p>\u041d\u043e \u0447\u0430\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0439 \u0441\u043a\u0443\u0447\u043d\u0430\u044f \u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f.<\/p>\n<p>PostgreSQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0430\u043a\u0438\u0435 placeholder\u2019\u044b:<\/p>\n<pre><code class=\"sql\">WHERE age &gt;= $1 AND status = $2<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>MySQL \u0438 SQLite \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0442\u0430\u043a\u0438\u0435:<\/p>\n<pre><code class=\"go\">WHERE age &gt;= ? AND status = ?<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0442\u043e\u0436\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443:<\/p>\n<pre><code class=\"sql\">-- PostgreSQL \/ SQLite\"users\".\"id\"-- MySQL`users`.`id`<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>qrafter \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0434\u0438\u043d \u0440\u0430\u0437:<\/p>\n<pre><code class=\"go\">query := q.Select(users.ID, users.UserName).    Where(        users.Age.Ge(18),        users.Status.Eq(\"active\"),    ).    OrderBy(users.ID.Asc()).    Limit(100)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410 \u043f\u043e\u0442\u043e\u043c \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0431\u0430\u0437\u0443:<\/p>\n<pre><code class=\"go\">pgSQL, pgArgs, err := query.Render(dialect.PostgreSQL{})mySQL, myArgs, err := query.Render(dialect.MySQL{})sqliteSQL, sqliteArgs, err := query.Render(dialect.SQLite{})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u0432 qrafter \u0435\u0441\u0442\u044c <code>BaseDialect<\/code>, <code>PostgreSQL<\/code>, <code>MySQL<\/code> \u0438 <code>SQLite<\/code>. \u0414\u0438\u0430\u043b\u0435\u043a\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043a\u0430\u0432\u044b\u0447\u043a\u0438, \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432\u0440\u043e\u0434\u0435 <code>LIMIT\/OFFSET<\/code>, <code>RETURNING<\/code>, <code>DELETE USING<\/code>, <code>JOIN<\/code> \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u044f. \u0415\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0421\u0423\u0411\u0414 \u0438\u043b\u0438 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u0437\u0430\u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SQLite \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 PostgreSQL, \u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u0440\u0435\u043d\u0434\u0435\u0440\u0430, \u0430 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 4: repository layer \u0431\u0435\u0437 \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/h2>\n<p>qrafter \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u043a\u0430\u043a \u0432\u0430\u043c \u043f\u0438\u0441\u0430\u0442\u044c repository layer, \u0433\u0434\u0435 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u043a\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u043a\u0430\u043a\u0438\u043c \u043b\u043e\u0433\u0433\u0435\u0440\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 <code>database\/sql<\/code>:<\/p>\n<pre><code class=\"go\">type UserRepository struct {    db      *sql.DB    dialect dialect.Renderer    users   UserTable}func NewUserRepository(db *sql.DB, d dialect.Renderer) *UserRepository {    return &amp;UserRepository{        db:      db,        dialect: d,        users:   q.MustNewTable[UserTable](),    }}func (r *UserRepository) List(    ctx context.Context,    filter UserFilter,) ([]UserDTO, error) {    query := applyUserFilter(        q.Select(            r.users.ID,            r.users.UserName,            r.users.Age,            r.users.Status,        ),        r.users,        filter,    ).OrderBy(r.users.ID.Asc()).        Limit(100)    sqlText, args, err := query.Render(r.dialect)    if err != nil {        return nil, fmt.Errorf(\"render users query: %w\", err)    }    rows, err := r.db.QueryContext(ctx, sqlText, args...)    if err != nil {        return nil, fmt.Errorf(\"query users: %w\", err)    }    defer rows.Close()    result := make([]UserDTO, 0)    for rows.Next() {        var user UserDTO        if err := rows.Scan(            &amp;user.ID,            &amp;user.UserName,            &amp;user.Age,            &amp;user.Status,        ); err != nil {            return nil, fmt.Errorf(\"scan user: %w\", err)        }        result = append(result, user)    }    if err := rows.Err(); err != nil {        return nil, fmt.Errorf(\"iterate users: %w\", err)    }    return result, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u0418\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"go\">func (r *UserRepository) List(    ctx context.Context,    filter UserFilter,) ([]UserDTO, error) {    \/\/ \u0422\u043e \u0436\u0435 \u0447\u0442\u043e \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u0448\u0435    result := make([]UserDTO, 0)      for rows.Next() {        var user UserDTO        dest, err := q.ScanDest(&amp;user)        if err != nil {log.Fatal(err)}if err := rows.Scan(dest...); err != nil {log.Fatal(err)}        result = append(result, user)    }    if err := rows.Err(); err != nil {        return nil, fmt.Errorf(\"iterate users: %w\", err)    }    return result, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>q.ScanDest(&amp;user)<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u043d\u043e. \u041e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 dest \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0445 Column-\u043f\u043e\u043b\u0435\u0439 \u0432 Go-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043f\u043e\u043b\u0435\u0439 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u043c \u0432 <code>q.Select.<\/code><\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430, \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u0435\u0449\u0451 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Go-\u043a\u043e\u0434. qrafter \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u044c \u0432\u0430\u0448\u0438\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 SQL \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043a\u043b\u0435\u0439\u043a\u0443 SQL \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u0443\u044e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 5: qrafter + sqlx<\/h2>\n<p><code>sqlx<\/code> \u0445\u043e\u0440\u043e\u0448\u043e \u043b\u043e\u0436\u0438\u0442\u0441\u044f \u0440\u044f\u0434\u043e\u043c \u0441 qrafter, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0435\u0448\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443. sqlx \u2014 \u044d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u0435\u0440\u0445 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e <code>database\/sql<\/code>: \u043e\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 struct scanning, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b <code>sql.DB<\/code>, <code>sql.Tx<\/code>, <code>sql.Stmt<\/code>.<\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c:<\/p>\n<p>qrafter \u2192 \u0441\u043e\u0431\u0440\u0430\u0442\u044c SQL \u2192 sqlx \u2192 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c SQL \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u043e\u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"go\">sqlText, args, err := q.Select(    users.ID,    users.UserName,    users.Age,).    Where(users.Status.Eq(\"active\")).    OrderBy(users.ID.Asc()).    Render(dialect.PostgreSQL{})if err != nil {    return err}var result []UserDTOif err := db.SelectContext(ctx, &amp;result, sqlText, args...); err != nil {    return err}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0411\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043e\u0442\u0447\u0451\u0442 \u0441 CTE \u0438 window function<\/h2>\n<p>\u041f\u0440\u043e\u0441\u0442\u044b\u0435 <code>SELECT ... WHERE ... LIMIT ...<\/code> \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0438\u0434\u0435\u044e, \u043d\u043e \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442, \u0437\u0430\u0447\u0435\u043c \u0432\u0441\u0451 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u0434\u0435.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 qrafter \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u044b\u0440\u043e\u0439 SQL.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0435\u0441\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b:<\/p>\n<pre><code class=\"go\">type CustomerTable struct {    q.Table `table:\"customers\"`    ID        q.Column[int64]      `db:\"id\"`    Name      q.Column[string]     `db:\"name\"`    DeletedAt q.Column[*time.Time] `db:\"deleted_at\"`}type OrderTable struct {    q.Table `table:\"orders\"`    ID         q.Column[int64]     `db:\"id\"`    CustomerID q.Column[int64]     `db:\"customer_id\"`    Status     q.Column[string]    `db:\"status\"`    CreatedAt  q.Column[time.Time] `db:\"created_at\"`}type OrderItemTable struct {    q.Table `table:\"order_items\"`    ID        q.Column[int64] `db:\"id\"`    OrderID   q.Column[int64] `db:\"order_id\"`    Quantity  q.Column[int64] `db:\"quantity\"`    UnitPrice q.Column[int64] `db:\"unit_price_cents\"`}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u0441\u0443\u043c\u043c\u0435 \u043f\u043e\u043a\u0443\u043f\u043e\u043a:<\/p>\n<ol>\n<li>\n<p>\u0412\u0437\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043a\u0430\u0437\u044b;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043a\u0430\u0437\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u0442\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0437\u0430\u043a\u0430\u0437\u0430;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0443\u043c\u043c\u0443;<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c rank \u043f\u043e \u0441\u0443\u043c\u043c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0434\u0430\u0442\u044c \u0442\u043e\u043f-20.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 SQL \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0438\u0442\u0441\u044f \u0432 CTE:<\/p>\n<pre><code class=\"sql\">WITH customer_spend AS (    SELECT        orders.customer_id,        COUNT(orders.id) AS orders_count,        MAX(orders.created_at) AS last_order_at,        SUM(order_items.quantity * order_items.unit_price_cents) AS total_spend_cents    FROM orders    JOIN order_items ON orders.id = order_items.order_id    WHERE orders.status = 'paid'      AND orders.created_at &gt;= $1    GROUP BY orders.customer_id)SELECT    customers.id,    customers.name,    customer_spend.orders_count,    customer_spend.last_order_at,    customer_spend.total_spend_cents,    RANK() OVER (ORDER BY customer_spend.total_spend_cents DESC) AS spend_rankFROM customersJOIN customer_spend ON customers.id = customer_spend.customer_idWHERE customers.deleted_at IS NULLORDER BY customer_spend.total_spend_cents DESCLIMIT 20;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 qrafter \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">customers := q.MustNewTable[CustomerTable]()orders := q.MustNewTable[OrderTable]()items := q.MustNewTable[OrderItemTable]()since := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)lineTotal := items.Quantity.Mul(items.UnitPrice)customerSpend := q.Select(    orders.CustomerID,    q.Count(orders.ID).As(\"orders_count\"),    q.Max(orders.CreatedAt).As(\"last_order_at\"),    q.Sum(lineTotal).As(\"total_spend_cents\"),).    Join(items, orders.ID.Eq(items.OrderID)).    Where(        orders.Status.Eq(\"paid\"),        orders.CreatedAt.Ge(since),    ).    GroupBy(orders.CustomerID).    CTE(\"customer_spend\").    WithColumns(        \"customer_id\",        \"orders_count\",        \"last_order_at\",        \"total_spend_cents\",    )spend := customerSpend.Column(\"total_spend_cents\")rank := q.Rank().    Over(q.Window().OrderBy(spend.Desc())).    As(\"spend_rank\")sqlText, args, err := q.Select(    customers.ID,    customers.Name,    customerSpend.Column(\"orders_count\"),    customerSpend.Column(\"last_order_at\"),    spend,    rank,).    Join(customerSpend, customers.ID.Eq(customerSpend.Column(\"customer_id\"))).    Where(customers.DeletedAt.IsNull()).    OrderBy(spend.Desc()).    Limit(20).    Render(dialect.PostgreSQL{})if err != nil {    return err}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u0438\u0433\u0440\u0443\u0448\u0435\u0447\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c CTE, join, aggregate functions, arithmetic expression, <code>GROUP BY<\/code>, window function, \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u043e\u0434 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 SQL, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439, \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0431\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u043f\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c\u0443 Select&#8217;\u0443 \u043f\u043e\u043d\u044f\u0442\u044c \u0442\u0438\u043f\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0438\u0437 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<h2>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e SQL \u0432 Go<\/h2>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, Go \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0445\u043e\u0440\u043e\u0448\u043e \u0434\u0440\u0443\u0436\u0438\u0442 \u0441 \u044f\u0432\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p><code>database\/sql<\/code> \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0442\u044c ORM. \u041e\u043d \u0434\u0430\u0451\u0442 \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043f\u0443\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, <code>QueryContext<\/code>, <code>ExecContext<\/code>, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, <code>Rows<\/code>, <code>Scan<\/code>. \u0412\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u0441\u0430\u043c\u0438. \u042d\u0442\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u043b\u044e\u0441 \u0438 \u043c\u0438\u043d\u0443\u0441.<\/p>\n<p>\u041f\u043b\u044e\u0441: \u043d\u0435\u0442 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u00ab\u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u00bb \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0431\u0430\u0437\u043e\u0439.<\/p>\n<p>\u041c\u0438\u043d\u0443\u0441: \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0440\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0439 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0441\u043b\u043e\u0439 \u0432\u043e\u043a\u0440\u0443\u0433 SQL.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 ORM.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 raw SQL.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 sqlc.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u0430\u0445 \u0447\u0435\u0440\u0435\u0437 <code>embed<\/code>.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0441\u0432\u043e\u0439 helper \u0434\u043b\u044f <code>WHERE<\/code>.<\/p>\n<p>qrafter \u2014 \u044d\u0442\u043e \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u043d\u044f\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u0437\u043a\u0443\u044e \u043d\u0438\u0448\u0443 \u043c\u0435\u0436\u0434\u0443 \u044d\u0442\u0438\u043c\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u0445\u043e\u0447\u0443 \u0432\u0438\u0434\u0435\u0442\u044c SQL<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0445\u043e\u0447\u0443 ORM<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0445\u043e\u0447\u0443 codegen<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0445\u043e\u0447\u0443 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0437\u043c\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u0445\u043e\u0447\u0443 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 SQL + []any \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435<\/p>\n<\/li>\n<\/ul>\n<h2>\u0427\u0442\u043e qrafter \u0434\u0430\u0451\u0442 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435<\/h2>\n<p>\u0414\u043b\u044f \u0441\u0435\u0431\u044f \u044f \u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u0443\u044e \u043f\u043b\u044e\u0441\u044b \u0442\u0430\u043a.<\/p>\n<p><strong>\u041f\u0435\u0440\u0432\u043e\u0435: \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a.<\/strong><\/p>\n<pre><code class=\"go\">users.Status.Eq(\"active\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c:<\/p>\n<pre><code class=\"go\">\"status = $1\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u043f\u0440\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0435 Go-\u043f\u043e\u043b\u044f \u0443 \u0432\u0430\u0441 \u0445\u043e\u0442\u044f \u0431\u044b \u0447\u0430\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u043b\u043e\u0432\u0438\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440.<\/p>\n<p><strong>\u0412\u0442\u043e\u0440\u043e\u0435: \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/strong><\/p>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0435 Go-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430, \u0430 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 SQL-\u0441\u0442\u0440\u043e\u043a\u0443. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0430\u043c\u0438, \u043d\u0430\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0431 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438.<\/p>\n<p><strong>\u0422\u0440\u0435\u0442\u044c\u0435: dialect layer.<\/strong><\/p>\n<p>PostgreSQL, MySQL \u0438 SQLite \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f. qrafter \u043d\u0435 \u0441\u0442\u0438\u0440\u0430\u0435\u0442 \u044d\u0442\u0438 \u043e\u0442\u043b\u0438\u0447\u0438\u044f, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c quoting \u0438 placeholders \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<\/p>\n<p><strong>\u0427\u0435\u0442\u0432\u0451\u0440\u0442\u043e\u0435: \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044f.<\/strong><\/p>\n<p>\u0424\u0438\u043b\u044c\u0442\u0440\u044b, join\u2019\u044b, CTE \u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435 \u043a\u0443\u0441\u043a\u0430\u043c\u0438 \u0441\u0442\u0440\u043e\u043a\u0438, \u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0418\u0445 \u043f\u0440\u043e\u0449\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p><strong>\u041f\u044f\u0442\u043e\u0435: \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c.<\/strong><\/p>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0439 sql-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043a \u043d\u0435\u043c\u0443. \u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>database\/sql<\/code>, <code>sqlx<\/code>, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u2014 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<h2>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432<\/h2>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u0434\u0445\u043e\u0434<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043e\u0433\u0434\u0430 \u0445\u043e\u0440\u043e\u0448<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0413\u0434\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0431\u043e\u043b\u0435\u0442\u044c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Raw SQL<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b, placeholder\u2019\u044b, \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 <code>WHERE<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">ORM<\/p>\n<\/td>\n<td>\n<p align=\"left\">CRUD, \u0441\u0432\u044f\u0437\u0438, hooks, \u0431\u044b\u0441\u0442\u0440\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u0432\u0435\u0440\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p align=\"left\">SQL \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043c\u0435\u043d\u0435\u0435 \u044f\u0432\u043d\u044b\u043c, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f, \u0442\u0440\u0443\u0434\u043d\u0435\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 CTE<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Squirrel<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0443\u0436\u0435\u043d \u0433\u0438\u0431\u043a\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u0435\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0447\u0430\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">sqlx<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0443\u0436\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 typed-\u0441\u0431\u043e\u0440\u043a\u0443 SQL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">qrafter<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0443\u0436\u0435\u043d \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 SQL \u0432 Go \u0441 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u043c\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041d\u0435 ORM, \u043d\u0435 codegen, \u043d\u0435 \u043f\u043e\u043b\u043d\u0430\u044f compile-time \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0445\u0435\u043c\u044b<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u042f \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u044e \u044d\u0442\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u043c\u0438. \u0412 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c raw SQL \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, sqlc \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, sqlx \u0434\u043b\u044f scanning \u0438 qrafter \u0434\u043b\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u043d\u0435 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u00a0\u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u00ab\u043c\u043e\u0434\u043d\u043e \/ \u043d\u0435\u00a0\u043c\u043e\u0434\u043d\u043e\u00bb, \u0430\u00a0\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430\u00a0\u0431\u043e\u043b\u044c.<\/p>\n<p><strong>\u0413\u0434\u0435 qrafter \u043d\u0435 \u043d\u0443\u0436\u0435\u043d<\/strong><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0447\u0435\u0441\u0442\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c.<\/p>\n<p>qrafter \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442 ORM, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0441\u0432\u044f\u0437\u0438, \u0436\u0430\u0434\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u043e\u0432\u0435\u0440\u0445 \u0431\u0430\u0437\u044b.<\/p>\n<p>qrafter \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442 sqlc, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f SQL-first workflow \u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c Go-\u043a\u043e\u0434 \u0438\u0437 <code>.sql<\/code> \u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>qrafter \u043d\u0435 \u0434\u0430\u0451\u0442 \u0441\u0442\u043e\u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u0443\u044e compile-time \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 production-\u0441\u0445\u0435\u043c\u044b. <code>q.Column[int]<\/code> \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u0432 Go-\u043a\u043e\u0434\u0435, \u043d\u043e \u043d\u0435 \u0434\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0432 \u0431\u0430\u0437\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430 \u0441 \u0442\u0430\u043a\u0438\u043c \u0442\u0438\u043f\u043e\u043c.<\/p>\n<p>qrafter \u0441\u0435\u0439\u0447\u0430\u0441 pre-v1, \u0438 API \u043c\u043e\u0436\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f. \u042d\u0442\u043e \u043f\u0440\u044f\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 README \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>\u042f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u0438\u0448\u0443 \u044d\u0442\u043e \u0437\u0434\u0435\u0441\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u0445\u043e\u0447\u0443 \u043f\u0440\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u0430\u043a \u0441\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u0443\u044e \u043f\u0443\u043b\u044e.<\/p>\n<p>\u042d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0437\u043e\u043d\u044b: <strong>\u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 SQL \u0431\u0435\u0437 ORM \u0438 \u0431\u0435\u0437 codegen<\/strong>.<\/p>\n<h2>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435: DDL \u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/h2>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435, \u2014 DDL \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>\u0423 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435: \u0435\u0441\u043b\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432 Go-\u043a\u043e\u0434\u0435, \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f <code>SELECT<\/code>, <code>INSERT<\/code>, <code>UPDATE<\/code> \u0438 <code>DELETE<\/code>, \u043d\u043e \u0438 \u0434\u043b\u044f schema-level \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0439\u0442\u0438 \u043a workflow \u0432 \u0434\u0443\u0445\u0435 Alembic (\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043d\u0430 Python):<\/p>\n<blockquote>\n<p>\u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0430\u0437\u044b + typed table definitions \u0432 Go \u2192 diff \u2192  \u0447\u0435\u0440\u043d\u043e\u0432\u0430\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u2192<br \/>\u0440\u0443\u0447\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u043f\u0440\u0430\u0432\u043a\u0430 \u2192 \u0444\u0430\u0439\u043b \u0441 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0435\u0439<\/p>\n<\/blockquote>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0437\u0434\u0435\u0441\u044c \u2014 \u0447\u0435\u0440\u043d\u043e\u0432\u0430\u044f.<\/p>\n<p>\u042f \u043d\u0435 \u0445\u043e\u0447\u0443, \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043c\u043e\u043b\u0447\u0430 \u0441\u0430\u043c \u043c\u0435\u043d\u044f\u043b production-\u0441\u0445\u0435\u043c\u0443. \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c, \u043d\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0435\u0432\u044c\u044e. \u0412 \u044d\u0442\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434 Alembic: \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u044b \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0447\u0435\u0440\u043d\u043e\u0432\u0443\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438 \u0434\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0440\u0443\u043a\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043b\u044f qrafter \u044d\u0442\u043e \u043f\u043e\u043a\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0430 \u043d\u0435 \u043e\u0431\u0435\u0449\u0430\u043d\u0438\u0435 \u043c\u0430\u0433\u0438\u0438. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u2014 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c: \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u043d\u0435\u043b\u044c\u0437\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0440\u043e\u0439 + \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e SQL, \u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 DDL \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430.<\/p>\n<p>\u041d\u043e \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0445\u0435\u043c\u044b \u0432 Go \u043c\u043e\u0433\u0443\u0442 \u0441\u0442\u0430\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430.<\/p>\n<h2>\u041a\u0430\u043a \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c<\/h2>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430:<\/p>\n<pre><code class=\"bash\">go get github.com\/SennovE\/qrafter<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042f \u0431\u044b \u043d\u0435 \u0441\u043e\u0432\u0435\u0442\u043e\u0432\u0430\u043b \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f. \u041b\u0443\u0447\u0448\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u2014 \u0432\u0437\u044f\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<ul>\n<li>\n<p>3 &#8212; 5 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>sort\/order<\/p>\n<\/li>\n<li>\n<p>pagination<\/p>\n<\/li>\n<li>\n<p>COUNT(*) \u0441 \u0442\u0435\u043c\u0438 \u0436\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u043e\u0434\u0438\u043d join<\/p>\n<\/li>\n<li>\n<p>PostgreSQL \u0438\u043b\u0438 SQLite<\/p>\n<\/li>\n<\/ul>\n<p>\u0418 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u043a\u043e\u0434 \u0441\u0442\u0430\u043b \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435 \u2014 qrafter \u043f\u043e\u043f\u0430\u043b \u0432 \u0432\u0430\u0448 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, raw SQL, sqlc, Squirrel, sqlx \u0438\u043b\u0438 ORM \u0431\u0443\u0434\u0443\u0442 \u043b\u0443\u0447\u0448\u0435.<\/p>\n<h2>\u0427\u0442\u043e \u043c\u043d\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/h2>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u043b\u043e\u0434\u043e\u0439, \u0438 \u043c\u043d\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u0430\u0436\u043d\u0435\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b, \u0447\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u043f\u043e\u0436\u0435\u043b\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<blockquote>\n<p>\u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441<\/p>\n<p>\u044f \u0445\u043e\u0442\u0435\u043b \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0442 \u0442\u0430\u043a<\/p>\n<p>\u0432 qrafter \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u0432\u043e\u0442 \u0437\u0434\u0435\u0441\u044c<\/p>\n<\/blockquote>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b:<\/p>\n<ul>\n<li>\n<p>API naming<\/p>\n<\/li>\n<li>\n<p>\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>joins<\/p>\n<\/li>\n<li>\n<p>CTE \/ recursive CTE<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 database\/sql<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>dialect-specific \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u0442\u0435 qrafter \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438 \u0443\u043f\u0440\u0451\u0442\u0435\u0441\u044c \u0432 \u0448\u0435\u0440\u043e\u0445\u043e\u0432\u0430\u0442\u043e\u0441\u0442\u044c API \u2014 \u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u043e\u0442 \u0444\u0438\u0434\u0431\u0435\u043a, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f \u0438 \u043f\u0438\u0448\u0443 \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u042f \u043d\u0435 \u043f\u0438\u0441\u0430\u043b qrafter \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u0438\u0440\u0443 \u0441\u0440\u043e\u0447\u043d\u043e \u043d\u0443\u0436\u0435\u043d \u0435\u0449\u0451 \u043e\u0434\u0438\u043d query builder. \u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0435\u0433\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f raw SQL, \u043d\u043e \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0435\u0433\u043e. \u042f \u0445\u043e\u0447\u0443 \u0432\u0438\u0434\u0435\u0442\u044c SQL. \u0425\u043e\u0447\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441. \u0425\u043e\u0447\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 <code>database\/sql<\/code>, <code>sqlx<\/code>, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, connection pool \u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u041d\u043e \u044f \u043d\u0435 \u0445\u043e\u0447\u0443 \u0440\u0443\u043a\u0430\u043c\u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c <code>$1<\/code>, <code>$2<\/code>, <code>$3<\/code>. \u041d\u0435 \u0445\u043e\u0447\u0443 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>\"user_name\"<\/code> \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443. \u041d\u0435 \u0445\u043e\u0447\u0443 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c <code>WHERE<\/code> \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u044e \u0441\u0442\u0440\u043e\u043a. \u041d\u0435 \u0445\u043e\u0447\u0443 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 \u043c\u0435\u0436\u0434\u0443 list \u0438 count. qrafter \u2014 \u044d\u0442\u043e \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u043d\u044f\u0442\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043c\u0435\u0436\u0434\u0443 raw SQL, ORM \u0438 codegen:<\/p>\n<blockquote>\n<p><a href=\"https:\/\/github.com\/SennovE\/qrafter\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 GitHub<\/a><\/p>\n<\/blockquote>\n<p>\u0411\u0443\u0434\u0443 \u0440\u0430\u0434 issues, PR \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u0432\u0430\u0448\u0438\u0445 Go-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1042578\/\">https:\/\/habr.com\/ru\/articles\/1042578\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u0439 SQL.\u041d\u0435 \u00ab\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c\u00bb, \u0430\u00a0\u043f\u0440\u0430\u0432\u0434\u0430 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u0412\u00a0\u0445\u043e\u0440\u043e\u0448\u0435\u043c SQL\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e\u00a0\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u00a0\u0434\u0430\u043d\u043d\u044b\u043c\u0438: \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0451\u043c, \u043a\u0430\u043a\u00a0\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c, \u0433\u0434\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c, \u0447\u0442\u043e\u00a0\u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u043c \u0438 \u0432\u00a0\u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0442\u0434\u0430\u0451\u043c \u043d\u0430\u0440\u0443\u0436\u0443. \u0418 \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f Go \u0437\u0430\u00a0\u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e: \u043a\u043e\u0434 \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u044f\u043c\u043e\u0439, \u044f\u0432\u043d\u044b\u0439 \u0438 \u0431\u0435\u0437\u00a0\u043b\u0438\u0448\u043d\u0438\u0445 \u0446\u0435\u0440\u0435\u043c\u043e\u043d\u0438\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u043b\u0433\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u0431\u0430\u0437\u043e\u0439 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u0430\u043a:rows, err := db.QueryContext(ctx, `    SELECT id, user_name, age\u00a0 \u00a0 FROM users\u00a0 \u00a0 WHERE status = $1\u00a0 \u00a0 ORDER BY id\u00a0 \u00a0 LIMIT $2`, status, limit)\u0412\u0441\u0451 \u0447\u0435\u0441\u0442\u043d\u043e. SQL \u0432\u0438\u0434\u0435\u043d. \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438. \u041d\u043e\u00a0\u043f\u043e\u0442\u043e\u043c \u0432\u00a0\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b. \u041f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u0444\u0438\u043b\u044c\u0442\u0440\u044b. \u041f\u043e\u0442\u043e\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0438\u0437\u00a0API. \u041f\u043e\u0442\u043e\u043c \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044f. \u041f\u043e\u0442\u043e\u043c \u0442\u0430\u043a\u043e\u0439\u00a0\u0436\u0435 WHERE \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f COUNT(*) \u0434\u043b\u044f\u00a0\u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a.\u041f\u043e\u0442\u043e\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u00a0SQLite, \u0445\u043e\u0442\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d \u043d\u0430\u00a0PostgreSQL. \u0418 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u00ab\u043f\u0440\u043e\u0441\u0442\u043e \u0441\u044b\u0440\u043e\u0439 SQL\u00bb, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 query builder:query := `\u00a0 \u00a0 SELECT id, user_name, age\u00a0 \u00a0 FROM users\u00a0 \u00a0 WHERE 1 = 1`args := make([]any, 0)if filter.Status != &#171;&#187; {\u00a0 \u00a0 args = append(args, filter.Status)\u00a0 \u00a0 query += fmt.Sprintf(&#187; AND status = $%d&#187;, len(args))}if filter.MinAge != nil {\u00a0 \u00a0 args = append(args, *filter.MinAge)\u00a0 \u00a0 query += fmt.Sprintf(&#187; AND age &gt;= $%d&#187;, len(args))}if filter.CreatedAfter != nil {\u00a0 \u00a0 args = append(args, *filter.CreatedAfter)\u00a0 \u00a0 query += fmt.Sprintf(&#187; AND created_at &gt;= $%d&#187;, len(args))}query += &#187; ORDER BY id LIMIT 100&#8243;\u042d\u0442\u043e \u043d\u0435 \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0430. \u0422\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u042f \u0441\u0430\u043c \u043f\u0438\u0441\u0430\u043b \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437.\u041d\u043e \u0441 \u043d\u0438\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043e\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0439 \u0440\u0443\u0447\u043d\u043e\u0439 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 SQL-\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u043c, \u043d\u043e\u043c\u0435\u0440\u043e\u043c placeholder\u2019\u0430 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u0435\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0432 []any.\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c \u043d\u043e\u043c\u0435\u0440\u0430. \u041f\u043e\u043c\u0435\u043d\u044f\u043b \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c args.\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0444\u0438\u043b\u044c\u0442\u0440 \u0432 COUNT(*) \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044c, \u0447\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446 \u043e\u0431\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435.\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u2014 \u0443\u0434\u0430\u0447\u0438 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 &#171;user_name&#187; \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443.\u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043c\u0435\u043d\u044f \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0435 SQL. \u041c\u0435\u043d\u044f \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0430\u0435\u0442 \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0438\u044f \u0432\u043e\u043a\u0440\u0443\u0433 SQL.\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f qrafter.\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 qrafterqrafter \u2014 \u044d\u0442\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f Go.\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f:SQL \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u044f\u0432\u043d\u044b\u043c, \u043d\u043e \u0438\u043c\u0435\u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a, placeholder\u2019\u044b \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439.Qrafter \u0441\u0442\u0440\u043e\u0438\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL \u0438\u0437 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 Go \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0438 \u043e\u0442\u0434\u0430\u0451\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 database\/sql, sqlx \u0438 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:package mainimport (    &#171;fmt&#187;    q &#171;github.com\/SennovE\/qrafter&#187;    &#171;github.com\/SennovE\/qrafter\/dialect&#187;)type User struct {    q.Table `table:&#187;users&#187;`    ID       q.Column[int] `db:&#187;id&#187;`    UserName q.Column[string]    Age      q.Column[int]}func main() {    users := q.MustNewTable[User]()    sql, args, err := q.Select(users.ID, users.UserName).        Where(            users.Age.Ge(18),            users.UserName.Eq(&#171;Alice&#187;),        ).        OrderBy(users.ID.Asc()).        Limit(10).        Render(dialect.PostgreSQL{})    if err != nil {        panic(err)    }    fmt.Println(sql)    fmt.Println(args)}\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:SELECT &#171;users&#187;.&#187;id&#187;, &#171;users&#187;.&#187;user_name&#187;FROM &#171;users&#187;WHERE &#171;users&#187;.&#187;age&#187; &gt;= $1 AND &#171;users&#187;.&#187;user_name&#187; = $2ORDER BY &#171;users&#187;.&#187;id&#187; ASCLIMIT 10\u0418 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:[]any{18, &#171;Alice&#187;}\u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u0434 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a SQL: SELECT, WHERE, ORDER BY, LIMIT.\u041d\u043e \u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u0438\u0448\u0443 &#171;user_name&#187; \u0440\u0443\u043a\u0430\u043c\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0435\u0441\u0442\u0435. \u041d\u0435 \u0441\u0447\u0438\u0442\u0430\u044e $1, $2, $3. \u041d\u0435 \u0434\u0443\u043c\u0430\u044e, \u043a\u0430\u043a\u0438\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0433\u043e SQL-\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430.\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 ORM\u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441: \u00ab\u0417\u0430\u0447\u0435\u043c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c ORM?\u00bbORM \u2014 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u0441\u0432\u044f\u0437\u0438, \u0436\u0430\u0434\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 CRUD \u0432\u043e\u043a\u0440\u0443\u0433 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.\u041d\u043e qrafter \u0440\u0435\u0448\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443.\u042f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u044f\u0442\u0430\u0442\u044c SQL \u0437\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e. \u041d\u0435 \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441\u0432\u044f\u0437\u0435\u0439. \u041d\u0435 \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0440\u0435\u0448\u0430\u043b\u0430, \u043a\u043e\u0433\u0434\u0430 \u0438 \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c  \u041c\u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u0431\u044b\u043b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u043d\u0438\u0436\u0435: \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Go \u0432 SQL string \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.\u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u044f \u0441\u0430\u043c \u0440\u0435\u0448\u0430\u044e, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441: database\/sql, sqlx, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f, \u0441\u0432\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043c\u0438\u0434\u043b\u0432\u0430\u0440\u044b, \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.database\/sql \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Go \u0443\u0436\u0435 \u0434\u0430\u0451\u0442 \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a SQL-like \u0431\u0430\u0437\u0430\u043c, \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u043f\u0443\u043b\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. qrafter \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439, \u0430 \u0432\u0441\u0442\u0430\u0451\u0442 \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c \u043a\u0430\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 sqlc\u0412\u0442\u043e\u0440\u043e\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u0437 sql-\u0444\u0430\u0439\u043b\u043e\u0432.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, sqlc \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 Go-\u043a\u043e\u0434 \u0438\u0437 SQL. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: SQL \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0438\u0441\u0442\u0438\u043d\u044b, \u0430 Go API \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438.\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 .sql \u0444\u0430\u0439\u043b\u0430\u0445, sqlc \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c.\u041d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437 API-\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442:GET \/users?status=active&amp;min_age=18&amp;created_after=2026-01-01\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0430\u0441\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 Go-\u043a\u043e\u0434\u0435:query := q.Select(users.ID, users.UserName, users.Age)if filter.Status != &#171;&#187; {    query = query.Where(users.Status.Eq(filter.Status))}if filter.MinAge != nil {    query = query.Where(users.Age.Ge(*filter.MinAge))}if filter.CreatedAfter != nil {    query = query.Where(users.CreatedAt.Ge(*filter.CreatedAfter))}sql, args, err := query.    OrderBy(users.ID.Asc()).    Limit(100).    Render(dialect.PostgreSQL{})\u0422\u043e \u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 SQL-\u0441\u0442\u0440\u043e\u043a\u0438sql := `    SELECT id, user_name, age    FROM users`where := make([]string, 0)args := make([]any, 0)if filter.Status != &#171;&#187; {    args = append(args, filter.Status)    where = append(where, fmt.Sprintf(&#171;status = $%d&#187;, len(args)))}if filter.MinAge != nil {    args = append(args, *filter.MinAge)    where = append(where, fmt.Sprintf(&#171;age &gt;= $%d&#187;, len(args)))}if filter.CreatedAfter != nil {    args = append(args, *filter.CreatedAfter)    where = append(where, fmt.Sprintf(&#171;created_at &gt;= $%d&#187;, len(args)))}if len(where) &gt; 0 {    sql += &#187; WHERE &#187; + strings.Join(where, &#187; AND &#171;)}sql += &#187; ORDER BY id ASC LIMIT 100&#8243;\u0417\u0434\u0435\u0441\u044c \u043c\u043d\u0435 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 SQL-\u0444\u0430\u0439\u043b \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041c\u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0439, \u043d\u043e \u043d\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u044e \u0441\u0442\u0440\u043e\u043a. \u0412\u043e\u0442 \u044d\u0442\u0430 \u0437\u043e\u043d\u0430 \u0438 \u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442\u043e qrafter.\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 Squirrel\u0415\u0441\u0442\u044c \u0438 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Squirrel \u2014 SQL-\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f Go. \u041e\u043d \u0445\u043e\u0440\u043e\u0448\u043e \u0443\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043a\u043b\u0435\u0439\u043a\u0443 \u0441\u0442\u0440\u043e\u043a:sq.Select(&#171;id&#187;, &#171;user_name&#187;).\u00a0 \u00a0 From(&#171;users&#187;).\u00a0 \u00a0 Where(sq.Eq{&#171;status&#187;: &#171;active&#187;})\u042d\u0442\u043e \u0443\u0436\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c strings.Builder, fmt.Sprintf \u0438 \u0440\u0443\u0447\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 AND.\u041d\u043e \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0434\u0440\u0443\u0433\u043e\u0433\u043e. \u0412 Squirrel \u0438\u043c\u0435\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0447\u0430\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u0410 \u044f \u0445\u043e\u0442\u0435\u043b \u0432\u0438\u0434\u0435\u0442\u044c \u044f\u0432\u043d\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:q.Select(users.ID, users.UserName).\u00a0 \u00a0 Where(users.Status.Eq(&#171;active&#187;))\u042d\u0442\u043e \u043d\u0435\u00a0\u0434\u0435\u043b\u0430\u0435\u0442 qrafter \u00ab\u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u0434\u0430\u00bb. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u044b\u0431\u043e\u0440: \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0437\u0430\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u00a0\u043a\u043e\u0434\u0443 \u0445\u043e\u0434\u044f\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u044b \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432.\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0412 qrafter \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u2014 \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u0430\u044f Go-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:type UserTable struct {    q.Table `table:&#187;users&#187;`    ID        q.Column[int64]  `db:&#187;id&#187;`    UserName  q.Column[string] `db:&#187;user_name&#187;`    Age       q.Column[int]    Status    q.Column[string]    CreatedAt q.Column[time.Time] `db:&#187;created_at&#187;`    DeletedAt q.Column[*time.Time] `db:&#187;deleted_at&#187;`}\u041f\u043e\u0442\u043e\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c SQL-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445:users := q.MustNewTable[UserTable]()\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e users.Age, users.Status, users.CreatedAt \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0438. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:users.Age.Ge(18)users.Status.Eq(&#171;active&#187;)users.DeletedAt.IsNull()users.CreatedAt.Ge(since)qrafter \u0441\u0430\u043c \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0441 \u0442\u0438\u043f\u043e\u043c Column \u0441 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a: \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0433 db \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 snake_case \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044f.\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 1: \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u044b\u0445 placeholder\u2019\u043e\u0432\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0444\u0438\u043b\u044c\u0442\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:type UserFilter struct {    Status         string    MinAge         *int    CreatedAfter   *time.Time    IncludeDeleted bool}\u041d\u0430 raw SQL \u044f \u0431\u044b \u0440\u0430\u043d\u044c\u0448\u0435 \u0434\u0435\u0440\u0436\u0430\u043b \u0440\u044f\u0434\u043e\u043c query, args \u0438 len(args). \u0421 qrafter \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a:func listUsers(ctx context.Context, db *sql.DB, filter UserFilter) error {    users := q.MustNewTable[UserTable]()    query := q.Select(users.ID, users.UserName, users.Age, users.Status, users.CreatedAt)    if filter.Status != &#171;&#187; {        query = query.Where(users.Status.Eq(filter.Status))    }    if filter.MinAge != nil {        query = query.Where(users.Age.Ge(*filter.MinAge))    }    if filter.CreatedAfter != nil {        query = query.Where(users.CreatedAt.Ge(*filter.CreatedAfter))    }    if !filter.IncludeDeleted {        query = query.Where(users.DeletedAt.IsNull())    }    sqlText, args, err := query.        OrderBy(users.ID.Asc()).        Limit(100).        Render(dialect.PostgreSQL{})    if err != nil {        return err    }    rows, err := db.QueryContext(ctx, sqlText, args&#8230;)    if err != nil {        return err    }    defer rows.Close()    \/\/ scan rows&#8230;    return rows.Err()\u0422\u043e \u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 SQL-\u0441\u0442\u0440\u043e\u043a\u0438func listUsers(ctx context.Context, db *sql.DB, filter UserFilter) error {    query := `        SELECT id, user_name, age, status, created_at        FROM users    `    where := make([]string, 0)    args := make([]any, 0)    if filter.Status != &#171;&#187; {        args = append(args, filter.Status)        where = append(where, fmt.Sprintf(&#171;status = $%d&#187;, len(args)))    }    if filter.MinAge != nil {        args = append(args, *filter.MinAge)        where = append(where, fmt.Sprintf(&#171;age &gt;= $%d&#187;, len(args)))    }    if filter.CreatedAfter != nil {        args = append(args, *filter.CreatedAfter)        where = append(where, fmt.Sprintf(&#171;created_at &gt;= $%d&#187;, len(args)))    }    if !filter.IncludeDeleted {        where = append(where, &#171;deleted_at IS NULL&#187;)    }    if len(where) &gt; 0 {        query += &#187; WHERE &#187; + strings.Join(where, &#187; AND &#171;)    }    query += &#187; ORDER BY id ASC LIMIT 100&#8243;    rows, err := db.QueryContext(ctx, query, args&#8230;)    if err != nil {        return err    }    defer rows.Close()    \/\/ scan rows&#8230;    return rows.Err()}\u0412\u0430\u0436\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u043a\u043e\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-482051","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482051","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=482051"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482051\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=482051"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=482051"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=482051"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}