diff --git a/docs/ff-integrations/database/supabase/database-actions.md b/docs/ff-integrations/database/supabase/database-actions.md index 00334151..b0e10c7d 100644 --- a/docs/ff-integrations/database/supabase/database-actions.md +++ b/docs/ff-integrations/database/supabase/database-actions.md @@ -1,185 +1,144 @@ --- slug: /integrations/database/supabase/database-actions title: Database Actions -description: Learn about Supabase Database actions in your FlutterFlow app, including how to perform various database operations. -tags: [Supabase, Database, Actions] +description: Learn how to insert, upsert, update, delete, and query Supabase rows from your FlutterFlow app. +tags: [Supabase, Database, Actions, Upsert] sidebar_position: 1 -keywords: [FlutterFlow, Supabase, Database, Actions] +keywords: [FlutterFlow, Supabase, Database, Actions, Upsert Row] toc_max_heading_level: 5 --- # Supabase Database Actions -The Supabase Database Actions allow you to **Insert, Update**, or **Delete a Row** from a Supabase table. - -Note that beyond actions, you can also setup [**Backend Queries**](../../../resources/control-flow/backend-logic/backend-query/backend-query.md) for Supabase. This includes realtime streaming queries. +Supabase Database Actions allow you to insert, upsert, update, delete, or query rows in a Supabase table. +You can also set up [**Backend Queries**](../../../resources/control-flow/backend-logic/backend-query/backend-query.md) to load Supabase data automatically and keep it updated through real-time streaming. :::note[Prerequisites] -Before getting started with this section, ensure you have, +Before using these actions: -1. Completed all steps in the [**Supabase setup**](../../supabase/supabase-setup.md) -2. Ensure you have a table created for adding, updating, and deleting data. +- Complete the [**Supabase setup**](../../supabase/supabase-setup.md). +- Create the table and fields your action will use. ::: - ## Types of Supabase Database Actions -Following are the types of actions you can perform on a Supabase table. +The following actions are available for Supabase tables: -- [**Insert Row**](#insert-row-action): Adds a new row in a table. -- [**Update Row**](#update-row-action)**:** Updates a row with the specified values. -- [**Delete Row**](#delete-row-action)**:** Deletes a row from a table. -- [**Query Rows**](#query-rows-action): Retrieves - rows from a table based on specific criteria or conditions. +- [**Insert Row**](#insert-row-action): Adds a new row to a table. +- [**Upsert Row**](#upsert-row-action): Inserts a new row or updates an existing row when the conflict columns match. +- [**Update Row**](#update-row-action): Updates rows that match specified filters. +- [**Delete Row**](#delete-row-action): Deletes rows that match specified filters. +- [**Query Rows**](#query-rows-action): Retrieves rows from a table based on specific criteria or conditions. ### Insert Row [Action] -1. Select the **Widget** (e.g., Button) on which you want to define the action. -2. Select **Actions** from the Properties Panel (the right menu), and click **Open**. This will - open an **Action Flow Editor** in a new popup window. +Use **Insert Row** when you always want to create a new row. - 1. Click on **+ Add Action**. - 2. On the right side, search and select the **Supabase** > **Insert Row** action. - 3. Set the **Table** to your table name (e.g., assignments). - 4. Under the **Set Fields** section, click on the **+ Add Field** button. - 5. Click on the Field name. +To configure the action: - 1. Scroll down to find the **Value Source** dropdown and change it to **From Variable**. - 2. Click on **UNSET** and select **Widget State > Name** of the TextField. - 6. Similarly, add the field for the other UI elements. +1. Select the widget that will trigger the action and open the **Action Flow Editor**. +2. Click **+ Add Action**, then search for and select **Insert Row**. +3. Set **Table** to the Supabase table where you want to add the row. +4. Under **Set Fields**, click **+ Add Field** and select a field. +5. Set its value directly or choose **From Variable** to use data such as a widget state value. +6. Repeat steps 4–5 for each remaining field you want to set. -:::tip[Pro Tip] -While adding this action, you can leave the **id** (if marked as *Primary*) and - **created_at** (if default value is `now()`) fields. Supabase will automatically add values for these fields. +:::tip[Generated values] +Leave automatically generated fields unset. For example, Supabase can generate `id` when it is configured as an identity column and `created_at` when its default value is `now()`. ::: -
- - +### Upsert Row [Action] -### Update Row [Action] - -1. Select the **Widget** (e.g., Button) on which you want to define the action. -2. Select **Actions** from the Properties Panel (the right menu), and click **Open**. This will - open an **Action Flow Editor** in a new popup window. +The **Upsert Row** action inserts a new row when no existing row has the same values in the selected conflict columns. If a matching row exists, the action updates that row instead. This is useful when you want to save data without first querying the table to determine whether to insert or update it. - 1. Click on **+ Add Action**. - 2. On the right side, search and select the **Supabase** > **Update Row** action. - 3. Set the **Table** to your table name (e.g., assignments). - 4. Optional: If you want to get the rows after the update is finished, enable the **Return Matching Rows** option. - 5. Now, you must set the row you want to update. Usually, this is done by finding a row in a table that matches the current row ID. To do so, click **+ Add Filter** button inside the **Matching Rows** section. +For example, you can use `id` as the conflict column when saving a task. If a task with that `id` exists, the action updates its fields. Otherwise, it inserts a new task. - 1. Set the **Field Name** to the field that contains the IDs. Typically, this is the - **id** column. - 2. Set the **Relation** to **Equal To** because you want to find a row with the exact id. - 3. Into the **Value Source**, you can select the **From Variable** and provide the id of the row for which you just updated values in the UI. - 6. Under the **Set Fields** section, click on the **+ Add Field** button. - 7. Click on the Field Name. - - 1. Scroll down to find the **Value Source** dropdown and change it to **From Variable**. - 2. Click on **UNSET** and select **Widget State > Name** of the TextField. - 8. Similarly, add the field for the other UI elements. +To configure the action: +1. Select the widget that will trigger the action. +2. Open the **Action Flow Editor**. +3. Click **+ Add Action**, then search for and select **Upsert Row**. +4. Set **Table** to the Supabase table you want to modify. +5. Under **Set Fields**, click **+ Add Field** and provide the values to insert or update. Include values for every selected conflict column. +6. Under **On Conflict Columns**, select the primary key or unique columns that identify an existing row. +7. Optional: Enter an **Action Output Variable Name** to use the returned row in later actions. -:::tip[How to & Tips] +:::note[Conflict columns] +The selected conflict columns must form a primary key or unique constraint in Supabase. If their values do not match an existing row, the action inserts a new row. For more information, see the [**Supabase Upsert documentation**](https://supabase.com/docs/reference/dart/upsert). +::: - +:::tip[Configure RLS] +Because an upsert can either insert or update a row, configure suitable `INSERT` and `UPDATE` row-level security (RLS) policies for the table. If you use the action output, ensure the user can also read the returned row. See the [**Supabase Row Level Security guide**](https://supabase.com/docs/guides/database/postgres/row-level-security) for details on creating policies. +::: - +### Update Row [Action] -If you have a flow like this, *HomePage* -> *AssignmentDetailsPage* -> -*UpdateAssignmentPage*, you can enable the **Replace Route** option (see point no. 5 [here](../../../ff-concepts/navigation-routing/page-navigation.md#navigate-to-action)) when you navigate from *AssignmentDetailsPage* to *UpdateAssignmentPage*. And then chain the [Navigate Back](../../../ff-concepts/navigation-routing/page-navigation.md#navigate-back-action) action after the update action. This will directly open the *HomePage* after the row is updated. -::: +Use **Update Row** to change one or more existing rows that match your filters. +To configure the action: +1. Select the widget that will trigger the action and open the **Action Flow Editor**. +2. Click **+ Add Action**, then search for and select **Update Row**. +3. Set **Table** to the Supabase table you want to update. +4. Optional: Enable **Return Matching Rows** if you need the updated rows in later actions. +5. Under **Matching Rows**, click **+ Add Filter** and configure the **Field Name**, **Relation**, and **Value**. For example, set **Field Name** to `id`, **Relation** to **Equal To**, and **Value** to the target row's ID. +6. Under **Set Fields**, click **+ Add Field** and provide each new value. ### Delete Row [Action] -Go to your project page on FlutterFlow and follow the steps below to define the Action to any widget. - -1. Select the **Widget** (e.g., Button) on which you want to define the action. -2. Select **Actions** from the Properties Panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window. +Use **Delete Row** to remove one or more rows that match your filters. - 1. Click on **+ Add Action**. - 2. On the right side, search and select the **Supabase** -> **Delete Row** action. - 3. Set the **Table** to your table name (e.g., assignments). - 4. Optional: If you want to know which rows were deleted from a table, enable the **Return - Matching Rows** option. - 5. Now, you must set the row you want to delete. Usually, this is done by finding a row in a table that matches the current row ID. To do so, click **+ Add Filter** button inside the **Matching Rows** section. +To configure the action: - 1. Set the **Field Name** to the field that contains the IDs. Typically, this is the - **id** column. - 2. Set the **Relation** to **Equal To** because you want to find a row with the exact id. - 3. Into the **Value Source**, you can select the **From Variable** and provide the id of the row you want to delete. +1. Select the widget that will trigger the action and open the **Action Flow Editor**. +2. Click **+ Add Action**, then search for and select **Delete Row**. +3. Set **Table** to the Supabase table from which you want to delete rows. +4. Optional: Enable **Return Matching Rows** if you need the deleted rows in later actions. +5. Under **Matching Rows**, click **+ Add Filter** and configure the **Field Name**, **Relation**, and **Value**. For example, set **Field Name** to `id`, **Relation** to **Equal To**, and **Value** to the target row's ID. - +:::caution +Filters determine which rows are updated or deleted. Use a unique field such as `id` when you intend to affect only one row. +::: - :::tip - -You can chain the [**Refresh Database Request**](../refresh-db-request.md) action after this action to remove the -deleted items from the list. - +You can add the [**Refresh Database Request**](../refresh-db-request.md) action after deleting rows to refresh the displayed data. ::: ### Query Rows [Action] -There are certain scenarios where you may want to query a Supabase table manually. For example, you might want to only fetch data in response to a specific user action, such as clicking on a button. +Use **Query Rows** to load data in response to an action, such as a button tap. This is useful when the query should run only after user interaction or when different actions need different data. -Additionally, if your app fetches different data under different conditions, you might find it more convenient to manually call queries. For example, you might fetch different tasks for admin and team members. +To configure the action: -To manually query a Supabase table, follow the steps below to define this action to any widget: +1. Select the widget that will trigger the query and open the **Action Flow Editor**. +2. Click **+ Add Action**, then search for and select **Query Rows**. +3. Select the **Table** you want to query. +4. Optional: Add [filters](#filtering-table-data) or [ordering](#ordering-table-data). +5. Enter an **Action Output Variable Name** to access the returned rows in later actions. -1. Select the **Widget** (e.g., Button) on which you want to define the action. +#### Use Query Results -2. Select **Actions** from the Properties Panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window. -3. Click on **+ Add Action**. -4. On the right side, search and select the **Supabase** > **Query Rows** action. -5. Select the **Table** you want to query. -6. You can also [Filter](#filtering-table-data) and [Order](#ordering-table-data) the query results. -7. Provide the **Action Output Variable Name**. This will be used to store the query result. - - - - - - - - -8. Now, you can use the **Action Output Variable Name** provided in the previous step to generate -children from a variable on **ListView**. -9. Finally, you can display data in a **Text** widget. To do so, select the **Text widget > Properties Panel > Text > Set from Variable menu > ***[children_from_variable_name]*** item > Get Row Field > select the row field** you want to display. - - +Access the returned rows from **Action Outputs**. To display them in a ListView, generate dynamic children from the action output and bind widgets inside each child to the appropriate row fields. +#### Filtering Table Data -#### Filtering table data -Sometimes you might want to filter a list based on a condition. For example, showing only -completed assignments. You can do so by adding the Filter while you query a Supabase table. +Use filters to return only rows that match specific conditions. For example, you can query only completed assignments. -Let's see how to filter the Supabase table to display only desired items: +To add a filter: -- In your **Action properties** of Query Rows action, scroll down and click on the **+ Add Filter** - button at the bottom. - -- Find the **Field Name**, click on the Unset, and select a column on which you would like to apply - the filter. -- Find the **Relation** dropdown, click on the Unset, and choose the relation amongst the list. -- Find the **Value** property and set it to an appropriate value and click Confirm. +1. In the **Query Rows** action properties, click **+ Add Filter**. +2. Set **Field Name** to the column you want to filter. +3. Select a **Relation**. +4. Set **Value**, then click **Confirm**. :::tip -You could choose a filter relation based on your requirements. For example: +Choose a filter relation based on the results you need. For example: -- **Equal To**: To show only completed assignments, set the **Field Name** to the column that holds the completion status (e.g., **is_done**), set the **Relation** to **Equal To**, and set the **Value** to **True**. -- **Greater Than**: To show only users older than 30, set the **Field Name** to the **age** column, set the **Relation** to **Greater Than**, and set the **Value** to 30. -- **Like**: For filtering addresses with zip codes starting with '35,' set the **Field Name** to the **zip_code** column, set the **Relation** to **LIKE**, and set the **Value** to **35%**. In the value field, you use the following wildcards to perform flexible pattern matching to filter your data effectively. - - **Percent (`%`) Wildcard**: Represents zero, one, or multiple characters. +- **Equal To**: To show only completed assignments, set **Field Name** to `is_done`, **Relation** to **Equal To**, and **Value** to `True`. +- **Greater Than**: To show only users older than 30, set **Field Name** to `age`, **Relation** to **Greater Than**, and **Value** to `30`. +- **Like**: To find addresses with ZIP codes starting with `35`, set **Field Name** to `zip_code`, **Relation** to **Like**, and **Value** to `35%`. Use these wildcards for pattern matching: + - **Percent (`%`) Wildcard**: Represents zero or more characters. - Example: `'A%'` matches any string starting with `'A'` (e.g., `'Apple'`, `'Apex'`). - Example: `'%A%'` matches any string containing `'A'` (e.g., `'Canada'`, `'Australia'`). - **Underscore (`_`) Wildcard**: Represents a single character. @@ -188,48 +147,35 @@ You could choose a filter relation based on your requirements. For example: ::: :::info -You can combine multiple filters using **AND** or **OR** operators to create more advanced filtering logic. This enables you to refine your data query to match specific conditions. +You can combine multiple filters using **AND** or **OR** operators to create more advanced filtering logic. ::: - - +#### Ordering Table Data -#### Ordering table data -You might want to show a list from the Supabase table in a specific order. For example, showing assignments in order of the due date. +Use ordering to return rows in a specific sequence, such as assignments ordered by due date. To specify the order: -- In your **Action properties** of Query Rows action, scroll down and click on the **+ Add Order** -button at the bottom. -- Set the **Table Field Name** to the column you would like to choose for ordering. -- Find **Order** dropdown, click on the Unset and choose the order either **Increasing** or **Decreasing** and - click **Confirm**. +1. In the **Query Rows** action properties, click **+ Add Order**. +2. Set **Table Field Name** to the column used for ordering. +3. Set **Order** to **Increasing** or **Decreasing**, then click **Confirm**. :::tip -You could choose the order based on your requirements. For example, to show assignments in order of due date, set Table Field Name to due_date and Order to Increasing. -::: - - - - -:::info -Additional Note: Currently, you can only add "and" conditions to Supabase query filters. If you want to add an "or" filter like "status == 5 or status == 8", you can consider logic to apply "status in (5,8)" or any other logic. Fully customizable using API calls or custom actions. +To show assignments with the earliest due dates first, set **Table Field Name** to `due_date` and **Order** to **Increasing**. ::: -## Trigger Action On Data Change +## Trigger an Action on Data Change -Sometimes, you may want to trigger an action whenever data changes in a Supabase table. For instance, in an ecommerce app, you might want to notify users on the orders page when the status of their order is updated. +You can trigger an action whenever data changes in a Supabase table. For example, an e-commerce app can notify users when an order's status changes. To respond to data changes in a Supabase table: 1. Ensure you have added a **Supabase Query** to a widget (e.g., a ListView) with **Single Time Query** disabled to enable real-time updates. 2. On the widget with the **Supabase Query**, open the **Action Flow Editor** and set **On Data Change** as the [Action Trigger](../../../resources/control-flow/functions/action-triggers.md). This ensures that any actions you add will be triggered whenever the data is updated, added, or deleted. -3. You can now [add any action](../../../resources/control-flow/functions/action-flow-editor.md#adding-an-action-example) you want to perform, such as showing a notification, refreshing the UI, or fetching related data. +3. [Add an action](../../../resources/control-flow/functions/action-flow-editor.md#adding-an-action-example), such as showing a notification, refreshing the UI, or fetching related data. :::info -If you are using this trigger on a ListView, make sure to **disable** the **Infinite Scroll**. +When using this trigger on a ListView, disable **Infinite Scroll**. :::