MySQL / MariaDB

Using a MySQL Database Server as a datasource for Budibase

👍

SQL Databases

Budibase is designed to integrate with any core SQL database.

Read more about SQL Datasources.

Tutorial: Building a HR portal

In this tutorial we will look at building a Budibase app from scratch using a MySQL employees sample database.

The full dataset and installation instructions can be found on Github: datacharmer/test_db.


Adding the datasource

When you have a MySQL or MariaDB Server instance running, with the sample database installed, we can begin pulling that data into Budibase.

First create an app - no sample data needed.

Once the new app has been created, click Add source and select MySQL, even if you are using MariaDB, or any other storage engine.

Click Save and fetch tables to finish.


Define existing relationships

Now that we have pulled in our tables, we need to inform Budibase how the tables relate to each other.

  • One Employee -> Many Titles (Historical)
  • One Employee -> Many Salaries (Historical)
  • Many Departments -> Many Employees / Managers

To define these relationships, click on the MySQL datasource in the datasource list and scroll down to and click Define relationship.

For the one employee to many titles and salaries, define a relationship like so:

One employee -> Many titles (matching on emp_no)

One employee -> Many titles (matching on emp_no)

For the relationship between departments and employees, there are joining tables, e.g. dept_emp. Usually we would setup a many-to-many relationship using the joining table as the Through table. Unfortunately in this case, the joining tables do not meet the requirements outlined by Budibase:

dept_emp is not a suitable Budibase joining table

dept_emp is not a suitable Budibase joining table

from_date and to_date are invalid

from_date and to_date are invalid

Luckily, this is an easy fix. Within MySQL Workbench, or through an alter SQL statement, make the from_date and to_date fields nullable for both joining tables.

ALTER TABLE `employees`.`dept_emp` 
CHANGE COLUMN `from_date` `from_date` DATE NULL ,
CHANGE COLUMN `to_date` `to_date` DATE NULL ;
dept_emp is now a suitable joining table

dept_emp is now a suitable joining table

Adding the Many -> Many relationships for dept_emp should now work.

📘

Make sure to re-fetch the tables to pull down the new schema information!

Many Departments -> Many Employees

Many Departments -> Many Employees

An additional Many -> Many relationship cannot be added for two tables that already have a Many -> Many relationship established, but for this tutorial we do not need the dept_manager table.

Because the Many -> Many relationship between departments and employees will pull down a huge amount of information, we will also create a Custom SQL query called Get Departments Only to simply get the departments without any employee data when needed.

Simple select statement with no relationship data

Simple select statement with no relationship data

🚧

Max SQL rows environment variable

When using a large dataset with a lot of relational data such as in this tutorial, you will need to update your .env hosting settings .

Set SQL_MAX_ROWS=50000 for this tutorial.

In the end your relationships table should look something like so:

By default the display name for the relationships will be the ID, but this isn't very readable:

To improve upon this, we can select a display column for each table. This will be the column that appears in the relationship pills. As an example, for the employees table, edit the first_name column and toggle Use as table display column on.

Setting the first_name to be the display column

Setting the first_name to be the display column

The employee relationship in the related tables, such as titles, is now more human readable. You can also use Formula columns to combine the first and last names of the employee into a single display column.

Create a new formula column in the employees table called 'full_name' with the following binding expression: {{ first_name }} {{ last_name }}. Set this column as the table display column.


Org chart screen

Now that we have the data pulled into Budibase, let's create a screen that allows HR to see the various departments and the org structure for each.

Step 1 - Adding the row explorer

On the home screen, click Add component and select the Row Explorer Block. For the table select departments, and remove the height - we will display all nine departments at once without the need for scroll.

Next in the Cards section, set the Title to match the dept_name, and remove the Subtitle and Description.

Selecting the department name as the card title

Selecting the department name as the card title

List of clickable department names

List of clickable department names

(Optional) Adding icons for each department

To add a little bit of flavour to the row explorer, we can provide an Image URL for each department. One way to do this would be to host the images in a public repository and name the files to match the department names. Another approach is to create a column in your table to store a URL icon path, which is what we'll do in this example.

  1. Within Budibase, click on the departments table, and click Create column.
  2. Add a Text column called icon_url.
  3. For each department row, add a URL path to an appropriate icon. I have found svgrepo.com to be a good resource for free SVG icons. For your convenience, I have provided SQL update statements:
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/428772/marketing-market-social.svg' WHERE dept_no = 'd001';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/381027/finance-bank-piggy-business-money.svg' WHERE dept_no = 'd002';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/218257/human-resources-search.svg' WHERE dept_no = 'd003';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/430190/production-industrial-automation.svg' WHERE dept_no = 'd004';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/428736/development-cognitive-progress.svg' WHERE dept_no = 'd005';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/422994/quality-premium-certificate.svg' WHERE dept_no = 'd006';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/430192/sales-shop-analytics.svg' WHERE dept_no = 'd007';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/119008/research.svg' WHERE dept_no = 'd008';
UPDATE departments SET icon_url = 'https://www.svgrepo.com/show/429955/customer-service-hotel.svg' WHERE dept_no = 'd009';
  1. In the Design section, click on the Row Explorer block and set the Image URL to the icon_url field.
Selecting an image url

Selecting an image url

  1. The image icons are not in the correct aspect ratio or a consistent size, but we can use the following Global styling to format the background image as needed:
<style>
.spectrum-Card-coverPhoto {
  background-size: 64px 64px;
  background-repeat: no-repeat;
}
</style>
  1. We also do not need the search, so we should Eject the block and delete the form. Your builder should appear like so:

Step 2 - Adding the manager and employee cards

After ejecting the row explorer block, we need to change the Data provider source to the Get Departments Only as we do not want the relational employee data in this simple list of departments.

In addition, the auto-generated click action of the Spectrumcard will need to be updated. Click Define actions and change the state value to the dept_no from the query:

At the moment upon previewing the app, a basic form is shown on click of each department row. Instead we want to display a card for the department managerial team and their employees.

First delete the Form block and button components from the container. Next we want to make sure the clicked department name is available in the explorer panel. To do this, we will push the clicked row department name into App state.

Click on the Spectrumcard component and within the Settings Panel click Define actions. Then click Add Action -> Update State and set a variable called DepartmentName as follows:

Be sure to click the Save button!

Whilst we could use multiple nested repeaters to pull in all of the department detail we want to display, it is much more efficient to use a Custom SQL query. Use the following SQL:

SELECT * FROM departments d
JOIN dept_manager dm on d.dept_no = dm.dept_no
JOIN employees e on dm.emp_no = e.emp_no
JOIN titles t on t.emp_no = e.emp_no
WHERE d.dept_name = {{ dept_name }} AND (e.emp_no, t.from_date) in (select t.emp_no, max(t.from_date) from titles t group by emp_no)

Also add a binding for the dept_name, and give the query the name Get Managers by Department Name. Make sure to save!

Back to the Design section, add a Cards Block for the managers using the SQL query datasource just added, passing in the binding: {{ State.DepartmentName }}. This will replace the form block we removed.

Within the Cards section set the Title to {{ Managers.Get Managers by Department Name.first_name }} {{ Managers.Get Managers by Department Name.last_name }}.

For the Description, we want to display the managers current (most recent) job title: {{ Managers.Get Managers by Department Name.title }}

With the card block setup, it is also worth adding a headline component to indicate which department has been selected. Above the cards block, add the headline component with the title {{ State.DepartmentName }}. Add some styling such as margin bottom and Extra Large size.

A preview of the app should show the following so far:


Employees screen

As this data set has thousands of employees per department, cards are not an ideal way to display the data. Instead we can display this data in a paginated Table block filtered on an encoded department ID passed via URL variables.

To get started, click Add screen and select Autogenerated screens. Tick the employees table and confirm.

Next we want to be able to pass through the emp_no and dept_name from the home screen. To support this, configure the screen route as follows:

Employees screen with two variables

Employees screen with two variables

Use the name URL variable in the Title of the table block.

Access the department name from the URL

Access the department name from the URL

With so many records, search will be very important. Under Search Fields select some searchable fields.

Now let's make use of the {{ URL.id }} binding to filter our employees by department. Define filters of the table block. The dept_no will be available via the dept_emp relationship, and we can match that against the ID in the URL as follows:

Also set the Scroll Limit of the table block to 200.

Linking from the home screen

The employee screen is ready to go, but we still need to link it to the home screen.

Add a Link component underneath the Managers card block. Add some margin top for some space. Give the URL the following binding: /employees/{{ State.cAF3fs8fNJ }}/{{ State.DepartmentName }}. The ID state will be different in your case.