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
@@ -0,0 +1,34 @@
# Handling json data in Microsoft SQL Server
This demonstrates both how to produce and read json data from a SQL query
in MS SQL Server (or Azure SQL Database), for creating advanced forms.
This lets your user interact with your database with a simple web interface,
even when you have multiple tables, with one-to-many relationships.
![](./screenshots/app.png)
## Documentation
SQLPage requires JSON to create multi-select input (dropdowns where an user can select multiple values).
The result of these multi-selects is a JSON array, which also needs to be read by SQL queries.
This example demonstrates how to consume [JSON](https://en.wikipedia.org/wiki/JSON) data from a SQL Server database,
using the [`OPENJSON`](https://docs.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql)
function to parse the JSON data into a table,
and [`FOR JSON PATH`](https://learn.microsoft.com/en-us/sql/relational-databases/json/format-query-results-as-json-with-for-json-sql-server)
to format query results as a JSON array.
This demonstrates an application designed for managing groups and users, allowing the creation of new groups, adding users, and assigning users to one or multiple groups.
The application has the following sections:
- **Create a New Group**: A form where users can enter the name of a new group.
- **Groups Display**: A list of existing groups.
- **Add a User**: A form where users can enter the name of a new user and select one or multiple groups to assign to this user.
- **Users Display**: A list of existing users and their associated group memberships.
When users submit the form, their selections are packaged up and sent to the database server. The server receives these selections as a structured JSON array.
The database then takes this list of selections and temporarily converts it into a format it can work with using the `OPENJSON` function, before saving the information permanently in the database tables. This allows the system to process multiple selections at once in an efficient way.
@@ -0,0 +1,30 @@
services:
web:
image: lovasoa/sqlpage:main
ports:
- "8080:8080"
volumes:
- .:/var/www
- ./sqlpage:/etc/sqlpage
depends_on:
- db
environment:
RUST_LOG: sqlpage=debug
DATABASE_URL: mssql://sa:YourStrong!Passw0rd@db:1433/
db:
image: mcr.microsoft.com/mssql/server:2022-latest
volumes:
- ./sqlpage/mssql-migrations:/migrations
environment:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: YourStrong!Passw0rd
MSSQL_PID: Express
command: >
bash -c "
/opt/mssql/bin/sqlservr &
until /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourStrong!Passw0rd -C -Q 'SELECT 1;'; do
echo 'Waiting for database...'
sleep 1
done
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourStrong!Passw0rd -C -i /migrations/0001_db_init.sql
tail -f /dev/null"
@@ -0,0 +1,37 @@
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,
1 as multiple,
'press ctrl to select multiple values' as description,
(
SELECT name as label, id as value
FROM groups
FOR JSON PATH -- this builds a JSON array of objects
) as options;
insert into users(name) select :UserName where :UserName is not null;
insert into group_members(group_id, user_id)
select json_elem.value, IDENT_CURRENT('users')
from openjson(:Memberships) as json_elem
where :Memberships is not null;
select 'list' as component, 'Users' as title, 'No user yet' as empty_title;
select
users.name as title,
string_agg(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,35 @@
create table users (
id int primary key IDENTITY(1,1),
name varchar(255) not null
);
create table groups (
id int primary key IDENTITY(1,1),
name varchar(255) not null
);
create table group_members (
group_id int not null,
user_id int not null,
constraint PK_group_members primary key (group_id, user_id),
constraint FK_group_members_groups foreign key (group_id) references groups (id),
constraint FK_group_members_users foreign key (user_id) references users (id)
);
CREATE TABLE questions(
id INT PRIMARY KEY IDENTITY(1,1),
question_text TEXT
);
CREATE TABLE survey_answers(
id INT PRIMARY KEY IDENTITY(1,1),
question_id INT,
answer TEXT,
timestamp DATETIME DEFAULT GETDATE(),
CONSTRAINT FK_survey_answers_questions 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?');
@@ -0,0 +1,11 @@
# Migrations for Microsoft SQL Server
This folder contains the migrations for the Microsoft SQL Server example.
At the time of writing, SQLPage does not support applying migrations for Microsoft SQL Server
automatically, so we need to apply them manually.
We write the migrations in a folder called `mssql-migrations`, instead of the usual `migrations`
folder, and we use the `sqlcmd` tool to apply them.
See [how it is done in the docker-compose file](../../docker-compose.yml).
@@ -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;
@@ -0,0 +1 @@
../../test.hurl