Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
448e6bb72a | |||
f7d3760af7 | |||
2acb05741e | |||
8104ee9df2 | |||
ab8566df03 | |||
94fa51ffb2 |
@ -7,7 +7,7 @@
|
|||||||

|

|
||||||
[](https://discord.gg/6pSWCTZ)
|
[](https://discord.gg/6pSWCTZ)
|
||||||
|
|
||||||
Super Graph gives you a high performance GraphQL API without you having to write any code. GraphQL is automatically compiled efficient an SQL query. Use it either as a library or a standalone service.
|
Super Graph gives you a high performance GraphQL API without you having to write any code. GraphQL is automagically compiled into an efficient SQL query. Use it either as a library or a standalone service.
|
||||||
|
|
||||||
## Using it as a service
|
## Using it as a service
|
||||||
|
|
||||||
|
@ -91,7 +91,6 @@ auth:
|
|||||||
# password: ""
|
# password: ""
|
||||||
# max_idle: 80
|
# max_idle: 80
|
||||||
# max_active: 12000
|
# max_active: 12000
|
||||||
|
|
||||||
# In most cases you don't need these
|
# In most cases you don't need these
|
||||||
# salt: "encrypted cookie"
|
# salt: "encrypted cookie"
|
||||||
# sign_salt: "signed encrypted cookie"
|
# sign_salt: "signed encrypted cookie"
|
||||||
@ -165,7 +164,6 @@ tables:
|
|||||||
- name: email
|
- name: email
|
||||||
related_to: products.name
|
related_to: products.name
|
||||||
|
|
||||||
|
|
||||||
roles_query: "SELECT * FROM users WHERE id = $user_id"
|
roles_query: "SELECT * FROM users WHERE id = $user_id"
|
||||||
|
|
||||||
roles:
|
roles:
|
||||||
@ -174,7 +172,7 @@ roles:
|
|||||||
- name: products
|
- name: products
|
||||||
query:
|
query:
|
||||||
limit: 10
|
limit: 10
|
||||||
columns: ["id", "name", "description" ]
|
columns: ["id", "name", "description"]
|
||||||
aggregation: false
|
aggregation: false
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
|
12
core/api.go
12
core/api.go
@ -210,3 +210,15 @@ func (sg *SuperGraph) GraphQL(c context.Context, query string, vars json.RawMess
|
|||||||
func (sg *SuperGraph) GraphQLSchema() (string, error) {
|
func (sg *SuperGraph) GraphQLSchema() (string, error) {
|
||||||
return sg.ge.Schema.String(), nil
|
return sg.ge.Schema.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Operation function return the operation type from the query. It uses a very fast algorithm to
|
||||||
|
// extract the operation without having to parse the query.
|
||||||
|
func Operation(query string) OpType {
|
||||||
|
return OpType(qcode.GetQType(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name function return the operation name from the query. It uses a very fast algorithm to
|
||||||
|
// extract the operation name without having to parse the query.
|
||||||
|
func Name(query string) string {
|
||||||
|
return allow.QueryName(query)
|
||||||
|
}
|
||||||
|
@ -61,6 +61,9 @@ type Config struct {
|
|||||||
// Inflections is to add additionally singular to plural mappings
|
// Inflections is to add additionally singular to plural mappings
|
||||||
// to the engine (eg. sheep: sheep)
|
// to the engine (eg. sheep: sheep)
|
||||||
Inflections map[string]string `mapstructure:"inflections"`
|
Inflections map[string]string `mapstructure:"inflections"`
|
||||||
|
|
||||||
|
// Database schema name. Defaults to 'public'
|
||||||
|
DBSchema string `mapstructure:"db_schema"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table struct defines a database table
|
// Table struct defines a database table
|
||||||
@ -103,7 +106,8 @@ type Role struct {
|
|||||||
|
|
||||||
// RoleTable struct contains role specific access control values for a database table
|
// RoleTable struct contains role specific access control values for a database table
|
||||||
type RoleTable struct {
|
type RoleTable struct {
|
||||||
Name string
|
Name string
|
||||||
|
ReadOnly *bool `mapstructure:"read_only"`
|
||||||
|
|
||||||
Query Query
|
Query Query
|
||||||
Insert Insert
|
Insert Insert
|
||||||
@ -117,7 +121,7 @@ type Query struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
DisableFunctions bool `mapstructure:"disable_functions"`
|
DisableFunctions bool `mapstructure:"disable_functions"`
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert struct contains access control values for insert operations
|
// Insert struct contains access control values for insert operations
|
||||||
@ -125,7 +129,7 @@ type Insert struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert struct contains access control values for update operations
|
// Insert struct contains access control values for update operations
|
||||||
@ -133,14 +137,14 @@ type Update struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete struct contains access control values for delete operations
|
// Delete struct contains access control values for delete operations
|
||||||
type Delete struct {
|
type Delete struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadInConfig function reads in the config file for the environment specified in the GO_ENV
|
// ReadInConfig function reads in the config file for the environment specified in the GO_ENV
|
||||||
|
19
core/core.go
19
core/core.go
@ -14,8 +14,10 @@ import (
|
|||||||
"github.com/valyala/fasttemplate"
|
"github.com/valyala/fasttemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OpType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OpQuery int = iota
|
OpQuery OpType = iota
|
||||||
OpMutation
|
OpMutation
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -56,16 +58,27 @@ type scontext struct {
|
|||||||
|
|
||||||
func (sg *SuperGraph) initCompilers() error {
|
func (sg *SuperGraph) initCompilers() error {
|
||||||
var err error
|
var err error
|
||||||
|
var schema string
|
||||||
|
|
||||||
|
if sg.conf.DBSchema == "" {
|
||||||
|
schema = "public"
|
||||||
|
} else {
|
||||||
|
schema = sg.conf.DBSchema
|
||||||
|
}
|
||||||
|
|
||||||
// If sg.di is not null then it's probably set
|
// If sg.di is not null then it's probably set
|
||||||
// for tests
|
// for tests
|
||||||
if sg.dbinfo == nil {
|
if sg.dbinfo == nil {
|
||||||
sg.dbinfo, err = psql.GetDBInfo(sg.db)
|
sg.dbinfo, err = psql.GetDBInfo(sg.db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(sg.dbinfo.Tables) == 0 {
|
||||||
|
return fmt.Errorf("no tables found in database (schema: %s)", schema)
|
||||||
|
}
|
||||||
|
|
||||||
if err = addTables(sg.conf, sg.dbinfo); err != nil {
|
if err = addTables(sg.conf, sg.dbinfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -334,7 +347,7 @@ func (c *scontext) executeRoleQuery(tx *sql.Tx) (string, error) {
|
|||||||
return role, nil
|
return role, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Result) Operation() int {
|
func (r *Result) Operation() OpType {
|
||||||
switch r.op {
|
switch r.op {
|
||||||
case qcode.QTQuery:
|
case qcode.QTQuery:
|
||||||
return OpQuery
|
return OpQuery
|
||||||
|
63
core/init.go
63
core/init.go
@ -216,53 +216,74 @@ func addRoles(c *Config, qc *qcode.Compiler) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addRole(qc *qcode.Compiler, r Role, t RoleTable) error {
|
func addRole(qc *qcode.Compiler, r Role, t RoleTable) error {
|
||||||
blockFilter := []string{"false"}
|
blocked := struct {
|
||||||
|
readOnly bool
|
||||||
|
query bool
|
||||||
|
insert bool
|
||||||
|
update bool
|
||||||
|
delete bool
|
||||||
|
}{true, true, true, true, true}
|
||||||
|
|
||||||
|
if r.Name == "anon" {
|
||||||
|
blocked.query = false
|
||||||
|
} else {
|
||||||
|
blocked.readOnly = false
|
||||||
|
blocked.query = false
|
||||||
|
blocked.insert = false
|
||||||
|
blocked.update = false
|
||||||
|
blocked.delete = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.ReadOnly != nil {
|
||||||
|
blocked.readOnly = *t.ReadOnly
|
||||||
|
}
|
||||||
|
if t.Query.Block != nil {
|
||||||
|
blocked.query = *t.Query.Block
|
||||||
|
}
|
||||||
|
if t.Insert.Block != nil {
|
||||||
|
blocked.insert = *t.Insert.Block
|
||||||
|
}
|
||||||
|
if t.Update.Block != nil {
|
||||||
|
blocked.update = *t.Update.Block
|
||||||
|
}
|
||||||
|
if t.Delete.Block != nil {
|
||||||
|
blocked.delete = *t.Delete.Block
|
||||||
|
}
|
||||||
|
|
||||||
query := qcode.QueryConfig{
|
query := qcode.QueryConfig{
|
||||||
Limit: t.Query.Limit,
|
Limit: t.Query.Limit,
|
||||||
Filters: t.Query.Filters,
|
Filters: t.Query.Filters,
|
||||||
Columns: t.Query.Columns,
|
Columns: t.Query.Columns,
|
||||||
DisableFunctions: t.Query.DisableFunctions,
|
DisableFunctions: t.Query.DisableFunctions,
|
||||||
}
|
Block: blocked.query,
|
||||||
|
|
||||||
if t.Query.Block {
|
|
||||||
query.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insert := qcode.InsertConfig{
|
insert := qcode.InsertConfig{
|
||||||
Filters: t.Insert.Filters,
|
Filters: t.Insert.Filters,
|
||||||
Columns: t.Insert.Columns,
|
Columns: t.Insert.Columns,
|
||||||
Presets: t.Insert.Presets,
|
Presets: t.Insert.Presets,
|
||||||
}
|
Block: blocked.insert,
|
||||||
|
|
||||||
if t.Insert.Block {
|
|
||||||
insert.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update := qcode.UpdateConfig{
|
update := qcode.UpdateConfig{
|
||||||
Filters: t.Update.Filters,
|
Filters: t.Update.Filters,
|
||||||
Columns: t.Update.Columns,
|
Columns: t.Update.Columns,
|
||||||
Presets: t.Update.Presets,
|
Presets: t.Update.Presets,
|
||||||
}
|
Block: blocked.update,
|
||||||
|
|
||||||
if t.Update.Block {
|
|
||||||
update.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete := qcode.DeleteConfig{
|
delete := qcode.DeleteConfig{
|
||||||
Filters: t.Delete.Filters,
|
Filters: t.Delete.Filters,
|
||||||
Columns: t.Delete.Columns,
|
Columns: t.Delete.Columns,
|
||||||
}
|
Block: blocked.delete,
|
||||||
|
|
||||||
if t.Delete.Block {
|
|
||||||
delete.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return qc.AddRole(r.Name, t.Name, qcode.TRConfig{
|
return qc.AddRole(r.Name, t.Name, qcode.TRConfig{
|
||||||
Query: query,
|
ReadOnly: blocked.readOnly,
|
||||||
Insert: insert,
|
Query: query,
|
||||||
Update: update,
|
Insert: insert,
|
||||||
Delete: delete,
|
Update: update,
|
||||||
|
Delete: delete,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/chirino/graphql/schema"
|
||||||
"github.com/dosco/super-graph/jsn"
|
"github.com/dosco/super-graph/jsn"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -140,6 +141,7 @@ func (al *List) Set(vars []byte, query, comment string) error {
|
|||||||
|
|
||||||
func (al *List) Load() ([]Item, error) {
|
func (al *List) Load() ([]Item, error) {
|
||||||
var list []Item
|
var list []Item
|
||||||
|
varString := "variables"
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(al.filepath)
|
b, err := ioutil.ReadFile(al.filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -180,9 +182,9 @@ func (al *List) Load() ([]Item, error) {
|
|||||||
s = e
|
s = e
|
||||||
}
|
}
|
||||||
ty = AL_QUERY
|
ty = AL_QUERY
|
||||||
} else if matchPrefix(b, e, "variables") {
|
} else if matchPrefix(b, e, varString) {
|
||||||
if c == 0 {
|
if c == 0 {
|
||||||
s = e + len("variables") + 1
|
s = e + len(varString) + 1
|
||||||
}
|
}
|
||||||
ty = AL_VARS
|
ty = AL_VARS
|
||||||
} else if b[e] == '{' {
|
} else if b[e] == '{' {
|
||||||
@ -234,7 +236,21 @@ func (al *List) Load() ([]Item, error) {
|
|||||||
func (al *List) save(item Item) error {
|
func (al *List) save(item Item) error {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
item.Name = QueryName(item.Query)
|
qd := &schema.QueryDocument{}
|
||||||
|
|
||||||
|
if err := qd.Parse(item.Query); err != nil {
|
||||||
|
fmt.Println("##", item.Query)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
qd.WriteTo(&buf)
|
||||||
|
query := buf.String()
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
// fmt.Println(">", query)
|
||||||
|
|
||||||
|
item.Name = QueryName(query)
|
||||||
item.key = strings.ToLower(item.Name)
|
item.key = strings.ToLower(item.Name)
|
||||||
|
|
||||||
if len(item.Name) == 0 {
|
if len(item.Name) == 0 {
|
||||||
|
@ -17,7 +17,7 @@ type DBInfo struct {
|
|||||||
colMap map[string]map[string]*DBColumn
|
colMap map[string]map[string]*DBColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
func GetDBInfo(db *sql.DB, schema string) (*DBInfo, error) {
|
||||||
di := &DBInfo{}
|
di := &DBInfo{}
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
@ -31,13 +31,13 @@ func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
di.Tables, err = GetTables(db)
|
di.Tables, err = GetTables(db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range di.Tables {
|
for _, t := range di.Tables {
|
||||||
cols, err := GetColumns(db, "public", t.Name)
|
cols, err := GetColumns(db, schema, t.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
|||||||
|
|
||||||
di.colMap = newColMap(di.Tables, di.Columns)
|
di.colMap = newColMap(di.Tables, di.Columns)
|
||||||
|
|
||||||
di.Functions, err = GetFunctions(db)
|
di.Functions, err = GetFunctions(db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ type DBTable struct {
|
|||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTables(db *sql.DB) ([]DBTable, error) {
|
func GetTables(db *sql.DB, schema string) ([]DBTable, error) {
|
||||||
sqlStmt := `
|
sqlStmt := `
|
||||||
SELECT
|
SELECT
|
||||||
c.relname as "name",
|
c.relname as "name",
|
||||||
@ -108,14 +108,12 @@ SELECT
|
|||||||
FROM pg_catalog.pg_class c
|
FROM pg_catalog.pg_class c
|
||||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||||
WHERE c.relkind IN ('r','v','m','f','')
|
WHERE c.relkind IN ('r','v','m','f','')
|
||||||
AND n.nspname <> ('pg_catalog')
|
AND n.nspname = $1
|
||||||
AND n.nspname <> ('information_schema')
|
AND pg_catalog.pg_table_is_visible(c.oid);`
|
||||||
AND n.nspname !~ ('^pg_toast')
|
|
||||||
AND pg_catalog.pg_table_is_visible(c.oid);`
|
|
||||||
|
|
||||||
var tables []DBTable
|
var tables []DBTable
|
||||||
|
|
||||||
rows, err := db.Query(sqlStmt)
|
rows, err := db.Query(sqlStmt, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error fetching tables: %s", err)
|
return nil, fmt.Errorf("Error fetching tables: %s", err)
|
||||||
}
|
}
|
||||||
@ -264,7 +262,7 @@ type DBFuncParam struct {
|
|||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFunctions(db *sql.DB) ([]DBFunction, error) {
|
func GetFunctions(db *sql.DB, schema string) ([]DBFunction, error) {
|
||||||
sqlStmt := `
|
sqlStmt := `
|
||||||
SELECT
|
SELECT
|
||||||
routines.routine_name,
|
routines.routine_name,
|
||||||
@ -278,11 +276,11 @@ RIGHT JOIN
|
|||||||
information_schema.parameters
|
information_schema.parameters
|
||||||
ON (routines.specific_name = parameters.specific_name and parameters.ordinal_position IS NOT NULL)
|
ON (routines.specific_name = parameters.specific_name and parameters.ordinal_position IS NOT NULL)
|
||||||
WHERE
|
WHERE
|
||||||
routines.specific_schema = 'public'
|
routines.specific_schema = $1
|
||||||
ORDER BY
|
ORDER BY
|
||||||
routines.routine_name, parameters.ordinal_position;`
|
routines.routine_name, parameters.ordinal_position;`
|
||||||
|
|
||||||
rows, err := db.Query(sqlStmt)
|
rows, err := db.Query(sqlStmt, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error fetching functions: %s", err)
|
return nil, fmt.Errorf("Error fetching functions: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -16,41 +16,46 @@ type QueryConfig struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
DisableFunctions bool
|
DisableFunctions bool
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type InsertConfig struct {
|
type InsertConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateConfig struct {
|
type UpdateConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteConfig struct {
|
type DeleteConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type TRConfig struct {
|
type TRConfig struct {
|
||||||
Query QueryConfig
|
ReadOnly bool
|
||||||
Insert InsertConfig
|
Query QueryConfig
|
||||||
Update UpdateConfig
|
Insert InsertConfig
|
||||||
Delete DeleteConfig
|
Update UpdateConfig
|
||||||
|
Delete DeleteConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type trval struct {
|
type trval struct {
|
||||||
query struct {
|
readOnly bool
|
||||||
|
query struct {
|
||||||
limit string
|
limit string
|
||||||
fil *Exp
|
fil *Exp
|
||||||
filNU bool
|
filNU bool
|
||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
disable struct {
|
disable struct{ funcs bool }
|
||||||
funcs bool
|
block bool
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insert struct {
|
insert struct {
|
||||||
@ -59,6 +64,7 @@ type trval struct {
|
|||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
psmap map[string]string
|
psmap map[string]string
|
||||||
pslist []string
|
pslist []string
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
update struct {
|
update struct {
|
||||||
@ -67,12 +73,14 @@ type trval struct {
|
|||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
psmap map[string]string
|
psmap map[string]string
|
||||||
pslist []string
|
pslist []string
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
delete struct {
|
delete struct {
|
||||||
fil *Exp
|
fil *Exp
|
||||||
filNU bool
|
filNU bool
|
||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ func NewFilter() *Exp {
|
|||||||
|
|
||||||
func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
||||||
var err error
|
var err error
|
||||||
trv := &trval{}
|
trv := &trval{readOnly: trc.ReadOnly}
|
||||||
|
|
||||||
// query config
|
// query config
|
||||||
trv.query.fil, trv.query.filNU, err = compileFilter(trc.Query.Filters)
|
trv.query.fil, trv.query.filNU, err = compileFilter(trc.Query.Filters)
|
||||||
@ -219,6 +219,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
}
|
}
|
||||||
trv.query.cols = listToMap(trc.Query.Columns)
|
trv.query.cols = listToMap(trc.Query.Columns)
|
||||||
trv.query.disable.funcs = trc.Query.DisableFunctions
|
trv.query.disable.funcs = trc.Query.DisableFunctions
|
||||||
|
trv.query.block = trc.Query.Block
|
||||||
|
|
||||||
// insert config
|
// insert config
|
||||||
trv.insert.fil, trv.insert.filNU, err = compileFilter(trc.Insert.Filters)
|
trv.insert.fil, trv.insert.filNU, err = compileFilter(trc.Insert.Filters)
|
||||||
@ -228,6 +229,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
trv.insert.cols = listToMap(trc.Insert.Columns)
|
trv.insert.cols = listToMap(trc.Insert.Columns)
|
||||||
trv.insert.psmap = parsePresets(trc.Insert.Presets)
|
trv.insert.psmap = parsePresets(trc.Insert.Presets)
|
||||||
trv.insert.pslist = mapToList(trv.insert.psmap)
|
trv.insert.pslist = mapToList(trv.insert.psmap)
|
||||||
|
trv.insert.block = trc.Insert.Block
|
||||||
|
|
||||||
// update config
|
// update config
|
||||||
trv.update.fil, trv.update.filNU, err = compileFilter(trc.Update.Filters)
|
trv.update.fil, trv.update.filNU, err = compileFilter(trc.Update.Filters)
|
||||||
@ -237,6 +239,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
trv.update.cols = listToMap(trc.Update.Columns)
|
trv.update.cols = listToMap(trc.Update.Columns)
|
||||||
trv.update.psmap = parsePresets(trc.Update.Presets)
|
trv.update.psmap = parsePresets(trc.Update.Presets)
|
||||||
trv.update.pslist = mapToList(trv.update.psmap)
|
trv.update.pslist = mapToList(trv.update.psmap)
|
||||||
|
trv.update.block = trc.Update.Block
|
||||||
|
|
||||||
// delete config
|
// delete config
|
||||||
trv.delete.fil, trv.delete.filNU, err = compileFilter(trc.Delete.Filters)
|
trv.delete.fil, trv.delete.filNU, err = compileFilter(trc.Delete.Filters)
|
||||||
@ -244,6 +247,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
trv.delete.cols = listToMap(trc.Delete.Columns)
|
trv.delete.cols = listToMap(trc.Delete.Columns)
|
||||||
|
trv.delete.block = trc.Delete.Block
|
||||||
|
|
||||||
singular := flect.Singularize(table)
|
singular := flect.Singularize(table)
|
||||||
plural := flect.Pluralize(table)
|
plural := flect.Pluralize(table)
|
||||||
@ -330,6 +334,28 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
|||||||
|
|
||||||
trv := com.getRole(role, field.Name)
|
trv := com.getRole(role, field.Name)
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case QTQuery:
|
||||||
|
if trv.query.block {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTInsert:
|
||||||
|
if trv.insert.block || trv.readOnly {
|
||||||
|
return fmt.Errorf("insert blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTUpdate:
|
||||||
|
if trv.update.block || trv.readOnly {
|
||||||
|
return fmt.Errorf("update blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTDelete:
|
||||||
|
if trv.delete.block || trv.readOnly {
|
||||||
|
return fmt.Errorf("delete blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
selects = append(selects, Select{
|
selects = append(selects, Select{
|
||||||
ID: id,
|
ID: id,
|
||||||
ParentID: parentID,
|
ParentID: parentID,
|
||||||
@ -946,6 +972,9 @@ func newExp(st *util.Stack, node *Node, usePool bool) (*Exp, error) {
|
|||||||
ex.Op = OpDistinct
|
ex.Op = OpDistinct
|
||||||
ex.Val = node.Val
|
ex.Val = node.Val
|
||||||
default:
|
default:
|
||||||
|
if len(node.Children) == 0 {
|
||||||
|
return nil, fmt.Errorf("[Where] invalid operation: %s", name)
|
||||||
|
}
|
||||||
pushChildren(st, node.exp, node)
|
pushChildren(st, node.exp, node)
|
||||||
return nil, nil // skip node
|
return nil, nil // skip node
|
||||||
}
|
}
|
||||||
@ -965,8 +994,9 @@ func newExp(st *util.Stack, node *Node, usePool bool) (*Exp, error) {
|
|||||||
case NodeVar:
|
case NodeVar:
|
||||||
ex.Type = ValVar
|
ex.Type = ValVar
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("[Where] valid values include string, int, float, boolean and list: %s", node.Type)
|
return nil, fmt.Errorf("[Where] invalid values for: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
setWhereColName(ex, node)
|
setWhereColName(ex, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,6 +1045,7 @@ func setWhereColName(ex *Exp, node *Node) {
|
|||||||
ex.Col = list[listlen-1]
|
ex.Col = list[listlen-1]
|
||||||
ex.NestedCols = list[:listlen]
|
ex.NestedCols = list[:listlen]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setOrderByColName(ob *OrderBy, node *Node) {
|
func setOrderByColName(ob *OrderBy, node *Node) {
|
||||||
|
@ -1,41 +1,40 @@
|
|||||||
0e384e19.bc97038f.js,1589756749060,098da569a72fb34a077f0e411b009ccdcc0e98c04a1a403a952bbea6a51aa195
|
01a106d5.06939d67.js,1589776216137,2e1ce67f6cf79a8a8e2070fc4ea4a6104ac73a5b26a1ab10b62f6cd8e45a8074
|
||||||
01a106d5.e6fa2a6a.js,1589756749060,7ee597df32dc6163edea35383043c7e5affb12525acb3250f92aa18157ab8e41
|
1.1c32171f.js.LICENSE.txt,1589776216144,31b4d50dbbd144da150dcdcf0ccef8f6cf8b6b5204d5c9adde3b24466777fad5
|
||||||
1.1c32171f.js.LICENSE.txt,1589756749064,31b4d50dbbd144da150dcdcf0ccef8f6cf8b6b5204d5c9adde3b24466777fad5
|
0e384e19.7f29b403.js,1589776216137,e2c3882226f2a601b65e4bb1fdb771296c1946f9f125c90af4a8f451dfd2c867
|
||||||
19.fdfbe826.js.LICENSE.txt,1589756749064,6ad95a8099127a8d42b5ace6d148064b1d3e922174f08d75d0ee2220ebeacd0b
|
19.fdfbe826.js.LICENSE.txt,1589776216145,6ad95a8099127a8d42b5ace6d148064b1d3e922174f08d75d0ee2220ebeacd0b
|
||||||
17896441.183211f5.js,1589756749060,7736db62d7498a8d3a10a617b1bdfac08c8f29dc03329f4ad3320f2571c223c0
|
17896441.183211f5.js,1589776216137,7736db62d7498a8d3a10a617b1bdfac08c8f29dc03329f4ad3320f2571c223c0
|
||||||
20ac7829.c04b4a1e.js,1589756749060,5b95f479848ccd6959630d4a24bd551d0dbc74457911e9b6f3498655bfaf8ea7
|
20ac7829.c04b4a1e.js,1589776216137,5b95f479848ccd6959630d4a24bd551d0dbc74457911e9b6f3498655bfaf8ea7
|
||||||
404.html,1589756750606,fe7e6a0f354000328576c9a2d8794d55dae6de0a9883e2f9dda7be4c91aa8f2a
|
1.1c32171f.js,1589776216137,5441b74bfad9f5a37ba0e6123621c73c3e3b9064bda6b9dcf62fdb7381bf8e41
|
||||||
1.1c32171f.js,1589756749061,5441b74bfad9f5a37ba0e6123621c73c3e3b9064bda6b9dcf62fdb7381bf8e41
|
2.8f12478f.js,1589776216137,3ac7ca0df8fca86145f5decbd86c8adfbc6b5b11a5be96fc96cc9bc33d6306e6
|
||||||
395f47e2.9ce46e61.js,1589756749060,fad9479ae57496cd96b3daf191197ec9899c9571bba4d35723a7a29e33468999
|
395f47e2.28d67f37.js,1589776216137,8a9b6bc2afdd99ca2b1827c8289352fab6163e30151b9701c29a7863b6cd00b6
|
||||||
2.8f12478f.js,1589756749061,3ac7ca0df8fca86145f5decbd86c8adfbc6b5b11a5be96fc96cc9bc33d6306e6
|
404.html,1589776218438,0a748eaa7614b1982623360ba8554c0f498b0796ead3cc429a2c84d287084b50
|
||||||
3d9c95a4.5f37b350.js,1589756749061,9458017327095622c54f0716951d83affe3149089f7dc56025627d979255bf43
|
3d9c95a4.c89589de.js,1589776216137,d5c45e5a3671f303683451d448e2e5d5b464f041cde683af6e824b9e7f951412
|
||||||
969d212d.82b6da9d.js,1589756749061,444b2a6c59ec2a0847279a4fed62b148c967fecae0b550433885f71ed5d9e13b
|
9225b3a9.a5e6036b.js,1589776216137,ec9a0d4b34d8751f74348d0da369625a18f320c9ed5ab3c5ccf047ead2551bd8
|
||||||
c4f5d8e4.47e70b85.js,1589756749064,6f986b48720724e7c8a715812b5f6625c71c8eca258bb4b410a447eb5da52734
|
741df2ae.e13b96b2.js,1589776216137,12028f0cbdf783ac91ea42db64d91190ebd4df24cc74162f953aacc75d16d078
|
||||||
741df2ae.162c25b8.js,1589756749061,8a68c30fa75945a2bff9899a3447003bcfc33f3b46111d37842e1802ad6d3fca
|
969d212d.9fc45877.js,1589776216138,8323c9f2db042bfaa2ebba43d9500bed881a694d0bfc27fd796cec95bb032dc5
|
||||||
9225b3a9.a07e65fb.js,1589756749061,5a6bb09b0b56b1d14c482dc1423e2eca5128a23fd54ff0fd261865543225d8cf
|
c4f5d8e4.47e70b85.js,1589776216145,6f986b48720724e7c8a715812b5f6625c71c8eca258bb4b410a447eb5da52734
|
||||||
index.html,1589756750606,43c17105a27007e3368d4275ec5fd617eea945b78868c43c73ba32f74184cb62
|
index.html,1589776218438,89f81ec3d3be439a827bd61448dcaddb71c33422df7baa88a7bbcdf784dbc0b2
|
||||||
main.f771ef31.js.LICENSE.txt,1589756749064,1d906c3b83eacffe298d21eeb73e6e73e96310983224783d236195098e6765a7
|
98ce8162.b5ace15d.js,1589776216137,935e1c6dd08f7e9d0d00221559b95f0f649e28ddf64be6bbb7b3e65bae1aba72
|
||||||
98ce8162.1704a8b8.js,1589756749061,d109a5c0b42fa7f7753dfe95fddeca8db1520956f724e90219be70d1e40c18f2
|
main.e30d99cd.js.LICENSE.txt,1589776216144,1d906c3b83eacffe298d21eeb73e6e73e96310983224783d236195098e6765a7
|
||||||
sitemap.xml,1589756750623,660ed269bf0306ba47ecdfb638e487147784d614c43c6c4a8e84194973baf183
|
runtime~main.366c29ad.js,1589776216145,0e550cc9522cd99c5fa4097c7db629eef56127a7f8ade0b7c9954cc8f6a01239
|
||||||
99e04881.2a79a052.js,1589756749064,8f5258dd347ac81b78c9837f762d9f247607011dd16553f34c2031c4ccbd38ea
|
5043549d.62508ecf.js,1589776216137,383959b80d2b0c6416e83c9640ea03c666fe92c407e13a6f022b58072feeafd2
|
||||||
runtime~main.82a8fb74.js,1589756749064,d921e2c431192f04f24dd17747b3f87ddc673c8ad16fd59a769dae8c1a37e23b
|
99e04881.197dcef6.js,1589776216144,af99883cbd4d58fbac7cbf814be33032b77bc8daf856aed54bdf0bf27ed5708d
|
||||||
5043549d.cb3b9121.js,1589756749061,3e19828fe02c125eff01c388067ee2d817bdc6f963c063ff7d1be9fba440f658
|
sitemap.xml,1589776218455,660ed269bf0306ba47ecdfb638e487147784d614c43c6c4a8e84194973baf183
|
||||||
styles.9155f1d2.js,1589756749060,f1e0863928710e67338dc88c37f47ef3ff164d36c4bba40d005561094c9c3284
|
styles.9155f1d2.js,1589776216137,f1e0863928710e67338dc88c37f47ef3ff164d36c4bba40d005561094c9c3284
|
||||||
db32d859.d7e74c54.js,1589756749064,e800ed98ca5b6a8dcb800e1b8fd8fe57564e22a41899181f07147ae08a153f24
|
db32d859.a032827a.js,1589776216145,36d575ffad747898726a97cb7a3551e636f744218595bea5c060536eb8d8390f
|
||||||
docs/advanced/index.html,1589756750609,9f7260c581cb4e71c46896af29c537e0fb02fac3228d4a991435bdf995f542e8
|
docs/advanced/index.html,1589776218439,31171870786a597597de9417978a27253581c013962e39959ae4c0777bf86c28
|
||||||
docs/deploy/index.html,1589756750609,555db8271ebd923ff2ffebe51ade18aa2f7f78650bd9d358fdcd8fb2eecd8de3
|
docs/deploy/index.html,1589776218440,7a4735edb93006311b704e62b843bf89bc4354fdf0fdc22a0c5802e39878c193
|
||||||
docs/home/index.html,1589756750609,5b095aec72d5e0a50aac298598c1b27964656d67db94097dc1c8e0bfac4c59b9
|
docs/home/index.html,1589776218440,c7fbb0c1084c6ef8858775c5083b6b416b8188942d4402a5a625eadb3bc00942
|
||||||
docs/react/index.html,1589756750609,bea10eea368d0ae5848e4dd34ccd0215b1fef58940768dd2d9c8fad246aee172
|
docs/intro/index.html,1589776218440,c7a50ae98c0b279f422e55c2eeb9f7ba1c7c1a8bcac07be11fd6e05ced224094
|
||||||
img/super-graph-logo.svg,1589756750606,648bfe286ee36b88ad9accf8cda7eb016c8fe3c0aa7fe6777856ac1e2dac9b32
|
img/super-graph-logo.svg,1589776218438,66a865c4936f44ea811464b967f221b615b7553e85dca0d6f1ef620da3911857
|
||||||
docs/intro/index.html,1589756750609,f9eefab7ad7aefec779dc43f2ee17df1cb5c1edd8878e723bf3c136c18468f9a
|
docs/react/index.html,1589776218440,f76fc976f3491d9aacf19ce3b34bee1339f87c673a9da95f192683615618f210
|
||||||
docs/why/index.html,1589756750609,7e4ecb00fc6fb663f826e424c3f09727fbafa5323e1de71ea178946a9584eae2
|
docs/why/index.html,1589776218440,4aa380fe4e5d8476645e368d1f708d5d1344331c572383db823c3499fa0c99cc
|
||||||
docs/security/index.html,1589756750609,a612631d3364369d079780ed377b84d1570a15233ab4ed66392ffc7248eaf4fa
|
docs/security/index.html,1589776218440,0c7d466dc143935db8c02a448952cae2465635e4b6782b1682449bbd56807917
|
||||||
styles.8ee0cad4.css,1589756749060,34b2e79c5c5b1f7afda4376e422e8ccb2c3c04213ca09d788f0c68ecf153d6e6
|
styles.8ee0cad4.css,1589776216137,34b2e79c5c5b1f7afda4376e422e8ccb2c3c04213ca09d788f0c68ecf153d6e6
|
||||||
docs/config/index.html,1589756750609,964692badbdd80f41ab481b4753046ec17583692b57843becadb18c84bc5fa52
|
docs/config/index.html,1589776218440,25b6e87a42c163ac966e80acebca8708f56ae95ba8f3ed8b98ff7fd70ca5a222
|
||||||
docs/start/index.html,1589756750609,8b6da7abe0dc0bacb97c6ba04e9b63d0de47c7d8c7db51b1b1d03c3fad740043
|
docs/internals/index.html,1589776218440,b6f2136a1c832f421a46329fb1f39269d820c55a0dfc9351848271a5501d8e6e
|
||||||
img/favicon.png,1589756750610,1a9ddda9df7e965340c2b5fdfc9b1f76ec11c2fcc800ec7908ca8827f3c95741
|
docs/start/index.html,1589776218440,485ec2c61117d8940d8028f34d51d421995a814d5b9d4d5a1870adaed48aec2c
|
||||||
docs/internals/index.html,1589756750607,d69ff057c545f868959dc8d54c577947d6c25ea982d992d377646eaffbef255c
|
docs/graphql/index.html,1589776218440,3bd79f703fe67656884f3121bfddc3a4fc4d9e5bb2bf9271c94014058fbbd806
|
||||||
docs/graphql/index.html,1589756750609,f8c7f0f5d5566eca1f8ae39b941aee0ed82adc52ce50dc922982de8d02d2a59a
|
main.e30d99cd.js,1589776216144,98a4087d6f537aaddbc1225aaabfb4d12d1394772deb618d4d457685cee59311
|
||||||
main.f771ef31.js,1589756749064,2dcb5a6634b787512f51a25f69f7f862f027548def31c5c79894ffff7375c59a
|
19.fdfbe826.js,1589776216144,b8abb73aea5fc0aa50d7e8b8bd38984e3b3aec62de2faf66fb3e55fd1428f8a7
|
||||||
19.fdfbe826.js,1589756749064,b8abb73aea5fc0aa50d7e8b8bd38984e3b3aec62de2faf66fb3e55fd1428f8a7
|
server.bundle.js,1589776218438,826db37f1de931e8b088c1ff20b4a3c2fe0c3d54d9ff4020e500f0df1b83a616
|
||||||
server.bundle.js,1589756750606,aceff68a47f9236060259eca732a163a2e660e59f43195289cafba2abd244165
|
|
||||||
|
@ -1,21 +1,45 @@
|
|||||||
---
|
---
|
||||||
id: home
|
id: home
|
||||||
title: Super Graph
|
title: Super Graph
|
||||||
|
hide_title: true
|
||||||
sidebar_label: Home
|
sidebar_label: Home
|
||||||
---
|
---
|
||||||
|
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl'; // Add to the top of the file below the front matter.
|
import useBaseUrl from '@docusaurus/useBaseUrl'; // Add to the top of the file below the front matter.
|
||||||
|
|
||||||
<img alt="Super Graph Logo" src={useBaseUrl('img/super-graph-logo.svg')} height="60" />;
|
<div class="hero shadow--lw margin-bottom--lg">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col--2">
|
||||||
|
<img
|
||||||
|
class="avatar__photo avatar__photo--xl"
|
||||||
|
alt="Super Graph Logo"
|
||||||
|
src={useBaseUrl('img/super-graph-logo.svg')}
|
||||||
|
height="70"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col col--10"><h1 class="hero__title">Super Graph</h1></div>
|
||||||
|
</div>
|
||||||
|
<p class="hero__subtitle">Fetch data without code!</p>
|
||||||
|
<div class="margin-bottom--lg">
|
||||||
|
<a class="button button--secondary button--outline button--lg" href="start">
|
||||||
|
Skip Intro
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p>Stop fighting ORM's and complex SQL just to fetch the data you need. Instead try Super Graph it automagically tranforms GraphQL into efficient SQL.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
## Fetch data without code!
|
:::info cut development time
|
||||||
|
|
||||||
### Stop strugging with ORM's and complex SQL just to fetch the data you need. Instead try asking nicely with GraphQL.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
80% of all web app development is either reading from or writing to a database. 100x your developer productivity and save valuable time by making that super simple.
|
80% of all web app development is either reading from or writing to a database. 100x your developer productivity and save valuable time by making that super simple.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Fetching data with GraphQL
|
||||||
|
|
||||||
|
Just imagine the code or SQL you'll need to fetch this data, the user, all his posts, all the votes on the posts, the authors information and the related tags. Oh yeah and you also need efficient cursor based pagination. And Remember you also need to maintain this code forever.
|
||||||
|
|
||||||
|
Instead just describe the data you need in GraphQL and give that to Super Graph it'll automatically learn your database and generate the most efficient SQL query fetching your data in the JSON structure you expected.
|
||||||
|
|
||||||
```graphql
|
```graphql
|
||||||
query {
|
query {
|
||||||
user(id: 5) {
|
user(id: 5) {
|
||||||
@ -45,7 +69,10 @@ query {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Super Graph automatially compiles your GraphQL into an efficient SQL query giving you the results you wanted.
|
### Instant results
|
||||||
|
|
||||||
|
Here's the data Super Graph fetched using the GraphQL above, it's even in the JSON structure you
|
||||||
|
wanted it in. All this without you writing any code or SQL.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -77,6 +104,8 @@ query {
|
|||||||
"created_at": "2020-05-13T13:51:21.729501+00:00"
|
"created_at": "2020-05-13T13:51:21.729501+00:00"
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
|
],
|
||||||
|
"posts_cursor": "a8d4j2k9d83dy373hd2nskw2sjs8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -3,7 +3,7 @@ module.exports = {
|
|||||||
tagline: "Fetch data without code",
|
tagline: "Fetch data without code",
|
||||||
url: "https://supergraph.dev",
|
url: "https://supergraph.dev",
|
||||||
baseUrl: "/",
|
baseUrl: "/",
|
||||||
favicon: "img/favicon.svg",
|
favicon: "img/super-graph-logo.svg",
|
||||||
organizationName: "dosco", // Usually your GitHub org/user name.
|
organizationName: "dosco", // Usually your GitHub org/user name.
|
||||||
projectName: "super-graph", // Usually your repo name.
|
projectName: "super-graph", // Usually your repo name.
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
@ -11,7 +11,7 @@ module.exports = {
|
|||||||
title: "Super Graph",
|
title: "Super Graph",
|
||||||
logo: {
|
logo: {
|
||||||
alt: "Super Graph Logo",
|
alt: "Super Graph Logo",
|
||||||
src: "img/favicon.png",
|
src: "img/super-graph-logo.svg",
|
||||||
},
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
@ -56,13 +56,13 @@ module.exports = {
|
|||||||
sidebarPath: require.resolve("./sidebars.js"),
|
sidebarPath: require.resolve("./sidebars.js"),
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl:
|
||||||
"https://github.com/facebook/docusaurus/edit/master/website/",
|
"https://github.com/dosco/super-graph/edit/master/docs/website",
|
||||||
},
|
},
|
||||||
blog: {
|
blog: {
|
||||||
showReadingTime: true,
|
showReadingTime: true,
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl:
|
||||||
"https://github.com/facebook/docusaurus/edit/master/website/blog/",
|
"https://github.com/dosco/super-graph/edit/master/docs/website",
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve("./src/css/custom.css"),
|
customCss: require.resolve("./src/css/custom.css"),
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
@ -2,7 +2,7 @@
|
|||||||
<svg width="378px" height="314px" viewBox="0 0 378 314" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="378px" height="314px" viewBox="0 0 378 314" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>battery-technology-svgrepo-com</title>
|
<title>battery-technology-svgrepo-com</title>
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="battery-technology-svgrepo-com" fill="#000000" fill-rule="nonzero">
|
<g id="battery-technology-svgrepo-com" fill="#444AA9" fill-rule="nonzero">
|
||||||
<path d="M234,269.076 L210,269.076 C196.8,269.076 186,258.276 186,245.076 L186,69.076 C186,55.876 196.8,45.076 210,45.076 L370,45.076 C374.4,45.076 378,41.476 378,37.076 C378,32.676 374.4,29.076 370,29.076 L210,29.076 C188,29.076 170,47.076 170,69.076 L170,245.076 C170,267.076 188,285.076 210,285.076 L234,285.076 C238.4,285.076 242,281.476 242,277.076 C242,272.676 238.4,269.076 234,269.076 Z" id="Path" transform="translate(274.000000, 157.076000) scale(-1, -1) translate(-274.000000, -157.076000) "></path>
|
<path d="M234,269.076 L210,269.076 C196.8,269.076 186,258.276 186,245.076 L186,69.076 C186,55.876 196.8,45.076 210,45.076 L370,45.076 C374.4,45.076 378,41.476 378,37.076 C378,32.676 374.4,29.076 370,29.076 L210,29.076 C188,29.076 170,47.076 170,69.076 L170,245.076 C170,267.076 188,285.076 210,285.076 L234,285.076 C238.4,285.076 242,281.476 242,277.076 C242,272.676 238.4,269.076 234,269.076 Z" id="Path" transform="translate(274.000000, 157.076000) scale(-1, -1) translate(-274.000000, -157.076000) "></path>
|
||||||
<path d="M64,269.076 L40,269.076 C26.8,269.076 16,258.276 16,245.076 L16,69.076 C16,55.876 26.8,45.076 40,45.076 L200,45.076 C204.4,45.076 208,41.476 208,37.076 C208,32.676 204.4,29.076 200,29.076 L40,29.076 C18,29.076 0,47.076 0,69.076 L0,245.076 C0,267.076 18,285.076 40,285.076 L64,285.076 C68.4,285.076 72,281.476 72,277.076 C72,272.676 68.4,269.076 64,269.076 Z" id="Path"></path>
|
<path d="M64,269.076 L40,269.076 C26.8,269.076 16,258.276 16,245.076 L16,69.076 C16,55.876 26.8,45.076 40,45.076 L200,45.076 C204.4,45.076 208,41.476 208,37.076 C208,32.676 204.4,29.076 200,29.076 L40,29.076 C18,29.076 0,47.076 0,69.076 L0,245.076 C0,267.076 18,285.076 40,285.076 L64,285.076 C68.4,285.076 72,281.476 72,277.076 C72,272.676 68.4,269.076 64,269.076 Z" id="Path"></path>
|
||||||
<path d="M196,269.076 L184,269.076 C179.6,269.076 176,272.676 176,277.076 C176,281.476 179.6,285.076 184,285.076 L196,285.076 C200.4,285.076 204,281.476 204,277.076 C204,272.676 200.4,269.076 196,269.076 Z" id="Path"></path>
|
<path d="M196,269.076 L184,269.076 C179.6,269.076 176,272.676 176,277.076 C176,281.476 179.6,285.076 184,285.076 L196,285.076 C200.4,285.076 204,281.476 204,277.076 C204,272.676 200.4,269.076 196,269.076 Z" id="Path"></path>
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@ -45,6 +45,16 @@ func initConf() (*Config, error) {
|
|||||||
logLevel = LogLevelNone
|
logLevel = LogLevelNone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy over db_schema from the core config
|
||||||
|
if c.DB.Schema == "" {
|
||||||
|
c.DB.Schema = c.DBSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default database schema
|
||||||
|
if c.DB.Schema == "" {
|
||||||
|
c.DB.Schema = "public"
|
||||||
|
}
|
||||||
|
|
||||||
// Auths: validate and sanitize
|
// Auths: validate and sanitize
|
||||||
am := make(map[string]struct{})
|
am := make(map[string]struct{})
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user