Skip to main content
Version: v3.x (DDN)

Commands Modify Data

Introduction

In DDN, commands represent operations in your API that can be executed such as those which modify data in your data sources, (inserts, updates, deletes), or custom business logic operations.

Lifecycle

The lifecycle in creating a command in your metadata is as follows:

  1. Have some operation in your data source that you want to make executable via your API.
  2. Introspect your data source using the DDN CLI with the relevant data connector to fetch the operation resources.
  3. Add the command to your metadata with the DDN CLI.
  4. Create a build of your supergraph API with the DDN CLI.
  5. Serve your build as your API with the Hasura engine either locally or in the cloud.
  6. Iterate on your API by repeating this process or by editing your metadata manually as needed.
Data modeling lifecycle

Create a command

To add a command you will need to have a data connector already set up and connected to the data source. Follow the Quickstart or the tutorial in How to Build with DDN to get to that point.

From a source operation

Introspect your data source:
ddn connector introspect <connector_name>
Show the resources discovered from your data source:
ddn connector show-resources <connector_name>
Add the command from the discovered resources to your metadata:
ddn command add <connector_link_name> <operation_name>

Or you can optionally add all the commands by specifying "*".

Add all commands from your data source:
ddn command add <connector_link_name> "*"

This will add commands with their accompanying metadata definitions to your metadata.

Via native mutation

The process of creating a native mutation for PostgreSQL is the following.

Within your connector's directory, you can add a new file with a .sql extension to define a native mutation.

Then, use the PostgreSQL connector's plugin to add the native query to your connector's configuration:

Then, use the PostgreSQL connector's plugin to add the native mutation to your connector's configuration:
ddn connector plugin \
--connector <subgraph_name>/<path-to-your-connector>/connector.yaml \
-- \
native-operation create \
--operation-path <subgraph_name>/<path-to-your-connector>/native-operations/mutations/<mutation_name>.sql \
--kind mutation
Introspect your PostgreSQL instance:
ddn connector introspect <connector_name>
Show the found resources:
ddn connector show-resources <connector_name>
Then, add your model:
ddn command add <connector_name> <mutation_name>
ddn supergraph build local
ddn run docker-start

Now in your console you can run the mutation with GraphQL.

See the tutorial for creating a native mutation in PostgreSQL here.

You can now build your supergraph API, serve it, and execute your commands.

For a walkthrough on how to create a command, see the Command Tutorials section below.

Update a command

If you want to update your command to reflect a change that happened in the underlying data source you should first introspect to get the latest resources and then update the relevant command.

Introspect your data source:
ddn connector introspect <connector_name>
Then, update your existing command:
ddn command update <connector_link_name> <command_name>

You will see an output which explains how new resources were added or updated in the command.

You can now build your supergraph API, serve it, and execute your commands with the updated definitions.

You can also update the command by editing the command's metadata manually.

Delete a command

If you no longer need a command, you can delete it:
ddn command remove <command_name>

Along with the command itself, the associated metadata is also removed.

Tutorials

The tutorials below follow on from each particular tutorial in the How to Build with DDN section. Select the relevant data connector to follow the tutorial.

Creating a command

To modify data, you first need to create a command that maps to a specific operation within your data source.

From a source operation

First, show a list of resouces identified by the connector.

Use the DDN CLI to introspect your PostgreSQL database:
ddn connector introspect <connector_name>
ddn connector show-resources my_pg

You will see a list of Commands (Mutations) which have been automatically detected by the connector since they are defined by a foreign key relationship in the database.

Then, add your command:
ddn command add my_pg insert_users

Rebuild your supergraph API.

Create a new build:
ddn supergraph build local

Serve your build.

Serve your build:
ddn run docker-start
ddn console --local

Run the mutation:

mutation InsertUser {
insertUsers(objects: { age: "21", name: "Sean" }, postCheck: {}) {
affectedRows
returning {
id
name
age
}
}
}
{
"data": {
"insertUsers": {
"affectedRows": 1,
"returning": [
{
"id": 4,
"name": "Sean",
"age": 21
}
]
}
}
}

Via native mutation

Within your connector's directory, you can add a new file with a .sql extension to define a native mutation.

Create a new directory to store your native mutations:
mkdir -p app/connector/my_pg/native_operations/mutations/

Let's create a mutation using a SQL UPDATE statement that updates the title of all posts from user's of that age by appending their age to the title.

Create a new file in your connector's directory:
-- native_operations/mutations/update_post_titles_by_age.sql
UPDATE posts
SET title = CASE
WHEN title ~ ' - age \d+$' THEN regexp_replace(title, ' - age \d+$', ' - age ' || {{ age }})
ELSE title || ' - age ' || {{ age }}
END
FROM users
WHERE posts.user_id = users.id
AND users.age = {{ age }}
RETURNING
posts.id,
posts.title,
posts.user_id,
users.name,
users.age;

Arguments are passed to the native mutation as variables surrounded by double curly braces {{ }}.

Then, use the PostgreSQL connector's plugin to add the native mutation to your connector's configuration:
ddn connector plugin \
--connector app/connector/my_pg/connector.yaml \
-- \
native-operation create \
--operation-path native_operations/mutations/update_post_titles_by_age.sql \
--kind mutation
Introspect your PostgreSQL instance:
ddn connector introspect my_pg
Show the found resources:
ddn connector show-resources my_pg
Then, add your model:
ddn command add my_pg update_post_titles_by_age
ddn supergraph build local
ddn run docker-start

Now in your console you can run the following mutation to see the results:

Run the following mutation:
mutation UpdatePostTitlesByAge {
updatePostTitlesByAge(age: "25") {
affectedRows
returning {
id
title
}
}
}
The response will be:
{
"data": {
"updatePostTitlesByAge": {
"affectedRows": 2,
"returning": [
{
"id": 1,
"title": "My First Post - age 25"
},
{
"id": 2,
"title": "Another Post - age 25"
}
]
}
}
}
Lambda connectors

Lambda connectors allow you to execute custom business logic directly via your API. You can learn more about Lambda connectors in the docs.

Updating a command

Your underlying data source may change over time. You can update your command to reflect these changes.

For an automatically detected command, you can update the command metadata.

Use the DDN CLI to introspect your PostgreSQL database:
ddn connector introspect my_pg
Show the resources discovered from your PostgreSQL database:
ddn connector show-resources my_pg
Then, update your commands:
ddn command update my_pg "*"

Deleting a command

If you no longer need a command, you can delete it with the CLI:
ddn command remove <command_name>

Reference

You can learn more about commands in the metadata reference docs.