tests

package module
v3.0.38 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2024 License: Apache-2.0 Imports: 0 Imported by: 0

Documentation

Overview

Package tests holds examples and integration tests for all of Graphjin including the standalone service `serv` github.com/dosco/serv/v3 and the core compiler `core` github.com/dosco/core/v3

Example (Insert)
gql := `mutation {
		users(insert: {
			id: $id,
			email: $email,
			full_name: $fullName,
			stripe_id: $stripeID,
			category_counts: $categoryCounts
		}) {
			id
			email
		}
	}`

vars := json.RawMessage(`{
		"id": 1001,
		"email": "user1001@test.com",
		"fullName": "User 1001",
		"stripeID": "payment_id_1001",
		"categoryCounts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1001@test.com","id":1001}]}
Example (InsertBulk)
gql := `mutation {
		users(insert: $data) {
			id
			email
		}
	}`

vars := json.RawMessage(`{
		"data": [{
			"id": 1002,
			"email": "user1002@test.com",
			"full_name": "User 1002",
			"stripe_id": "payment_id_1002",
			"category_counts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}]
		},
		{
			"id": 1003,
			"email": "user1003@test.com",
			"full_name": "User 1003",
			"stripe_id": "payment_id_1003",
			"category_counts": [{"category_id": 2, "count": 400},{"category_id": 3, "count": 600}]
		}]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1002@test.com","id":1002},{"email":"user1003@test.com","id":1003}]}
Example (InsertInlineBulk)
gql := `mutation {
		users(insert: [
			{id: $id1, email: $email1, full_name: $full_name1},
			{id:, $id2, email: $email2, full_name: $full_name2}]) {
			id
			email
		}
	}`

vars := json.RawMessage(`{
		"id1": 1008,
		"email1": "one@test.com",
		"full_name1": "John One",
		"id2": 1009,
		"email2":  "two@test.com",
		"full_name2": "John Two"
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"two@test.com","id":1009},{"email":"one@test.com","id":1008}]}
Example (InsertInlineWithValidation)
gql := `mutation 
		@constraint(variable: "email", format: "email", min: 1, max: 100)
		@constraint(variable: "full_name", requiredIf: { id: 1007 } ) 
		@constraint(variable: "id", greaterThan:1006  ) 
		@constraint(variable: "id", lessThanOrEqualsField:id  ) {
		users(insert: { id: $id, email: $email, full_name: $full_name }) {
			id
			email
			full_name
		}
	}`

vars := json.RawMessage(`{
		"id": 1007,
		"email": "not_an_email"
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
	for _, e := range res.Validation {
		fmt.Println(e.Constraint, e.FieldName)
	}
} else {
	printJSON(res.Data)
}
// Ordered output:
// validation failed
// format email
// min email
// max email
// requiredIf full_name
Example (InsertIntoMultipleRelatedTables)
gql := `mutation {
		purchases(insert: $data) {
			quantity
			customer {
				id
				full_name
				email
			}
			product {
				id
				name
				price
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 3001,
			"quantity": 5,
			"customer": {
				"id": 1004,
				"email": "user1004@test.com",
				"full_name": "User 1004",
				"stripe_id": "payment_id_1004",
				"category_counts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}]
			},
			"product": {
				"id": 2002,
				"name": "Product 2002",
				"description": "Description for product 2002",
				"price": 2012.5,
				"tags": ["Tag 1", "Tag 2"],
				"category_ids": [1, 2, 3, 4, 5],
				"owner_id": 3
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"purchases":[{"customer":{"email":"user1004@test.com","full_name":"User 1004","id":1004},"product":{"id":2002,"name":"Product 2002","price":2012.5},"quantity":5}]}
Example (InsertIntoRecursiveRelationship)
gql := `mutation {
		comments(insert: $data, where: { id: { in: [5001, 5002] }}) {
			id
			reply_to_id
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 5001,
			"body": "Comment body 5001",
			"created_at": "now",
			"comments": {
				"find": "children",
				"id": 5002,
				"body": "Comment body 5002",
				"created_at": "now"	
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":[{"id":5001,"reply_to_id":null},{"id":5002,"reply_to_id":5001}]}
Example (InsertIntoRecursiveRelationshipAndConnectTable1)
gql := `mutation {
		comments(insert: $data, where: { id: { in: [5, 5003] }}) {
			id
			reply_to_id
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 5003,
			"body": "Comment body 5003",
			"created_at": "now",
			"comments": {
				"find": "children",
				"connect": { "id": 5 }
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":[{"id":5003,"reply_to_id":null},{"id":5,"reply_to_id":5003}]}
Example (InsertIntoRecursiveRelationshipAndConnectTable2)
gql := `mutation {
  	comments(insert: $data) @object {
			id
			product {
				id
			}
			commenter {
				id
			}
			comments(find: "children") {
				id
			}
  	}
  }`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

vars := json.RawMessage(`{
			"data": {
				"id":  5004,
				"body": "Comment body 5004",
				"created_at": "now",
				"comments": {
					"connect": { "id": 6 },
					"find": "children"
				},
				"product": {
					"connect": { "id": 26 }
				},
				"commenter":{
					"connect":{ "id": 3 }
				}
			}
		}`)

ctx := context.WithValue(context.Background(), core.UserIDKey, 50)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":{"commenter":{"id":3},"comments":[{"id":6}],"id":5004,"product":{"id":26}}}
Example (InsertIntoTableAndConnectToRelatedTableWithArrayColumn)
gql := `mutation {
		products(insert: $data) {
			id
			name
			categories {
				id
				name
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 2006,
			"name": "Product 2006",
			"description": "Description for product 2006",
			"price": 2016.5,
			"tags": ["Tag 1", "Tag 2"],
			"categories": {
				"connect": { "id": [1, 2, 3, 4, 5] }
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Tables = []core.Table{
	{Name: "products", Columns: []core.Column{{Name: "category_ids", ForeignKey: "categories.id"}}},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"},{"id":3,"name":"Category 3"},{"id":4,"name":"Category 4"},{"id":5,"name":"Category 5"}],"id":2006,"name":"Product 2006"}]}
Example (InsertIntoTableAndConnectToRelatedTables)
gql := `mutation {
		products(insert: $data) {
			id
			name
			owner {
				id
				full_name
				email
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 2005,
			"name": "Product 2005",
			"description": "Description for product 2005",
			"price": 2015.5,
			"tags": ["Tag 1", "Tag 2"],
			"category_ids": [1, 2, 3, 4, 5],
			"owner": {
				"connect": { "id": 6 }
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":2005,"name":"Product 2005","owner":{"email":"user6@test.com","full_name":"User 6","id":6}}]}
Example (InsertIntoTableAndRelatedTable1)
gql := `mutation {
		users(insert: $data) {
			id
			full_name
			email
			products {
				id
				name
				price
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 1005,
			"email": "user1005@test.com",
			"full_name": "User 1005",
			"stripe_id": "payment_id_1005",
			"category_counts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}],
			"products": {
				"id": 2003,
				"name": "Product 2003",
				"description": "Description for product 2003",
				"price": 2013.5,
				"tags": ["Tag 1", "Tag 2"],
				"category_ids": [1, 2, 3, 4, 5],
				"owner_id": 3
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1005@test.com","full_name":"User 1005","id":1005,"products":[{"id":2003,"name":"Product 2003","price":2013.5}]}]}
Example (InsertIntoTableAndRelatedTable2)
gql := `mutation {
		products(insert: $data) {
			id
			name
			owner {
				id
				full_name
				email
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 2004,
			"name": "Product 2004",
			"description": "Description for product 2004",
			"price": 2014.5,
			"tags": ["Tag 1", "Tag 2"],
			"category_ids": [1, 2, 3, 4, 5],
			"owner": {
				"id": 1006,
				"email": "user1006@test.com",
				"full_name": "User 1006",
				"stripe_id": "payment_id_1006",
				"category_counts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}]
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":2004,"name":"Product 2004","owner":{"email":"user1006@test.com","full_name":"User 1006","id":1006}}]}
Example (InsertIntoTableBulkInsertIntoRelatedTable)
gql := `mutation {
		users(insert: $data) {
			id
			full_name
			email
			products {
				id
				name
				price
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 10051,
			"email": "user10051@test.com",
			"full_name": "User 10051",
			"stripe_id": "payment_id_10051",
			"category_counts": [
				{"category_id": 1, "count": 400},
				{"category_id": 2, "count": 600}
			],
			"products": [
				{
					"id": 20031,
					"name": "Product 20031",
					"description": "Description for product 20031",
					"price": 2013.5,
					"tags": ["Tag 1", "Tag 2"],
					"category_ids": [1, 2, 3, 4, 5],
					"owner_id": 3
				},
				{
					"id": 20032,
					"name": "Product 20032",
					"description": "Description for product 20032",
					"price": 2014.5,
					"tags": ["Tag 1", "Tag 2"],
					"category_ids": [1, 2, 3, 4, 5],
					"owner_id": 3
				}
			]
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user10051@test.com","full_name":"User 10051","id":10051,"products":[{"id":20031,"name":"Product 20031","price":2013.5},{"id":20032,"name":"Product 20032","price":2014.5}]}]}
Example (InsertWithCamelToSnakeCase)
gql := `mutation {
		products(insert: $data) {
			id
			name
			owner {
				id
				email
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 2007,
			"name": "Product 2007",
			"description": "Description for product 2007",
			"price": 2011.5,
			"tags": ["Tag 1", "Tag 2"],
			"categoryIds": [1, 2, 3, 4, 5]
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, EnableCamelcase: true})
err := conf.AddRoleTable("user", "products", core.Insert{
	Presets: map[string]string{"ownerId": "$user_id"},
})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":2007,"name":"Product 2007","owner":{"email":"user3@test.com","id":3}}]}
Example (InsertWithPresets)
gql := `mutation {
		products(insert: $data) {
			id
			name
			owner {
				id
				email
			}
		}
	}`

vars := json.RawMessage(`{
		"data": {
			"id": 2001,
			"name": "Product 2001",
			"description": "Description for product 2001",
			"price": 2011.5,
			"tags": ["Tag 1", "Tag 2"],
			"category_ids": [1, 2, 3, 4, 5]
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
err := conf.AddRoleTable("user", "products", core.Insert{
	Presets: map[string]string{"owner_id": "$user_id"},
})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":2001,"name":"Product 2001","owner":{"email":"user3@test.com","id":3}}]}
Example (InsertWithTransaction)
gql := `mutation {
		users(insert: {
			id: $id,
			email: $email,
			full_name: $fullName,
			stripe_id: $stripeID,
			category_counts: $categoryCounts
		}) {
			id
			email
		}
	}`

vars := json.RawMessage(`{
		"id": 1007,
		"email": "user1007@test.com",
		"fullName": "User 1007",
		"stripeID": "payment_id_1007",
		"categoryCounts": [{"category_id": 1, "count": 400},{"category_id": 2, "count": 600}]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

c := context.Background()
tx, err := db.BeginTx(c, nil)
if err != nil {
	panic(err)
}
defer tx.Rollback() //nolint:errcheck

c = context.WithValue(c, core.UserIDKey, 3)
res, err := gj.GraphQLTx(c, tx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
	return
}
if err := tx.Commit(); err != nil {
	panic(err)
}
printJSON(res.Data)
Output:

{"users":[{"email":"user1007@test.com","id":1007}]}
Example (Query)
gql := `
	query {
		products(limit: 3) {
			id
			count_likes,
			owner {
				id
				fullName: full_name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"count_likes":null,"id":1,"owner":{"fullName":"User 1","id":1}},{"count_likes":null,"id":2,"owner":{"fullName":"User 2","id":2}},{"count_likes":null,"id":3,"owner":{"fullName":"User 3","id":3}}]}
Example (QueryBlockWithRoles)
gql := `query {
		users {
			id
			full_name
			email
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.RolesQuery = `SELECT * FROM users WHERE id = $user_id`
conf.Roles = []core.Role{{Name: "disabled_user", Match: "disabled = true"}}

err := conf.AddRoleTable("disabled_user", "users", core.Query{Block: true})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 50)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":null}
Example (QueryByID)
gql := `query {
		products(id: $id) {
			id
			name
		}
	}`

vars := json.RawMessage(`{
		"id": 2
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":2,"name":"Product 2"}}
Example (QueryBySearch)
gql := `query {
		products(search: $query, limit: 5) {
			id
			name
		}
	}`

vars := json.RawMessage(`{
		"query": "\"Product 3\""
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":3,"name":"Product 3"}]}
Example (QueryChildrenWithParent)
gql := `query {
		products(limit: 2) {
			name
			price
			owner {
				email
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"name":"Product 1","owner":{"email":"user1@test.com"},"price":11.5},{"name":"Product 2","owner":{"email":"user2@test.com"},"price":12.5}]}
Example (QueryInTransaction)
gql := `
	query {
		products(limit: 3) {
			id
			owner {
				id
				fullName: full_name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

c := context.Background()
tx, err := db.BeginTx(c, nil)
if err != nil {
	panic(err)
}
defer tx.Rollback() //nolint:errcheck

res, err := gj.GraphQLTx(c, tx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
	return
}
if err := tx.Commit(); err != nil {
	panic(err)
}
printJSON(res.Data)
Output:

{"products":[{"id":1,"owner":{"fullName":"User 1","id":1}},{"id":2,"owner":{"fullName":"User 2","id":2}},{"id":3,"owner":{"fullName":"User 3","id":3}}]}
Example (QueryManyToManyViaJoinTable1)
gql := `query {
		products(limit: 2) {
			name
			customer {
				email
			}
			owner {
				email
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"customer":[{"email":"user2@test.com"}],"name":"Product 1","owner":{"email":"user1@test.com"}},{"customer":[{"email":"user3@test.com"}],"name":"Product 2","owner":{"email":"user2@test.com"}}]}
Example (QueryManyToManyViaJoinTable2)
gql := `query {
		users {
			email
			full_name
			products {
				name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","full_name":"User 1","products":[{"name":"Product 1"}]},{"email":"user2@test.com","full_name":"User 2","products":[{"name":"Product 2"}]}]}
Example (QueryManyToManyViaJoinTable3)
gql := `
	query {
		graph_node {
			id
			dst_node  {
				id
			}
			src_node {
				id
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"graph_node":[{"dst_node":[{"id":"b"},{"id":"c"}],"id":"a","src_node":[]},{"dst_node":[],"id":"b","src_node":[{"id":"a"}]}]}
Example (QueryParentAndChildrenViaArrayColumn)
gql := `
	query {
		products(limit: 2) {
			name
			price
			categories {
				id
				name
			}
		}
		categories {
			name
			products {
				name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
conf.Tables = []core.Table{
	{
		Name: "products",
		Columns: []core.Column{
			{Name: "category_ids", ForeignKey: "categories.id", Array: true},
		},
	},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"categories":[{"name":"Category 1","products":[{"name":"Product 1"},{"name":"Product 2"}]},{"name":"Category 2","products":[{"name":"Product 1"},{"name":"Product 2"}]}],"products":[{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"name":"Product 1","price":11.5},{"categories":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"name":"Product 2","price":12.5}]}
Example (QueryParentsWithChildren)
gql := `query {
		users(order_by: { id: asc }, limit: 2) {
			email
			products {
				name
				price
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","products":[{"name":"Product 1","price":11.5}]},{"email":"user2@test.com","products":[{"name":"Product 2","price":12.5}]}]}
Example (QueryWithAddAndRemoveDirective1)
gql := `
	query {
		products(limit: 2, order_by: { id: asc }) @add(ifRole: "user") {
			id
			name
		}
		users(limit: 3, order_by: { id: asc }) @remove(ifRole: "user") {
			id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithAddAndRemoveDirective2)
gql := `
	query {
		products(limit: 2, order_by: { id: asc })  {
			id 
			name @add(ifRole: "user")
		}
		users(limit: 3, order_by: { id: asc })  {
			id @remove(ifRole: "anon")
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2}],"users":[{},{},{}]}
Example (QueryWithAggregation)
gql := `query {
		products(where: { id: { lteq: 100 } }) {
			count_id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"count_id":100}]}
Example (QueryWithAggregationBlockedColumn)
gql := `query {
		products {
			sum_price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
err := conf.AddRoleTable("anon", "products", core.Query{
	Columns: []string{"id", "name"},
})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

db column blocked: price (role: 'anon')
Example (QueryWithAlternateFieldNames)
gql := `query {
		comments(limit: 2) {
			id
			commenter {
				email
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":[{"commenter":{"email":"user1@test.com"},"id":1},{"commenter":{"email":"user2@test.com"},"id":2}]}
Example (QueryWithCamelToSnakeCase)
gql := `query {
		hotProducts(where: { productID: { eq: 55 } }, order_by: { productID: desc }) {
			countryCode
			countProductID
			products {
				id
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, EnableCamelcase: true})
conf.Tables = []core.Table{
	{
		Name: "hot_products",
		Columns: []core.Column{
			{Name: "product_id", Type: "int", ForeignKey: "products.id"},
		},
	},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"hotProducts":[{"countProductID":1,"countryCode":"US","products":{"id":55}}]}
Example (QueryWithCursorPagination1)
gql := `query {
		products(
			where: { id: { lesser_or_equals: 100 } }
			first: 3
			after: $cursor
			order_by: { price: desc }) {
			name
		}
		products_cursor
	}`

vars := json.RawMessage(`{"cursor": null}`)

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
	SecretKey:        "not_a_real_secret",
})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
	return
}

type result struct {
	Products json.RawMessage `json:"products"`
	Cursor   string          `json:"products_cursor"`
}

var val result
if err := json.Unmarshal(res.Data, &val); err != nil {
	fmt.Println(err)
	return
}

if val.Cursor == "" {
	fmt.Println("product_cursor value missing")
	return
}
fmt.Println(string(val.Products))
Output:

[{"name": "Product 100"}, {"name": "Product 99"}, {"name": "Product 98"}]
Example (QueryWithCursorPagination2)
gql := `query {
		products(
			first: 1
			after: $cursor
			where: { id: { lteq: 100 }}
			order_by: { price: desc }) {
			name
		}
		products_cursor
	}`

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
	SecretKey:        "not_a_real_secret",
})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

type result struct {
	Products json.RawMessage `json:"products"`
	Cursor   string          `json:"products_cursor"`
}

var val result
for i := 0; i < 25; i++ {
	vars := json.RawMessage(
		`{"cursor": "` + val.Cursor + `"}`)

	res, err := gj.GraphQL(context.Background(), gql, vars, nil)
	if err != nil {
		fmt.Println(err)
		return
	}

	if err := json.Unmarshal(res.Data, &val); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(val.Products))
}
Output:

[{"name": "Product 100"}]
[{"name": "Product 99"}]
[{"name": "Product 98"}]
[{"name": "Product 97"}]
[{"name": "Product 96"}]
[{"name": "Product 95"}]
[{"name": "Product 94"}]
[{"name": "Product 93"}]
[{"name": "Product 92"}]
[{"name": "Product 91"}]
[{"name": "Product 90"}]
[{"name": "Product 89"}]
[{"name": "Product 88"}]
[{"name": "Product 87"}]
[{"name": "Product 86"}]
[{"name": "Product 85"}]
[{"name": "Product 84"}]
[{"name": "Product 83"}]
[{"name": "Product 82"}]
[{"name": "Product 81"}]
[{"name": "Product 80"}]
[{"name": "Product 79"}]
[{"name": "Product 78"}]
[{"name": "Product 77"}]
[{"name": "Product 76"}]
Example (QueryWithDynamicOrderBy)
gql := `
	query getProducts {
		products(
			order_by: $order, 
			where: { id: { lt: 6 } }, 
			limit: 5,
			before: $cursor) {
			id
			price
		}
	}`

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
	Tables: []core.Table{{
		Name: "products",
		OrderBy: map[string][]string{
			"price_and_id": {"price desc", "id asc"},
			"just_id":      {"id asc"},
		},
	}},
})

type result struct {
	Products json.RawMessage `json:"products"`
	Cursor   string          `json:"products_cursor"`
}
var val result

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

vars1 := json.RawMessage(`{ "order": "price_and_id" }`)

res1, err1 := gj.GraphQL(context.Background(), gql, vars1, nil)
if err1 != nil {
	fmt.Println(err)
	return
}

if err := json.Unmarshal(res1.Data, &val); err != nil {
	fmt.Println(err)
	return
}

if val.Cursor == "" {
	fmt.Println("product_cursor value missing")
	return
}
printJSONString(string(val.Products))

vars2 := json.RawMessage(`{ "order": "just_id" }`)

res2, err2 := gj.GraphQL(context.Background(), gql, vars2, nil)
if err2 != nil {
	fmt.Println(err)
	return
}

if err := json.Unmarshal(res2.Data, &val); err != nil {
	fmt.Println(err)
	return
}

if val.Cursor == "" {
	fmt.Println("product_cursor value missing")
	return
}

printJSONString(string(val.Products))
Output:

[{"id":5,"price":15.5},{"id":4,"price":14.5},{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5}]
[{"id":1,"price":11.5},{"id":2,"price":12.5},{"id":3,"price":13.5},{"id":4,"price":14.5},{"id":5,"price":15.5}]
Example (QueryWithFragments1)
gql := `
	fragment userFields1 on user {
		id
		email
	}

	query {
		users {
			...userFields2
			stripe_id
			...userFields1
		}
	}

	fragment userFields2 on user {
		full_name
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFragments2)
gql := `
	query {
		users {
			...userFields2

			stripe_id
			...userFields1
		}
	}

	fragment userFields1 on user {
		id
		email
	}

	fragment userFields2 on user {
		full_name
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFragments3)
gql := `
	fragment userFields1 on user {
		id
		email
	}

	fragment userFields2 on user {
		full_name

		...userFields1
	}

	query {
		users {
			...userFields2
			stripe_id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","full_name":"User 1","id":1,"stripe_id":"payment_id_1001"},{"email":"user2@test.com","full_name":"User 2","id":2,"stripe_id":"payment_id_1002"}]}
Example (QueryWithFunctionAndDirectives)
gql := `
	query {
		products(id: 51) {
			id
			name
			is_hot_product(args: {id: id}, skipIf: { id: { eq: 51 } })
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":51,"is_hot_product":null,"name":"Product 51"}}
Example (QueryWithFunctionFields)
gql := `
	query {
		products(id: 51) {
			id
			name
			is_hot_product(args: { id: id })
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":51,"is_hot_product":true,"name":"Product 51"}}
Example (QueryWithFunctionFieldsArgList)
gql := `
	query {
		products(id: 51) {
			id
			name
			is_hot_product(args: {a0: 51})
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":51,"is_hot_product":true,"name":"Product 51"}}
Example (QueryWithFunctionReturingTables)
gql := `query {
		get_oldest5_products(limit: 3) {
			id
			name
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"get_oldest5_products":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"},{"id":3,"name":"Product 3"}]}
Example (QueryWithFunctionReturingTablesWithArgs)
gql := `query {
		get_oldest_users(limit: 2, args: {a0: 4, a1: $tag}) {
			tag_name
			id
			full_name
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

vars := json.RawMessage(`{ "tag": "boo" }`)
res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"get_oldest_users":[{"full_name":"User 1","id":1,"tag_name":"boo"},{"full_name":"User 2","id":2,"tag_name":"boo"}]}
Example (QueryWithFunctionReturingTablesWithNamedArgs)
gql := `query {
		get_oldest_users(limit: 2, args: { user_count: 4, tag: $tag }) {
			tag_name
			id
			full_name
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

vars := json.RawMessage(`{ "tag": "boo" }`)
res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"get_oldest_users":[{"full_name":"User 1","id":1,"tag_name":"boo"},{"full_name":"User 2","id":2,"tag_name":"boo"}]}
Example (QueryWithFunctionReturingUserDefinedTypes)
gql := `query {
		get_product(limit: 2, args: { a0: 1 }) {
			id
			name
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"get_product":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}]}
Example (QueryWithFunctionsBlocked)
gql := `query {
		products {
			sum_price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
err := conf.AddRoleTable("anon", "products", core.Query{
	DisableFunctions: true,
})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

all db functions blocked: sum (role: 'anon')
Example (QueryWithFunctionsWithWhere)
gql := `query {
		products(where: { id: { lesser_or_equals: 100 } }) {
			max_price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"max_price":110.5}]}
Example (QueryWithJsonColumn)
gql := `query {
		users(id: 1) {
			id
			category_counts {
				count
				category {
					name
				}
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Tables = []core.Table{
	{
		Name:  "category_counts",
		Table: "users",
		Type:  "json",
		Columns: []core.Column{
			{Name: "category_id", Type: "int", ForeignKey: "categories.id"},
			{Name: "count", Type: "int"},
		},
	},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":{"category_counts":[{"category":{"name":"Category 1"},"count":400},{"category":{"name":"Category 2"},"count":600}],"id":1}}
Example (QueryWithLimitOffsetOrderByDistinctAndWhere)
gql := `query {
		products(
			# returns only 5 items
			limit: 5,

			# starts from item 10, commented out for now
			# offset: 10,

			# orders the response items by highest price
			order_by: { price: desc },

			# no duplicate prices returned
			distinct: [ price ]

			# only items with an id >= 50 and < 100 are returned
			where: { id: { and: { greater_or_equals: 50, lt: 100 } } }) {
			id
			name
			price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":99,"name":"Product 99","price":109.5},{"id":98,"name":"Product 98","price":108.5},{"id":97,"name":"Product 97","price":107.5},{"id":96,"name":"Product 96","price":106.5},{"id":95,"name":"Product 95","price":105.5}]}
Example (QueryWithMultipleTopLevelTables)
gql := `query {
		products(id: $id) {
			id
			name
			customer {
				email
			}
		}
		users(id: $id) {
			id
			email
		}
		purchases(id: $id) {
			id
		}
	}`

vars := json.RawMessage(`{ "id": 1 }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"customer":[{"email":"user2@test.com"}],"id":1,"name":"Product 1"},"purchases":{"id":1},"users":{"email":"user1@test.com","id":1}}
Example (QueryWithNestedOrderBy)
gql := `
	query getProducts {
		products(order_by: { users: { email: desc }, id: desc}, where: { id: { lt: 6 } }, limit: 5) {
			id
			price
		}
	}`

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
})

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":5,"price":15.5},{"id":4,"price":14.5},{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5}]}
Example (QueryWithOrderByList)
gql := `
	query getProducts {
		products(order_by: { id: [$list, "asc"] }, where: { id: { in: $list } }, limit: 5) {
			id
			price
		}
	}`

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
})

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

vars := json.RawMessage(`{ "list": [3, 2, 1, 5] }`)
res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":3,"price":13.5},{"id":2,"price":12.5},{"id":1,"price":11.5},{"id":5,"price":15.5}]}
Example (QueryWithRecursiveRelationship1)
gql := `query {
		reply : comments(id: $id) {
			id
			comments(
				where: { id: { lt: 50 } }, 
				limit: 5,
				find: "parents") {
				id
			}
		}
	}`

vars := json.RawMessage(`{"id": 50 }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"reply":{"comments":[{"id":49},{"id":48},{"id":47},{"id":46},{"id":45}],"id":50}}
Example (QueryWithRecursiveRelationship2)
gql := `query {
		comments(id: 95) {
			id
			replies: comments(find: "children") {
				id
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":{"id":95,"replies":[{"id":96},{"id":97},{"id":98},{"id":99},{"id":100}]}}
Example (QueryWithRecursiveRelationshipAndAggregations)
gql := `query {
		comments(id: 95) {
			id
			replies: comments(find: "children") {
				count_id
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"comments":{"id":95,"replies":[{"count_id":5}]}}
Example (QueryWithRemoteAPIJoin)
gql := `query {
		users {
			email
			payments {
				desc
			}
		}
	}`

// fake remote api service
go func() {
	http.HandleFunc("/payments/", func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Path[10:]
		fmt.Fprintf(w, `{"data":[{"desc":"Payment 1 for %s"},{"desc": "Payment 2 for %s"}]}`,
			id, id)
	})
	log.Fatal(http.ListenAndServe("localhost:12345", nil)) //nolint:gosec
}()

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
conf.Resolvers = []core.ResolverConfig{{
	Name:      "payments",
	Type:      "remote_api",
	Table:     "users",
	Column:    "stripe_id",
	StripPath: "data",
	Props:     core.ResolverProps{"url": "http://localhost:12345/payments/$id"},
}}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":[{"email":"user1@test.com","payments":[{"desc":"Payment 1 for payment_id_1001"},{"desc":"Payment 2 for payment_id_1001"}]},{"email":"user2@test.com","payments":[{"desc":"Payment 1 for payment_id_1002"},{"desc":"Payment 2 for payment_id_1002"}]}]}
Example (QueryWithSkipAndIncludeDirective1)
gql := `
	query {
		products(limit: 2, order_by: { id: asc }) @include(ifRole: "user") {
			id
			name
		}
		users(limit: 3, order_by: { id: asc }) @skip(ifRole: "user") {
			id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":null,"users":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithSkipAndIncludeDirective2)
gql := `
	query {
		products(limit: 2, order_by: { id: asc })  {
			id @skip(ifRole: "user")
			name @include(ifRole: "user")
		}
		users(limit: 3, order_by: { id: asc })  {
			id @include(ifRole: "anon")
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

c := context.WithValue(context.Background(), core.UserIDKey, 1)
res, err := gj.GraphQL(c, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":null,"name":"Product 1"},{"id":null,"name":"Product 2"}],"users":[{"id":null},{"id":null},{"id":null}]}
Example (QueryWithSkipAndIncludeDirective3)
gql := `
	query {
		products(limit: 2) @include(ifVar: $test) {
			id
			name
		}
		users(limit: 3) @skip(ifVar: $test) {
			id
		}
	}`

vars := json.RawMessage(`{ "test": true }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}],"users":null}
Example (QueryWithSkipAndIncludeDirective4)
gql := `
	query {
		products(limit: 2)  {
			id @skip(ifVar: $test)
			name @include(ifVar: $test)
		}
		users(limit: 3)  {
			id @skip(ifVar: $test)
		}
	}`

vars := json.RawMessage(`{ "test": true }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":null,"name":"Product 1"},{"id":null,"name":"Product 2"}],"users":[{"id":null},{"id":null},{"id":null}]}
Example (QueryWithSkipAndIncludeIfArg)
gql := `
	query {
		products(limit: 2, order_by: { id: asc })  {
			id(includeIf: { id: { eq: 1 } })
			name
		}
		users(limit: 3, order_by: { id: asc })  {
			id(skipIf: { id: { eq: 2 } })
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1,"name":"Product 1"},{"id":null,"name":"Product 2"}],"users":[{"id":1},{"id":null},{"id":3}]}
Example (QueryWithSkippingAuthRequiredSelectors)
gql := `query {
		products(limit: 2) {
			id
			name
			owner(where: { id: { eq: $user_id } }) {
				id
				email
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1,"name":"Product 1","owner":null},{"id":2,"name":"Product 2","owner":null}]}
Example (QueryWithSyntheticTables)
gql := `query {
		me @object {
			email
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Tables = []core.Table{{Name: "me", Table: "users"}}
err := conf.AddRoleTable("user", "me", core.Query{
	Filters: []string{`{ id: $user_id }`},
	Limit:   1,
})
if err != nil {
	panic(err)
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 1)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"me":{"email":"user1@test.com"}}
Example (QueryWithTypename)
gql := `query getUser {
		__typename
		users(id: 1) {
		  id
		  email
		  __typename
		}
	  }`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, json.RawMessage(`{"id":2}`), nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"__typename":"getUser","users":{"__typename":"users","email":"user1@test.com","id":1}}
Example (QueryWithUnionForPolymorphicRelationships)
gql := `
	fragment userFields on user {
		email
	}

	fragment productFields on product {
		name
	}

	query {
		notifications {
			id
			verb
			subject {
				...on users {
					...userFields
				}
				...on products {
					...productFields
				}
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, DefaultLimit: 2})
conf.Tables = []core.Table{{
	Name:    "subject",
	Type:    "polymorphic",
	Columns: []core.Column{{Name: "subject_id", ForeignKey: "subject_type.id"}},
}}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"notifications":[{"id":1,"subject":{"email":"user1@test.com"},"verb":"Joined"},{"id":2,"subject":{"name":"Product 2"},"verb":"Bought"}]}
Example (QueryWithUser)
gql := `
	query {
		products(where: { owner_id: { eq: $user_id } }) {
			id
			owner {
				id
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 31)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":31,"owner":{"id":31}}]}
Example (QueryWithVariableLimit)
gql := `query {
		products(limit: $limit) {
			id
		}
	}`

vars := json.RawMessage(`{
		"limit": 10
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10}]}
Example (QueryWithVariables)
gql := `query {
		products(id: $product_id, where: { price: { gt: $product_price } }) {
			id
			name
		}
	}`

vars := json.RawMessage(`{ "product_id": 70 }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Vars = map[string]string{"product_price": "50"}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":70,"name":"Product 70"}}
Example (QueryWithVariablesDefaultValue)
gql := `query ($product_id = 70) {
		products(id: $product_id, where: { price: { gt: $product_price } }) {
			id
			name
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Vars = map[string]string{"product_price": "50"}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":70,"name":"Product 70"}}
Example (QueryWithView)
gql := `query {
		hot_products(limit: 3) {
			product {
				id
				name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Tables = []core.Table{
	{
		Name: "hot_products",
		Columns: []core.Column{
			{Name: "product_id", Type: "int", ForeignKey: "products.id"},
		},
	},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"hot_products":[{"product":{"id":51,"name":"Product 51"}},{"product":{"id":52,"name":"Product 52"}},{"product":{"id":53,"name":"Product 53"}}]}
Example (QueryWithWhere1)
gql := `query {
		products(where: {
			id: [3, 34], 
			or: { 
				name: { iregex: $name }, 
				description: { iregex: $name }
			}
		}) {
			id
		}
	}`

vars := json.RawMessage(`{
		"name": "Product 3"
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":3},{"id":34}]}
Example (QueryWithWhereGreaterThanOrLesserThan)
gql := `query {
		products(
			limit: 3
			where: {
				or: {
					price: { gt: 20 },
					price: { lt: 22 }
				} }
			) {
			id
			name
			price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1,"name":"Product 1","price":11.5},{"id":2,"name":"Product 2","price":12.5},{"id":3,"name":"Product 3","price":13.5}]}
Example (QueryWithWhereHasAnyKey)
gql := `query {
		products(
			where: { metadata: { has_key_any: ["foo", "bar"] } }
			limit: 3
		) {
			id
	}
}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithWhereIn)
gql := `query {
		products(where: { id: { in: $list } }) {
			id
		}
	}`

vars := json.RawMessage(`{
		"list": [1,2,3]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2},{"id":3}]}
Example (QueryWithWhereInWithStaticArrayColumn)
gql := `query {
		products(where: { tags: { in: ["Tag 1", "Tag 2"] } }, 
			limit: 2, 
			order_by: {id: asc}) {
			id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2}]}
Example (QueryWithWhereInWithStaticNumericArrayColumn)
gql := `query {
		products(where: { category_ids: { in: [1,2] } }, 
			limit: 2, 
			order_by: {id: asc}) {
			id
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2}]}
Example (QueryWithWhereInWithVariableArrayColumn)
gql := `query {
		products(where: { tags: { in: $list } }, 
			limit: 2, 
			order_by: {id: asc}) {
			id
		}
	}`

vars := json.RawMessage(`{
		"list": ["Tag 1", "Tag 2"]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2}]}
Example (QueryWithWhereInWithVariableNumericArrayColumn)
gql := `query {
		products(where: { category_ids: { in: $list } }, 
			limit: 2, 
			order_by: {id: asc}) {
			id
		}
	}`

vars := json.RawMessage(`{
		"list": [1, 2]
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1},{"id":2}]}
Example (QueryWithWhereNotIsNullAndGreaterThan)
gql := `query {
		products(
			where: {
				and: [
					{ not: { id: { is_null: true } } },
					{ price: { gt: 10 } },
				] 
			} 
			limit: 3) {
			id
			name
			price
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":1,"name":"Product 1","price":11.5},{"id":2,"name":"Product 2","price":12.5},{"id":3,"name":"Product 3","price":13.5}]}
Example (QueryWithWhereOnRelatedTable)
gql := `query {
		products(where: { owner: { id: { or: [ { eq: $user_id }, { eq: 3 } ] } } }, limit: 2) {
			id
			owner {
				id
				email
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 2)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":2,"owner":{"email":"user2@test.com","id":2}},{"id":3,"owner":{"email":"user3@test.com","id":3}}]}
Example (SetArrayColumnToEmpty)
gql := `mutation {
		products(where: { id: 100 }, update: { tags: [] }) {
			id
			tags
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":100,"tags":[]}]}
Example (SetArrayColumnToValue)
gql := `mutation {
		products(where: { id: 100 }, update: { tags: ["super", "great", "wow"] }) {
			id
			tags
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, nil, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":[{"id":100,"tags":["super","great","wow"]}]}
Example (Subscription)
gql := `subscription test {
		users(id: $id) {
			id
			email
			phone
		}
	}`

vars := json.RawMessage(`{ "id": 3 }`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true, SubsPollDuration: 1})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

m, err := gj.Subscribe(context.Background(), gql, vars, nil)
if err != nil {
	fmt.Println(err)
	return
}
for i := 0; i < 10; i++ {
	msg := <-m.Result
	printJSON(msg.Data)

	// update user phone in database to trigger subscription
	q := fmt.Sprintf(`UPDATE users SET phone = '650-447-000%d' WHERE id = 3`, i)
	if _, err := db.Exec(q); err != nil {
		panic(err)
	}
}
Output:

{"users":{"email":"user3@test.com","id":3,"phone":null}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0000"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0001"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0002"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0003"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0004"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0005"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0006"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0007"}}
{"users":{"email":"user3@test.com","id":3,"phone":"650-447-0008"}}
Example (SubscriptionWithCursor)
// func TestSubCursor(t *testing.T) {
// query to fetch existing chat messages
// gql1 := `query {
// 	chats(first: 3, after: $cursor) {
// 		id
// 		body
// 	}
// 	chats_cursor
// }`

// query to subscribe to new chat messages
gql2 := `subscription {
		chats(first: 1, after: $cursor) {
			id
			body
		}
	}`

conf := newConfig(&core.Config{
	DBType:           dbType,
	DisableAllowList: true,
	SubsPollDuration: 1,
	SecretKey:        "not_a_real_secret",
})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

// struct to hold the cursor value from fetching the existing
// chat messages
// res := struct {
// 	Cursor string `json:"chats_cursor"`
// }{}

// execute query for existing chat messages
// m1, err := gj.GraphQL(context.Background(), gql1, nil, nil)
// if err != nil {
// 	fmt.Println(err)
// 	return
// }

// extract out the cursor `chats_cursor` to use in the subscription
// if err := json.Unmarshal(m1.Data, &res); err != nil {
// 	fmt.Println(err)
// 	return
// }

// replace cursor value to make test work since it's encrypted
// v1 := cursorRegex.ReplaceAllString(string(m1.Data), "cursor_was_here")
// fmt.Println(v1)

// create variables with the previously extracted cursor value to
// pass to the new chat messages subscription
// vars := json.RawMessage(`{ "cursor": "` + res.Cursor + `" }`)
vars := json.RawMessage(`{ "cursor": null }`)

// subscribe to new chat messages using the cursor
m2, err := gj.Subscribe(context.Background(), gql2, vars, nil)
if err != nil {
	fmt.Println(err)
	return
}

go func() {
	for i := 6; i < 20; i++ {
		// insert a new chat message
		q := fmt.Sprintf(`INSERT INTO chats (id, body) VALUES (%d, 'New chat message %d')`, i, i)
		if _, err := db.Exec(q); err != nil {
			panic(err)
		}
		time.Sleep(3 * time.Second)
	}
}()

for i := 0; i < 19; i++ {
	msg := <-m2.Result
	// replace cursor value to make test work since it's encrypted
	v2 := cursorRegex.ReplaceAllString(string(msg.Data), `cursor":"cursor_was_here`)
	printJSON([]byte(v2))
}
Output:

{"chats":[{"body":"This is chat message number 1","id":1}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"This is chat message number 2","id":2}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"This is chat message number 3","id":3}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"This is chat message number 4","id":4}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"This is chat message number 5","id":5}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 6","id":6}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 7","id":7}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 8","id":8}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 9","id":9}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 10","id":10}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 11","id":11}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 12","id":12}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 13","id":13}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 14","id":14}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 15","id":15}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 16","id":16}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 17","id":17}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 18","id":18}],"chats_cursor":"cursor_was_here"}
{"chats":[{"body":"New chat message 19","id":19}],"chats_cursor":"cursor_was_here"}
Example (Update)
gql := `mutation {
		products(id: $id, update: $data) {
			id
			name
		}
	}`

vars := json.RawMessage(`{ 
		"id": 100,
		"data": { 
			"name": "Updated Product 100",
			"description": "Description for updated product 100"
		} 
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"products":{"id":100,"name":"Updated Product 100"}}
Example (UpdateMultipleRelatedTables1)
gql := `mutation {
		purchases(id: $id, update: $data) {
			quantity
			customer {
				full_name
			}
			product {
				description
			}
		}
	}`

vars := json.RawMessage(`{
		"id": 100,
		"data": {
			"quantity": 6,
			"customer": {
				"full_name": "Updated user related to purchase 100"
			},
			"product": {
				"description": "Updated product related to purchase 100"
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"purchases":{"customer":{"full_name":"Updated user related to purchase 100"},"product":{"description":"Updated product related to purchase 100"},"quantity":6}}
Example (UpdateTableAndConnectToRelatedTables)
gql := `mutation {
		users(id: $id, update: $data) {
			full_name
			products {
				id
			}
		}
	}`

vars := json.RawMessage(`{
		"id": 100,
		"data": {
			"full_name": "Updated user 100",
			"products": {
				"connect": { "id": 99 },
				"disconnect": { "id": 100 }
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":{"full_name":"Updated user 100","products":[{"id":99}]}}
Example (UpdateTableAndRelatedTable)
gql := `mutation {
		users(id: $id, update: $data) {
			full_name
			products {
				id
			}
		}
	}`

vars := json.RawMessage(`{
		"id": 90,
		"data": {
			"full_name": "Updated user 90",
			"products": {
				"where": { "id": { "gt": 1 } },
				"name": "Updated Product 90"
			}
		}
	}`)

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
gj, err := core.NewGraphJin(conf, db)
if err != nil {
	panic(err)
}

ctx := context.WithValue(context.Background(), core.UserIDKey, 3)
res, err := gj.GraphQL(ctx, gql, vars, nil)
if err != nil {
	fmt.Println(err)
} else {
	printJSON(res.Data)
}
Output:

{"users":{"full_name":"Updated user 90","products":[{"id":90}]}}
Example (VeryComplexQueryWithArrayColumns)

TODO: Fix: Does not work in MYSQL

gql := `query {
		products(
			# returns only 1 items
			limit: 1,
	
			# starts from item 10, commented out for now
			# offset: 10,
	
			# orders the response items by highest price
			order_by: { price: desc },
	
			# only items with an id >= 30 and < 30 are returned
			where: { id: { and: { greater_or_equals: 20, lt: 28 } } }) {
			id
			name
			price
			owner {
				full_name
				picture : avatar
				email
				category_counts(limit: 2) {
					count
					category {
						name
					}
				}
			}
			category(limit: 2) {
				id
				name
			}
		}
	}`

conf := newConfig(&core.Config{DBType: dbType, DisableAllowList: true})
conf.Tables = []core.Table{
	{
		Name:  "category_counts",
		Table: "users",
		Type:  "json",
		Columns: []core.Column{
			{Name: "category_id", Type: "int", ForeignKey: "categories.id"},
			{Name: "count", Type: "int"},
		},
	},
	{
		Name:    "products",
		Columns: []core.Column{{Name: "category_ids", ForeignKey: "categories.id"}},
	},
}

gj, err := core.NewGraphJin(conf, db)
if err != nil {
	fmt.Println(err)
	return
}

res, err := gj.GraphQL(context.Background(), gql, nil, nil)
if err != nil {
	fmt.Println(err)
	return
}

printJSON(res.Data)
Output:

{"products":[{"category":[{"id":1,"name":"Category 1"},{"id":2,"name":"Category 2"}],"id":27,"name":"Product 27","owner":{"category_counts":[{"category":{"name":"Category 1"},"count":400},{"category":{"name":"Category 2"},"count":600}],"email":"user27@test.com","full_name":"User 27","picture":null},"price":37.5}]}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL