func (c *PgCache) GetGuild(id uint64, withMembers bool) (g guild.Guild, ok bool) {
	var raw string
	err := c.QueryRow(context.Background(), `SELECT "data" FROM guilds WHERE "guild_id" = $1;`, id).Scan(&raw)
	if err != nil {
		if err == pgx.ErrNoRows {
			return g, false
		}
		fmt.Println(err.Error())
		return
	}
	var cachedGuild guild.CachedGuild
	if err := json.Unmarshal([]byte(raw), &cachedGuild); err != nil {
		fmt.Println(err.Error())
		return
	}
	g = cachedGuild.ToGuild(id)
	g.Channels = c.GetGuildChannels(id)
	g.Roles = c.GetGuildRoles(id)
	if withMembers {
		g.Members = c.GetGuildMembers(id, false)
	}
	g.Emojis = c.GetGuildEmojis(id)
	g.VoiceStates = c.GetGuildVoiceStates(id)
	return g, true
}
use withMembers with extreme caution!
package cache
import (
	"context"
	"database/sql"
	"fmt"
	"github.com/jackc/pgx/v4"
	"github.com/jackc/pgx/v4/pgxpool"
	jsoniter "github.com/json-iterator/go"
	"github.com/rxdn/gdl/objects/channel"
	"github.com/rxdn/gdl/objects/guild"
	"github.com/rxdn/gdl/objects/guild/emoji"
	"github.com/rxdn/gdl/objects/member"
	"github.com/rxdn/gdl/objects/user"
	"sync"
)
type PgCache struct {
	*pgxpool.Pool
	Options CacheOptions
	selfLock sync.RWMutex
	self     user.User
}
var json = jsoniter.Config{
	MarshalFloatWith6Digits: false,
	EscapeHTML:              false,
	SortMapKeys:             false,
}.Froze()
func NewPgCache(db *pgxpool.Pool, options CacheOptions) PgCache {
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS guilds("guild_id" int8 NOT NULL UNIQUE, "data" jsonb NOT NULL, PRIMARY KEY("guild_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS channels("channel_id" int8 NOT NULL UNIQUE, "guild_id" int8 NOT NULL, "data" jsonb NOT NULL, PRIMARY KEY("channel_id", "guild_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS users("user_id" int8 NOT NULL UNIQUE, "data" jsonb NOT NULL, PRIMARY KEY("user_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS members("guild_id" int8 NOT NULL, "user_id" int8 NOT NULL, "data" jsonb NOT NULL, PRIMARY KEY("guild_id", "user_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS roles("role_id" int8 NOT NULL UNIQUE, "guild_id" int8 NOT NULL, "data" jsonb NOT NULL, PRIMARY KEY("role_id", "guild_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS emojis("emoji_id" int8 NOT NULL UNIQUE, "guild_id" int8 NOT NULL, "data" jsonb NOT NULL, PRIMARY KEY("emoji_id", "guild_id"));`)
	pgMustRun(db, `CREATE TABLE IF NOT EXISTS voice_states("guild_id" int8 NOT NULL, "user_id" INT8 NOT NULL, "data" jsonb NOT NULL, PRIMARY KEY("guild_id", "user_id"));`)  
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS channels_guild_id ON channels("guild_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS members_guild_id ON members("guild_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS member_user_id ON members("user_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS roles_guild_id ON roles("guild_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS emojis_guild_id ON emojis("guild_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS voice_states_guild_id ON voice_states("guild_id");`)
	pgMustRun(db, `CREATE INDEX CONCURRENTLY IF NOT EXISTS voice_states_user_id ON voice_states("user_id");`)
	return PgCache{
		Pool:    db,
		Options: options,
	}
}
func pgMustRun(db *pgxpool.Pool, query string) {
	if _, err := db.Exec(context.Background(), query); err != nil {
		panic(err)
	}
}
func (c *PgCache) GetOptions() CacheOptions {
	return c.Options
}
func (c *PgCache) StoreUser(user user.User) {
	if c.Options.Users {
		if encoded, err := json.Marshal(user.ToCachedUser()); err == nil {
			_, _ = c.Exec(context.Background(), `INSERT INTO users("user_id", "data") VALUES($1, $2) ON CONFLICT("user_id") DO UPDATE SET "data" = $2;`, user.Id, string(encoded))
		}
	}
}
func (c *PgCache) StoreUsers(users []user.User) {
	if c.Options.Users {
		batch := &pgx.Batch{}
		for _, u := range users {
			if encoded, err := json.Marshal(u.ToCachedUser()); err == nil {
				batch.Queue(`INSERT INTO users("user_id", "data") VALUES($1, $2) ON CONFLICT("user_id") DO UPDATE SET "data" = $2;`, u.Id, string(encoded))
			}
		}
		br := c.SendBatch(context.Background(), batch)
		defer br.Close()
		_, _ = br.Exec()
	}
}
func (c *PgCache) GetUser(id uint64) (u user.User, ok bool) {
	var raw string
	if err := c.QueryRow(context.Background(), `SELECT "data" FROM users WHERE "user_id" = $1;`, id).Scan(&raw); err != nil {
		return
	}
	var cached user.CachedUser
	if err := json.Unmarshal([]byte(raw), &cached); err != nil {
		return
	}
	return cached.ToUser(id), true
}
func (c *PgCache) StoreGuilds(guilds []guild.Guild) {
	if c.Options.Guilds {
		batch := &pgx.Batch{}
		for _, guild := range guilds {
			if encoded, err := json.Marshal(guild.ToCachedGuild()); err == nil {
				batch.Queue(`INSERT INTO guilds("guild_id", "data") VALUES($1, $2) ON CONFLICT("guild_id") DO UPDATE SET "data" = $2;`, guild.Id, string(encoded))
			}
			if c.Options.Channels {
				for _, channel := range guild.Channels {
					if encoded, err := json.Marshal(channel.ToCachedChannel()); err == nil {
						batch.Queue(`INSERT INTO channels("channel_id", "guild_id", "data") VALUES($1, $2, $3) ON CONFLICT("channel_id") DO UPDATE SET "data" = $3;`, channel.Id, channel.GuildId, string(encoded))
					}
				}
			}
			if c.Options.Roles {
				for _, role := range guild.Roles {
					if encoded, err := json.Marshal(role.ToCachedRole(guild.Id)); err == nil {
						batch.Queue(`INSERT INTO roles("role_id", "guild_id", "data") VALUES($1, $2, $3) ON CONFLICT("role_id", "guild_id") DO UPDATE SET "data" = $3;`, role.Id, guild.Id, string(encoded))
					}
				}
			}
			if c.Options.Members {
				for _, member := range guild.Members {
					if encoded, err := json.Marshal(member.ToCachedMember()); err == nil {
						batch.Queue(`INSERT INTO members("guild_id", "user_id", "data") VALUES($1, $2, $3) ON CONFLICT("guild_id", "user_id") DO UPDATE SET "data" = $3;`, guild.Id, member.User.Id, string(encoded))
					}
				}
			}
			if c.Options.Users {
				for _, member := range guild.Members {
					if encoded, err := json.Marshal(member.User.ToCachedUser()); err == nil {
						batch.Queue(`INSERT INTO users("user_id", "data") VALUES($1, $2) ON CONFLICT("user_id") DO UPDATE SET "data" = $2;`, member.User.Id, string(encoded))
					}
				}
			}
			if c.Options.Emojis {
				for _, emoji := range guild.Emojis {
					if encoded, err := json.Marshal(emoji.ToCachedEmoji(guild.Id)); err == nil {
						batch.Queue(`INSERT INTO emojis("emoji_id", "guild_id", "data") VALUES($1, $2, $3) ON CONFLICT("emoji_id") DO UPDATE SET "data" = $3;`, emoji.Id, guild.Id, string(encoded))
					}
				}
			}
			if c.Options.VoiceStates {
				for _, state := range guild.VoiceStates {
					if encoded, err := json.Marshal(state.ToCachedVoiceState()); err == nil {
						batch.Queue(`INSERT INTO voice_states("guild_id", "user_id", "data") VALUES($1, $2, $3) ON CONFLICT("guild_id", "user_id") DO UPDATE SET "data" = $3;`, state.GuildId, state.UserId, string(encoded))
					}
				}
			}
		}
		br := c.SendBatch(context.Background(), batch)
		defer br.Close()
		_, _ = br.Exec()
	}
}
func (c *PgCache) StoreGuild(g guild.Guild) {
	if c.Options.Guilds {
		if encoded, err := json.Marshal(g.ToCachedGuild()); err == nil {
			_, _ = c.Exec(context.Background(), `INSERT INTO guilds("guild_id", "data") VALUES($1, $2) ON CONFLICT("guild_id") DO UPDATE SET "data" = $2;`, g.Id, string(encoded))
		}
	}
	for i, channel := range g.Channels {
		channel.GuildId = g.Id
		g.Channels[i] = channel
	}
	c.StoreChannels(g.Channels)
	c.StoreRoles(g.Roles, g.Id)
	c.StoreMembers(g.Members, g.Id)
	c.StoreEmojis(g.Emojis, g.Id)
	c.StoreVoiceStates(g.VoiceStates)
	var users []user.User
	for _, m := range g.Members {
		users = append(users, m.User)
	}
	c.StoreUsers(users)
}