chore: import upstream snapshot with attribution
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / hurl (${{ matrix.example }}) (push) Has been skipped
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
CI / windows_test (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:31:57 +08:00
commit d718c5a372
986 changed files with 74597 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# Handling json data in MySQL
This demonstrates both how to produce json data from a SQL query in MySQL
and how to consume json data from SQLPage.
![](./screenshots/app.png)
## Documentation
This example demonstrates how to consume [JSON](https://en.wikipedia.org/wiki/JSON) data from a MySQL database,
using the [`JSON_TABLE`](https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html)
function to parse the JSON data into a table.
The main page contains a form with a select input, in which the user can
select one or multiple values.
The values are then sent to the server, and are accessible from SQL queries in the form of a JSON array.
The SQL then uses the `JSON_TABLE` function to transform the JSON array into a temporary table,
which is then used to process the data and insert it into the database.
@@ -0,0 +1,17 @@
services:
web:
image: lovasoa/sqlpage:main # main is cutting edge, use sqlpage/SQLPage:latest for the latest stable version
ports:
- "8080:8080"
volumes:
- .:/var/www
- ./sqlpage:/etc/sqlpage
depends_on:
- db
environment:
DATABASE_URL: mysql://root:secret@db/sqlpage
db: # The DB environment variable can be set to "mariadb" or "postgres" to test the code with different databases
image: mariadb:12 # support for json_table was added in mariadb 10.6
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: sqlpage
+35
View File
@@ -0,0 +1,35 @@
select 'form' as component, 'Create a new Group' as title, 'Create' as validate;
select 'Name' as name;
insert into groups(name) select :Name where :Name is not null;
select 'list' as component, 'Groups' as title, 'No group yet' as empty_title;
select name as title from groups;
select 'form' as component, 'Add a user' as title, 'Add' as validate;
select 'UserName' as name, 'Name' as label;
select
'Memberships[]' as name,
'Group memberships' as label,
'select' as type,
TRUE as multiple,
'press ctrl to select multiple values' as description,
json_arrayagg(json_object("label", name, "value", id)) as options
from groups;
insert into users(name) select :UserName where :UserName is not null;
insert into group_members(group_id, user_id)
select group_name, last_insert_id()
from json_table(:Memberships, '$[*]' columns (
group_name int path '$'
)) as json_elems
where :Memberships is not null;
select 'list' as component, 'Users' as title, 'No user yet' as empty_title;
select
users.name as title,
group_concat(groups.name) as description
from users
left join group_members on users.id = group_members.user_id
left join groups on groups.id = group_members.group_id
group by users.id, users.name;
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@@ -0,0 +1,17 @@
create table users (
id int primary key auto_increment,
name varchar(255) not null
);
create table groups (
id int primary key auto_increment,
name varchar(255) not null
);
create table group_members (
group_id int not null,
user_id int not null,
primary key (group_id, user_id),
foreign key (group_id) references groups (id),
foreign key (user_id) references users (id)
);
@@ -0,0 +1,18 @@
CREATE TABLE questions(
id INT PRIMARY KEY AUTO_INCREMENT,
question_text TEXT
);
CREATE TABLE survey_answers(
id INT PRIMARY KEY AUTO_INCREMENT,
question_id INT,
answer TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (question_id) REFERENCES questions(id)
);
INSERT INTO questions(question_text) VALUES
('What is your name?'),
('What is your age?'),
('What is your favorite color?');
+27
View File
@@ -0,0 +1,27 @@
SELECT 'form' as component, 'Survey' as title;
SELECT id as name, question_text as label, 'textarea' as type
FROM questions;
-- Save all the answers to the database, whatever the number and id of the questions
INSERT INTO survey_answers (question_id, answer)
SELECT
question_id,
json_unquote(
json_extract(
sqlpage.variables('post'),
concat('$."', question_id, '"')
)
)
FROM json_table(
json_keys(sqlpage.variables('post')),
'$[*]' columns (question_id int path '$')
) as question_ids;
-- Show the answers
select 'card' as component, 'Survey results' as title;
select
questions.question_text as title,
survey_answers.answer as description,
'On ' || survey_answers.timestamp as footer
from survey_answers
inner join questions on questions.id = survey_answers.question_id;
+37
View File
@@ -0,0 +1,37 @@
GET http://localhost:8080
HTTP 200
[Asserts]
header "Content-Type" contains "text/html"
xpath "//html" exists
xpath "//body" exists
body not contains "An error occurred"
POST http://localhost:8080/
Content-Type: application/x-www-form-urlencoded
[FormParams]
Name: Hurl Analysts
HTTP 200
[Asserts]
body contains "Hurl Analysts"
body not contains "An error occurred"
POST http://localhost:8080/
Content-Type: application/x-www-form-urlencoded
[FormParams]
Name: Hurl Reviewers
HTTP 200
[Captures]
analysts_id: xpath "string(//select[@name='Memberships[]']/option[normalize-space(.)='Hurl Analysts']/@value)"
reviewers_id: xpath "string(//select[@name='Memberships[]']/option[normalize-space(.)='Hurl Reviewers']/@value)"
[Asserts]
body contains "Hurl Reviewers"
body not contains "An error occurred"
POST http://localhost:8080/
Content-Type: application/x-www-form-urlencoded
`UserName=Hurl+User&Memberships%5B%5D={{analysts_id}}&Memberships%5B%5D={{reviewers_id}}`
HTTP 200
[Asserts]
body contains "Hurl User"
body htmlUnescape contains "Hurl Analysts,Hurl Reviewers"
body not contains "An error occurred"