first commit

This commit is contained in:
2025-07-26 18:34:56 +05:30
commit d340db6dfd
29 changed files with 2284 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
// Code generated by db-gen. DO NOT EDIT.
package branchuser
import "code.patial.tech/go/pgm"
const (
// BranchID field has db type "bigint NOT NULL"
BranchID pgm.Field = "branch_users.branch_id"
// UserID field has db type "bigint NOT NULL"
UserID pgm.Field = "branch_users.user_id"
// RoleID field has db type "smallint NOT NULL"
RoleID pgm.Field = "branch_users.role_id"
// CreatedAt field has db type "timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL"
CreatedAt pgm.Field = "branch_users.created_at"
// UpdatedAt field has db type "timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL"
UpdatedAt pgm.Field = "branch_users.updated_at"
)

View File

@@ -0,0 +1,18 @@
// Code generated by db-gen. DO NOT EDIT.
package comment
import "code.patial.tech/go/pgm"
const (
// ID field has db type "integer NOT NULL"
ID pgm.Field = "comments.id"
// PostID field has db type "integer NOT NULL"
PostID pgm.Field = "comments.post_id"
// UserID field has db type "integer NOT NULL"
UserID pgm.Field = "comments.user_id"
// Content field has db type "text NOT NULL"
Content pgm.Field = "comments.content"
// CreatedAt field has db type "timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP"
CreatedAt pgm.Field = "comments.created_at"
)

View File

@@ -0,0 +1,18 @@
// Code generated by db-gen. DO NOT EDIT.
package employee
import "code.patial.tech/go/pgm"
const (
// ID field has db type "integer NOT NULL"
ID pgm.Field = "employees.id"
// Name field has db type "var NOT NULL"
Name pgm.Field = "employees.name"
// Department field has db type "var NOT NULL"
Department pgm.Field = "employees.department"
// Salary field has db type "decimal(10,2)"
Salary pgm.Field = "employees.salary"
// CreatedAt field has db type "timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP updated_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP"
CreatedAt pgm.Field = "employees.created_at"
)

18
example/db/post/posts.go Normal file
View File

@@ -0,0 +1,18 @@
// Code generated by db-gen. DO NOT EDIT.
package post
import "code.patial.tech/go/pgm"
const (
// ID field has db type "integer NOT NULL"
ID pgm.Field = "posts.id"
// UserID field has db type "integer NOT NULL"
UserID pgm.Field = "posts.user_id"
// Title field has db type "character varying(255) NOT NULL"
Title pgm.Field = "posts.title"
// Content field has db type "text"
Content pgm.Field = "posts.content"
// CreatedAt field has db type "timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP"
CreatedAt pgm.Field = "posts.created_at"
)

15
example/db/schema.go Normal file
View File

@@ -0,0 +1,15 @@
// Code generated by code.patial.tech/go/pgm/cmd
// DO NOT EDIT.
package db
import "code.patial.tech/go/pgm"
var (
User = pgm.Table{Name: "users", FieldCount: 11}
UserSession = pgm.Table{Name: "user_sessions", FieldCount: 8}
BranchUser = pgm.Table{Name: "branch_users", FieldCount: 5}
Post = pgm.Table{Name: "posts", FieldCount: 5}
Comment = pgm.Table{Name: "comments", FieldCount: 5}
Employee = pgm.Table{Name: "employees", FieldCount: 5}
)

30
example/db/user/users.go Normal file
View File

@@ -0,0 +1,30 @@
// Code generated by db-gen. DO NOT EDIT.
package user
import "code.patial.tech/go/pgm"
const (
// ID field has db type "integer NOT NULL"
ID pgm.Field = "users.id"
// Name field has db type "character varying(255) NOT NULL"
Name pgm.Field = "users.name"
// Email field has db type "character varying(255) NOT NULL"
Email pgm.Field = "users.email"
// Phone field has db type "character varying(20)"
Phone pgm.Field = "users.phone"
// FirstName field has db type "character varying(50) NOT NULL"
FirstName pgm.Field = "users.first_name"
// MiddleName field has db type "character varying(50)"
MiddleName pgm.Field = "users.middle_name"
// LastName field has db type "character varying(50) NOT NULL"
LastName pgm.Field = "users.last_name"
// StatusID field has db type "smallint"
StatusID pgm.Field = "users.status_id"
// MfaKind field has db type "character varying(50) DEFAULT 'None'::character varying"
MfaKind pgm.Field = "users.mfa_kind"
// CreatedAt field has db type "timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP"
CreatedAt pgm.Field = "users.created_at"
// UpdatedAt field has db type "timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP"
UpdatedAt pgm.Field = "users.updated_at"
)

View File

@@ -0,0 +1,24 @@
// Code generated by db-gen. DO NOT EDIT.
package usersession
import "code.patial.tech/go/pgm"
const (
// ID field has db type "character varying NOT NULL"
ID pgm.Field = "user_sessions.id"
// CreatedAt field has db type "timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL"
CreatedAt pgm.Field = "user_sessions.created_at"
// UpdatedAt field has db type "timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL"
UpdatedAt pgm.Field = "user_sessions.updated_at"
// ExpiresAt field has db type "timestamp with time zone NOT NULL"
ExpiresAt pgm.Field = "user_sessions.expires_at"
// BranchID field has db type "bigint"
BranchID pgm.Field = "user_sessions.branch_id"
// UserID field has db type "bigint NOT NULL"
UserID pgm.Field = "user_sessions.user_id"
// RoleID field has db type "smallint"
RoleID pgm.Field = "user_sessions.role_id"
// LoginIp field has db type "character varying NOT NULL"
LoginIp pgm.Field = "user_sessions.login_ip"
)

3
example/generate.go Normal file
View File

@@ -0,0 +1,3 @@
//go:generate go run code.patial.tech/go/pgm/cmd -o ./db ./schema.sql
package example

View File

@@ -0,0 +1,18 @@
package example
import (
"testing"
"code.patial.tech/go/pgm/example/db"
"code.patial.tech/go/pgm/example/db/user"
)
func TestDelete(t *testing.T) {
expected := "DELETE FROM users WHERE users.id = $1 AND users.status_id NOT IN($2)"
got := db.User.Delete().
Where(user.ID.Eq(1), user.StatusID.NotIn(1, 2, 3)).
String()
if got != expected {
t.Errorf("got %q, want %q", got, expected)
}
}

View File

@@ -0,0 +1,84 @@
package example
import (
"testing"
"code.patial.tech/go/pgm"
"code.patial.tech/go/pgm/example/db"
"code.patial.tech/go/pgm/example/db/user"
)
func TestInsertQuery(t *testing.T) {
got := db.User.Insert().
Set(user.Email, "aa@aa.com").
Set(user.Phone, 8889991234).
Set(user.FirstName, "fname").
Set(user.LastName, "lname").
Returning(user.ID).
String()
expected := "INSERT INTO users(email, phone, first_name, last_name) VALUES($1, $2, $3, $4) RETURNING id"
if got != expected {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
func TestInsertSetMap(t *testing.T) {
got := db.User.Insert().
SetMap(map[pgm.Field]any{
user.Email: "aa@aa.com",
user.Phone: 8889991234,
user.FirstName: "fname",
user.LastName: "lname",
}).
Returning(user.ID).
String()
expected := "INSERT INTO users(email, phone, first_name, last_name) VALUES($1, $2, $3, $4) RETURNING id"
if got != expected {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
func TestInsertQuery2(t *testing.T) {
got := db.User.Insert().
Set(user.Email, "aa@aa.com").
Set(user.Phone, 8889991234).
OnConflict(user.ID).
DoNothing().
String()
expected := "INSERT INTO users(email, phone) VALUES($1, $2) ON CONFLICT (id) DO NOTHING"
if got != expected {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
// BenchmarkInsertQuery-12 1952412 605.3 ns/op 1144 B/op 18 allocs/op
func BenchmarkInsertQuery(b *testing.B) {
for b.Loop() {
_ = db.User.Insert().
Set(user.Email, "aa@aa.com").
Set(user.Phone, 8889991234).
Set(user.FirstName, "fname").
Set(user.LastName, "lname").
Returning(user.ID).
String()
}
}
// BenchmarkInsertSetMap-12 1534039 777.1 ns/op 1480 B/op 20 allocs/op
func BenchmarkInsertSetMap(b *testing.B) {
for b.Loop() {
_ = db.User.Insert().
SetMap(map[pgm.Field]any{
user.Email: "aa@aa.com",
user.Phone: 8889991234,
user.FirstName: "fname",
user.LastName: "lname",
}).
Returning(user.ID).
String()
}
}

View File

@@ -0,0 +1,90 @@
package example
import (
"testing"
"code.patial.tech/go/pgm"
"code.patial.tech/go/pgm/example/db"
"code.patial.tech/go/pgm/example/db/branchuser"
"code.patial.tech/go/pgm/example/db/employee"
"code.patial.tech/go/pgm/example/db/user"
"code.patial.tech/go/pgm/example/db/usersession"
)
func TestQryBuilder2(t *testing.T) {
got := db.User.Debug().Select(user.Email, user.FirstName).
Join(db.UserSession, user.ID, usersession.UserID).
Join(db.BranchUser, user.ID, branchuser.UserID).
Where(
user.ID.Eq(1),
pgm.Or(
user.StatusID.Eq(2),
user.UpdatedAt.Eq(3),
),
user.MfaKind.Eq(4),
pgm.Or(
user.FirstName.Eq(5),
user.MiddleName.Eq(6),
),
).
Where(
user.LastName.NEq(7),
user.Phone.Like("%123%"),
user.Email.NotInSubQuery(db.User.Select(user.ID).Where(user.ID.Eq(123))),
).
Limit(10).
Offset(100).
String()
expected := "SELECT users.email, users.first_name FROM users JOIN user_sessions ON users.id = user_sessions.user_id" +
" JOIN branch_users ON users.id = branch_users.user_id WHERE users.id = $1 AND (users.status_id = $2 OR users.updated_at = $3)" +
" AND users.mfa_kind = $4 AND (users.first_name = $5 OR users.middle_name = $6) AND users.last_name != $7 AND users.phone" +
" LIKE $8 AND users.email NOT IN(SELECT users.id FROM users WHERE users.id = $9) LIMIT 10 OFFSET 100"
if expected != got {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
func TestSelectWithHaving(t *testing.T) {
expected := "SELECT employees.department, AVG(employees.salary), COUNT(employees.id)" +
" FROM employees GROUP BY employees.department HAVING AVG(employees.salary) > $1 AND COUNT(employees.id) > $2"
got := db.Employee.
Select(employee.Department, employee.Salary.Avg(), employee.ID.Count()).
GroupBy(employee.Department).
Having(employee.Salary.Avg().Gt(50000), employee.ID.Count().Gt(5)).
String()
if expected != got {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
// BenchmarkSelect-12 668817 1753 ns/op 4442 B/op 59 allocs/op
// BenchmarkSelect-12 638901 1860 ns/op 4266 B/op 61 allocs/op
func BenchmarkSelect(b *testing.B) {
for b.Loop() {
_ = db.User.Select(user.Email, user.FirstName).
Join(db.UserSession, user.ID, usersession.UserID).
Join(db.BranchUser, user.ID, branchuser.UserID).
Where(
user.ID.Eq(1),
pgm.Or(
user.StatusID.Eq(2),
user.UpdatedAt.Eq(3),
),
user.MfaKind.Eq(4),
pgm.Or(
user.FirstName.Eq(5),
user.MiddleName.Eq(6),
),
).
Where(
user.LastName.NEq(7),
user.Phone.Like("%123%"),
user.Email.NotInSubQuery(db.User.Select(user.ID).Where(user.ID.Eq(123))),
).
Limit(10).
Offset(100).
String()
}
}

View File

@@ -0,0 +1,66 @@
package example
import (
"testing"
"code.patial.tech/go/pgm"
"code.patial.tech/go/pgm/example/db"
"code.patial.tech/go/pgm/example/db/user"
)
func TestUpdateQuery(t *testing.T) {
got := db.User.Update().
Set(user.FirstName, "ankit").
Set(user.MiddleName, "singh").
Set(user.LastName, "patial").
Where(
user.Email.Eq("aa@aa.com"),
).
Where(
user.StatusID.NEq(1),
).
String()
expected := "UPDATE users SET first_name=$1, middle_name=$2, last_name=$3 WHERE users.email = $4 AND users.status_id != $5"
if got != expected {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
func TestUpdateSetMap(t *testing.T) {
got := db.User.Update().
SetMap(map[pgm.Field]any{
user.FirstName: "ankit",
user.MiddleName: "singh",
user.LastName: "patial",
}).
Where(
user.Email.Eq("aa@aa.com"),
).
Where(
user.StatusID.NEq(1),
).
String()
expected := "UPDATE users SET first_name=$1, middle_name=$2, last_name=$3 WHERE users.email = $4 AND users.status_id != $5"
if got != expected {
t.Errorf("\nexpected: %q\ngot: %q", expected, got)
}
}
// BenchmarkUpdateQuery-12 2004985 592.2 ns/op 1176 B/op 20 allocs/op
func BenchmarkUpdateQuery(b *testing.B) {
for b.Loop() {
_ = db.User.Update().
Set(user.FirstName, "ankit").
Set(user.MiddleName, "singh").
Set(user.LastName, "patial").
Where(
user.Email.Eq("aa@aa.com"),
).
Where(
user.StatusID.NEq(1),
).
String()
}
}

306
example/schema.sql Normal file
View File

@@ -0,0 +1,306 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 15.3
-- Dumped by pg_dump version 15.3
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: myapp_development; Type: DATABASE; Schema: -; Owner: postgres
--
CREATE DATABASE myapp_development WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE = 'en_US.UTF-8';
ALTER DATABASE myapp_development OWNER TO postgres;
\connect myapp_development
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.schema_migrations (
version character varying(255) NOT NULL
);
ALTER TABLE public.schema_migrations OWNER TO postgres;
--
-- Name: users; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.users (
id integer NOT NULL,
name character varying(255) NOT NULL,
email character varying(255) NOT NULL,
phone character varying(20),
first_name character varying(50) NOT NULL,
middle_name character varying(50),
last_name character varying(50) NOT NULL,
status_id smallint,
mfa_kind character varying(50) DEFAULT 'None'::character varying,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE public.users OWNER TO postgres;
CREATE TABLE public.user_sessions (
id character varying NOT NULL,
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
expires_at timestamp with time zone NOT NULL,
branch_id bigint,
user_id bigint NOT NULL,
role_id smallint,
login_ip character varying NOT NULL,
);
CREATE TABLE public.branch_users (
branch_id bigint NOT NULL,
user_id bigint NOT NULL,
role_id smallint NOT NULL,
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
);
--
-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE public.users_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.users_id_seq OWNER TO postgres;
--
-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--
ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id;
--
-- Name: posts; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.posts (
id integer NOT NULL,
user_id integer NOT NULL,
title character varying(255) NOT NULL,
content text,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE public.posts OWNER TO postgres;
--
-- Name: posts_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE public.posts_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.posts_id_seq OWNER TO postgres;
--
-- Name: posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--
ALTER SEQUENCE public.posts_id_seq OWNED BY public.posts.id;
--
-- Name: comments; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.comments (
id integer NOT NULL,
post_id integer NOT NULL,
user_id integer NOT NULL,
content text NOT NULL,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE public.comments OWNER TO postgres;
CREATE TABLE public.employees (
id integer NOT NULL,
name var NOT NULL,
department var NOT NULL,
salary decimal(10,2) ,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
updated_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
--
-- Name: comments_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--
CREATE SEQUENCE public.comments_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.comments_id_seq OWNER TO postgres;
--
-- Name: comments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--
ALTER SEQUENCE public.comments_id_seq OWNED BY public.comments.id;
--
-- Name: users id; Type: DEFAULT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
--
-- Name: posts id; Type: DEFAULT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.posts ALTER COLUMN id SET DEFAULT nextval('public.posts_id_seq'::regclass);
--
-- Name: comments id; Type: DEFAULT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.comments ALTER COLUMN id SET DEFAULT nextval('public.comments_id_seq'::regclass);
--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.schema_migrations
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
--
-- Name: users users_email_key; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.users
ADD CONSTRAINT users_email_key UNIQUE (email);
--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
--
-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.posts
ADD CONSTRAINT posts_pkey PRIMARY KEY (id);
--
-- Name: comments comments_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.comments
ADD CONSTRAINT comments_pkey PRIMARY KEY (id);
--
-- Name: idx_comments_post_id; Type: INDEX; Schema: public; Owner: postgres
--
CREATE INDEX idx_comments_post_id ON public.comments USING btree (post_id);
--
-- Name: idx_comments_user_id; Type: INDEX; Schema: public; Owner: postgres
--
CREATE INDEX idx_comments_user_id ON public.comments USING btree (user_id);
--
-- Name: idx_posts_user_id; Type: INDEX; Schema: public; Owner: postgres
--
CREATE INDEX idx_posts_user_id ON public.posts USING btree (user_id);
--
-- Name: posts posts_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.posts
ADD CONSTRAINT posts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
--
-- Name: comments comments_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.comments
ADD CONSTRAINT comments_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id) ON DELETE CASCADE;
--
-- Name: comments comments_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--
ALTER TABLE ONLY public.comments
ADD CONSTRAINT comments_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
--
-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.schema_migrations (version) FROM stdin;
20200227231541
20200227231542
20200227231543
\.
--
-- Data for Name: users; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.users (id, name, email, created_at) FROM stdin;
\.
--
-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.posts (id, user_id, title, content, created_at) FROM stdin;
\.
--
-- Data for Name: comments; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.comments (id, post_id, user_id, content, created_at)